render 函数是什么
平常我们写 <template>
里面所使用模板HTML语法组建页面的,其实在 vue
中都会编译成 render
函数,因为vue
中采用的是 虚拟DOM
所以拿到template模板时也要转译成 VNode
(virtual node 虚拟节点) 函数
插一嘴 虚拟DOM
与 真实DOM
的区别
虚拟DOM
不会进行排版与重绘操作 ,虚拟DOM
就是把真实DOM
转换为Javascript
代码,并且真实DOM
频繁操作排版、重绘效率相比虚拟DOM
效率会低很多,比如原生操作真实DOM浏览器会从构建DOM树
开始从头到尾执行一遍流程。而虚拟DOM
是用Object
来代表一颗节点,这个Object
叫做VNode
,然后使用两个VNode
进行对比,根据对比后的结果修改真实DOM
。
浏览器渲染引擎工作流程
虚拟DOM
与VNode
又涉及到diff
算法,所以我们先暂停这里,开始我们的正文,当然有兴趣的小伙伴们可以去查阅相关资料
每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样,每个节点都可以有孩子节点 (也就是说每个部分可以包含其它的一些部分)。
高效地更新所有这些节点会是比较困难的,不过所幸你不必手动完成这个工作。你只需要告诉 Vue 你希望页面上的 HTML 是什么,这可以是在一个模板里:
<h1>{{ blogTitle }}</h1>
或者一个渲染函数里:
render: function (createElement) { return createElement('h1', this.blogTitle) }
在这两种情况下,Vue 都会自动保持页面的更新,即便 blogTitle
发生了改变。
render 函数的使用
先看看我们平常vue中的写法
<template> <div> <h1>严老湿</h1> </div> </template>
如果使用render函数将是怎样呢?
<script> export default { render(createElement){ // createElement: // 第一个参数是标签名类型必须是String // 第二个是属性值 我们后面来讲,类型是Object // 第三个是子级虚拟节点 (VNodes) 可以是String|Array return createElement('h1',{},"严老湿") } } </script>
这样我们也是一样的可以实现 template 中的元素
动态接收参数
修改以下上面的代码,我们再来试试
<script> export default { props:{ tag:{ type:String, required: true } }, render(createElement){ return createElement(this.tag,{},"严老湿") } } </script>
在父组件中传值给子组件动态切换标签
<sub-components tag="button"></sub-components>
原来可以这样操作,那我们在玩点其他的呗
<script> export default { props: { tag: { type: String, required: true, }, data: { type: Array, required:true }, }, render(createElement) { return createElement(this.tag, {}, // 嵌套到 this.tag 元素上 this.data.map(item=> createElement('li',{},item.toString()) ) ); }, }; </script>
父组件传值
<sub-components tag="ul" :data="data"></sub-components> data:["新冠病毒灭活疫苗首次亮相","辽宁副省长卢柯拿下科学大奖","阚清子说朱一龙神秘"]
createElement 的属性
我们刚刚使用了createElement
的第一个和第三个参数
现在来看看第二个参数,为什么拿到后面来讲了,因为里面的东西比较多
嗯?重头戏么
接着来看看就知道啦
class
<script> export default { props: { tag: { type: String, required: true, }, data: { type: Array, required:true }, }, render(createElement) { return createElement(this.tag, {}, this.data.map(item=> createElement('li',{ // 首先上场的是class class:'child-element' // or // domProps: {className: "child-element"}, },item.toString()) ) ); }, }; </script>
我们给li
标签加上了class之后,可以直接在元素上看到 child-element
,然后想修改样式的呢,直接通过选择器修改就好了,这就不用多说了吧!
on
再来看看事件系列
<script> export default { props: { tag: { type: String, required: true, }, data: { type: Array, required:true }, }, render(createElement) { return createElement(this.tag, {}, this.data.map(item=> createElement('li',{ domProps: { className: "child-element" }, // 在on中我们可以写需要的事件 on:{ // 点击事件 点击打印 Pointer Event click:(e)=>{ console.log(e) }, // mouseover // mouseout } },item.toString()) ) ); }, }; </script>
打印结果:
里面还有很多好玩的东西可以去看看 vue2.0
官方文档
如 :style
、 attrs
、directives
等等....
vue组件
如果看过 render 源码的同学应该知道,我们刚刚所说的第一个参数 tag
不仅仅可以是标准的html标签。tag
可以分为正常html标签 | vue组件 两类 。之前已经学了html标签,接下来 我们来看看vue组件
首先我们新建一个 vue 组件
<template> <div> {{content}} </div> </template> <script> export default { props:{ content:{ type:String } } } </script>
在render函数页面中引入
<script> // 引入组件 import Widget from './Widget' export default { render(createElement) { // 传入组件 return createElement(Widget, { // 传值 content props:{ content:"hello CrazyYan" } }); }, }; </script>
ok 返回到页面上,我们已经看到了组件
我们学到这里,应该知道
- render函数的作用
- 它的简单使用方法
- 几个参数的作用