vuejs渲染函数渲染复杂HTML,关于Vue渲染函数的一些总结

最近遍历 Vue核心库的文档,看到渲染函数这章的时候,突然感觉眼前一亮。为什么这么说?因为从此刻开始Vue对于我们初学者来说开始由黑盒向灰盒转变了,我们见见可以开始看到Vue的一些本质的东西了。由于目前只是初步涉猎,先做一些基础总结,后期再补充。

为什么要学习Vue的渲染函数?

效率高。因为vue的模板最后还是要编译成渲染函数的。

代码简洁 用JS能完成的代码行数会比模板语言的函数多?起码大多数情况是要少的!。

效率高是因为vue的模板最后还是要编译成渲染函数的。为什么这么说,看下Vue的模板编译:

Document

var res = Vue.compile(`

I'm a template!

{{ message }}

No message.

`

);

new Vue({

data: {

msg: 'hello'

},

render: res.render,

staticRenderFns: res.staticRenderFns,

created() {

console.log(res);

}

})

1e21ea10b6e1

image.png

1e21ea10b6e1

image.png

可以看到,vue模板(html)被最后编译成了2部分,一部分是动态部分render, 另一部分被编译成了静态部分staticRenderFns,render和staticRenderFns中的每个元素都是return了一个函数,这个函数就是渲染函数。既然模板编译最终都会编译成渲染函数,那么直接用渲染函数构建组件不是比用模板效率更高么?

代码简洁, 这里引用官网的例子:

加入我们要生成如下的锚点

Hello world!

我们要注册一个对应的组件

Hello world!

然后在anchored-heading这个组件内部很可能会这样实现

//这边组件内部的其他代码省略

是不是代码有点冗长?然后我们用渲染函数重新实现下上面的例子:

//这个例子就是基于vuee/cli脚手架写的,这里注册了一个全局组件

Vue.component('anchored-heading', {

render(h) {

return h(

'h' + this.level,

this.$slots.default

);

},

props: {

level: {

default: 1

}

}

})

hello world

// @ is an alias to /src

export default {

data() {

return {

level: 2

}

}

}

是不是很简单?

下面我们来详细看下这个渲染函数

render(h) {

return h(

'h' + this.level, //HTML标签名, 必须

{}, //一个包含模板相关属性的数据对象,可选

this.$slots.default //子节点对象数组,该数组的元素都是h函数生成的对象,可选

);

}

就像上面写的那样渲染函数就是一个函数名为render的函数,该函数默认传入一个参数,该参数是一个用于创建虚拟节点(vnode)的方法h(Vue社区大家都命名该函数为h),接受3个参数,第一个参数接受HTML标签名,字符串类型,必须传入;第二个参数是一个包含模板相关属性的数据对象,可选传入;第三个参数是一个子节点对象数组,该数组的元素都是h函数生成的对象,可选传入。

具体看下这个数据对象(照搬官网)

有一点要注意:正如在模板语法中,v-bind:class 和 v-bind:style,会被特别对待一样,在 VNode 数据对象中,下列属性名是级别最高的字段。该对象也允许你绑定普通的 HTML 特性,就像 DOM 属性一样,比如 innerHTML (这会取代 v-html 指令)。

{

// 和`v-bind:class`一样的 API

// 接收一个字符串、对象或字符串和对象组成的数组

'class': {

foo: true,

bar: false

},

// 和`v-bind:style`一样的 API

// 接收一个字符串、对象或对象组成的数组

style: {

color: 'red',

fontSize: '14px'

},

// 普通的 HTML 特性

attrs: {

id: 'foo'

},

// 组件 props

props: {

myProp: 'bar'

},

// DOM 属性

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 }

scopedSlots: {

default: props => createElement('span', props.text)

},

// 如果组件是其他组件的子组件,需为插槽指定名称

slot: 'name-of-slot',

// 其他特殊顶层属性

key: 'myKey',

ref: 'myRef',

// 如果你在渲染函数中向多个元素都应用了相同的 ref 名,

// 那么 `$refs.myRef` 会变成一个数组。

refInFor: true

}

PS:上面说的h函数第三个参数中,子节点必须是唯一的,比如像下面这样创建组件是无效的

render: function (createElement) {

var myParagraphVNode = createElement('p', 'hi')

return createElement('div', [

// 错误-重复的 VNodes

myParagraphVNode, myParagraphVNode

])

}

其他相关概念

虚拟节点(vnode): 一个用于描述实际DOM对象的js对象,Vue就是值h函数返回的对象。

虚拟DOM(vnode树):由虚拟节点构成的虚拟节点树称.

【完】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值