第二十七节:Vue渲染函数Render

源码 2024-9-29 18:12:55 52 0 来自 中国
媒介:

通过前面的学习,我们已经知道了在vue中,怎样利用template模板编写组件,但是利用模板并不是唯一能让vue知道应该在页面表现什么内容的方法,那接下来看看其他的方式
Render 函数是 Vue2.x 新增的一个函数、重要用来提拔节点的性能,它是基于 JavaScript 盘算。利用 Render 函数将 Template 里面的节点剖析成虚拟的 Dom 。
Vue 保举在绝大多数情况下利用模板来创建你的 HTML。然而在一些场景中,你真的须要 JavaScript 的完全编程的本事。这时你可以用渲染函数,它比模板更靠近编译器。
简而言之: 在 Vue 中利用模板 HTML 语法组建页面,利用 Render 函数是为了让我们用 Js 语言来构建 DOM。
原理: Vue框架的焦点是虚拟DOM,编译template模板时要转译成VNode的函数,当用render函数构建DOM时,Vue就免除了转译的步调。
1. render渲染函数基本相识

可以将一个函数转达给Vue 实例选项对象中render属性, 该函数会担当一个creatElement函数,可以利用它指定须要在页面上表现的内容,createElment 就是一个用来创建虚拟DOM(VNode)的函数
render这个方法有吸收参数,

  • 第一个标签参数为必填项, 范例可以为 Function(createElement ),
    render返回值是VNode(虚拟节点),范例可以是String 、Array。
2. createElement 用法

createElement函数担当三个参数

  • 第一个参数: 是天生在页面上表现的标签元素(必须参数)
  • 第二个参数: 是包含设置信息的数据对象(诸如HTML特性,属性,变乱侦听器已经要绑定的class和style)
  • 第三个参数: 是一个子节点字符串大概包含子节点的数组.
这里是 createElement 担当的参数:
// @returns {VNode}createElement(  // {String | Object | Function}  // 一个 HTML 标签名、组件选项对象,大概  // resolve 了上述任何一种的一个 async 函数。必填项。  'div',  // {Object}  // 一个与模板中 attribute 对应的数据对象。可选。  {    // (详情见下一节)  },  // {String | Array}  // 子级虚拟节点 (VNodes),由 `createElement()` 构建而成,  // 也可以利用字符串来天生“文本虚拟节点”。可选。  [    '先写一些笔墨',    createElement('h1', '一则头条'),    createElement(MyComponent, {      props: {        someProp: 'foobar'      }    })  ])那么接下来让我们好悦目看这几个参数
2.1 第一个参数{String | Object | Function}

第一个参数是一个必须的参数,这个参数可以是字符串string、对象object,大概一个函数function。
比如我们想创建一个标签,从前的写法是如许的
<div id="app"></div><script>    //  实例    const vm = new Vue({        el: "#app",        template:"<h2></h2>",    })</script>这是最基本的用法
那么我们怎样利用渲染函数来创建标签呢,
2.1.1 字符串:

第一个参数可以是标签名的字符串
<div id="app"></div><script>    const vm = new Vue({        el: "#app",        render:function(createElement){            return createElement("h2")        }    })</script>给createElement 传入了一个字符串参数h2, 我们就会发现页面上h2标签被渲染出来了
2.1.2 对象,

参数除了是字符串外,可以是组件的选项对象
<div id="app"></div><script>    //  组件选项对象    let MyComponent = {        template:"<h3>我就一个组件而已</h3>",    };    //  实例中注册组件    const vm = new Vue({        el: "#app",        render(createElement){            return createElement(MyComponent)        }    })</script>我们发现会直接表现组件的内容
2.1.3 函数:

着实第一个参数也可以是一个函数,只不外这个函数实行完毕后,须要返回一个标签名的字符串大概组件对象
<div id="app"></div><script>    //  实例中注册组件    const vm = new Vue({        el: "#app",        render(createElement){            let eleFn = function(){                return {                    template:"<div>Hello Vue!</div>"                }            }            return createElement(eleFn())        }    })</script>表现效果
3.png 2.2 第二个参数:{Object}

是一个可选参数,这个参数是一个Object。关于第一个参数创建的 标签的属性
{  // 与 `v-bind:class` 的 API 雷同,  // 担当一个字符串、对象或字符串和对象组成的数组  'class': {    foo: true,    bar: false  },  // 与 `v-bind:style` 的 API 雷同,  // 担当一个字符串、对象,或对象组成的数组  style: {    color: 'red',    fontSize: '14px'  },  // 平常的 HTML attribute  attrs: {    id: 'foo'  },  // 组件 prop  props: {    myProp: 'bar'  },  // DOM property  domProps: {    innerHTML: 'baz'  },  // 变乱监听器在 `on` 内,  // 但不再支持如 `v-on:keyup.enter` 如许的修饰器。  // 须要在处理惩罚函数中手动查抄 keyCode。  on: {    click: this.clickHandler  },  // 仅用于组件,用于监听原生变乱,而不是组件内部利用  // `vm.$emit` 触发的变乱。  nativeOn: {    click: this.nativeClickHandler  },  // 自界说指令。注意,你无法对 `binding` 中的 `oldValue`  // 赋值,由于 Vue 已经自动为你举行了同步。  directives: [    {      name: 'my-custom-directive',      value: '2',      expression: '1 + 1',      arg: 'foo',      modifiers: {        bar: true      }    }  ],  // 作用域插槽的格式为  // { name: props => VNode | Array<VNode> }  scopedSlots: {    default: props => createElement('span', props.text)  },  // 如果组件是别的组件的子组件,需为插槽指定名称  slot: 'name-of-slot',  // 别的特殊顶层 property  key: 'myKey',  ref: 'myRef',  // 如果你在渲染函数中给多个元素都应用了雷同的 ref 名,  // 那么 `$refs.myRef` 会酿成一个数组。  refInFor: true}//  class style的差别写法{    class:["class1",{"class2":true}],    style: {background: red}}请注意,class,style并没有在attrs属性中,他们是单独设置的,这是由于v-bind指令的特性,如果仅仅将class大概style设置在attrs对象中的一个属性,就不能将class和style设置为数组或是对象了,
示例:
const vm = new Vue({    el: "#app",    render: function (createElement) {        // 第一个参数是一个简单的HTML标具名符 “必选”        // 第二个参数是一个包含模板干系属性的数据对象 “可选”        return createElement('div', {            'class': {                foo: true,                bar: false            },            style: {                color: 'skyblue',                fontSize: '24px'            },            attrs: {                id: 'foo'            },            domProps: {                innerHTML: 'Hello Vue!'            }        })    }})终极天生的DOM,将会带一些属性和内容的div元素,如下图所示:
4.png 2.3 第三个参数: {String | Array}

这个参数是可选的,可以给其传一个String或Array处理惩罚子节点
2.3.1 字符串

当第三个参数为字符串是,就是节点的文本内容
<script>    const vm = new Vue({        el: "#app",        render:function(createElement){            return createElement("input", {                class:"title"            },"这是标题")        }    })</script>表现效果:
2.3.2 数组

数组中可以放多个节点,可以说是字符串的文本节点, 也可以是通过createElement创建的节点
<script>    const vm = new Vue({        el: "#app",        render(h){            return h("div",{                class:"box",            },[                h("span","我是一个span标签"),                h("input",{                    attrs:{                        type:"button",                        value:"按钮"                    }                })            ])        }    })</script>表现效果:
6.png 2.4 渲染函数简写

我们会发现每次写createElement会非常繁琐,以是我们可以给这个函数界说别名h
那么我们的代码就可以修改为
<div id="app"></div><script>    const vm = new Vue({        el: "#app",        render(h){            return h("input", {                class:"title"            },["这是标题"])        }    })</script>3. 束缚:

3.1 束缚的明白

组件树中的全部虚拟DOM(VNode)必须是唯一的,
比方,我想通过render函数实现下面的效果
我们大概会利用如下的方法
<div id="app"></div><script>    //  实例中注册组件    const vm = new Vue({        el:"#app",        data:{            msg:'hello'        },        render(h){            // 1\. 创建虚拟DOM 节点            let myVNode = h("p","hello");            // 2\. 返回终极的虚拟DOM            return h("div",[                myVNode,myVNode,myVNode,myVNode            ])        }    })</script>我们会发现固然可以实现效果, 也没有报错,但是不合法
那么我们应该怎样实现呢
3.2 建议利用的方法

利用数据map帮我们处理惩罚创建多个虚拟DOM
示例:
<script>    const vm = new Vue({        el:"#app",        data:{            msg:'hello'        },        render(h){            // 返回终极的虚拟DOM            return h("div",                     Array.apply(null,{length:4}).map(() => {                        return h("p","hello")                    })             )        }    })</script>如许创建的虚拟DOM就都是唯一的了
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:54, Processed in 0.153155 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表