博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue render深入窥探之谜
阅读量:6377 次
发布时间:2019-06-23

本文共 6119 字,大约阅读时间需要 20 分钟。

简介

在使用Vue进行开发的时候,大多数情况下都是使用template进行开发,使用template简单、方便、快捷,可是有时候需要特殊的场景使用template就不是很适合。因此为了很好使用render函数,我决定深入窥探一下。各位看官如果觉得下面写的有不正确之处还望看官指出,你们与我的互动就是写作的最大动力。

场景

官网描述的场景当我们开始写一个通过 level prop 动态生成 heading 标签的组件,你可能很快想到这样实现:

Vue.component('anchored-heading', {  template: '#anchored-heading-template',  props: {    level: {      type: Number,      required: true    }  }})

在这种场景中使用 template 并不是最好的选择:首先代码冗长,为了在不同级别的标题中插入锚点元素,我们需要重复地使用 <slot></slot>。

虽然模板在大多数组件中都非常好用,但是在这里它就不是很简洁的了。那么,我们来尝试使用 render 函数重写上面的例子:

Vue.component('anchored-heading', {  render: function (createElement) {    return createElement(      'h' + this.level,   // tag name 标签名称      this.$slots.default // 子组件中的阵列    )  },  props: {    level: {      type: Number,      required: true    }  }})

简单清晰很多!简单来说,这样代码精简很多,但是需要非常熟悉 Vue 的实例属性。在这个例子中,你需要知道当你不使用 slot 属性向组件中传递内容时,比如 anchored-heading 中的 Hello world!,这些子元素被存储在组件实例中的 $slots.default中。

createElement参数介绍

接下来你需要熟悉的是如何在 createElement 函数中生成模板。这里是 createElement 接受的参数:

createElement(  // {String | Object | Function}  // 一个 HTML 标签字符串,组件选项对象,或者  // 解析上述任何一种的一个 async 异步函数,必要参数。  'div',  // {Object}  // 一个包含模板相关属性的数据对象  // 这样,您可以在 template 中使用这些属性。可选参数。  {    // (详情见下一节)  },  // {String | Array}  // 子节点 (VNodes),由 `createElement()` 构建而成,  // 或使用字符串来生成“文本节点”。可选参数。  [    '先写一些文字',    createElement('h1', '一则头条'),    createElement(MyComponent, {      props: {        someProp: 'foobar'      }    })  ])

深入 data 对象

有一件事要注意:正如在模板语法中,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      }    }  ],  // Scoped slots in the form of  // { name: props => VNode | Array
} scopedSlots: { default: props => createElement('span', props.text) }, // 如果组件是其他组件的子组件,需为插槽指定名称 slot: 'name-of-slot', // 其他特殊顶层属性 key: 'myKey', ref: 'myRef'}

条件渲染

既然熟读以上api接下来咱们就来点实战。

之前这样写

//HTML
我被你发现啦!!!
//js//组件形式 Vue.component('vv-isshow', { props:['show'], template:'
我被你发现啦2!!!
',});var vm = new Vue({ el: "#app", data: { isShow:true }});

render这样写

//HTML
我被你发现啦3!!!
//js//组件形式 Vue.component('vv-isshow', { props:{ show:{ type: Boolean, default: true } }, render:function(h){ if(this.show ) return h('div',this.$slots.default); },});var vm = new Vue({ el: "#app", data: { isShow:true }});

列表渲染

之前是这样写的,而且v-for 时template内必须被一个标签包裹

//HTML
//js//组件形式 Vue.component('vv-aside', { props:['list'], methods:{ handelClick(item){ console.log(item); } }, template:'
\
{
{item.txt}}
\
', //template:'
{
{item.txt}}
',错误 });var vm = new Vue({ el: "#app", data: { list: [{ id: 1, txt: 'javaScript', odd: true }, { id: 2, txt: 'Vue', odd: false }, { id: 3, txt: 'React', odd: true }] }});

render这样写

//HTML
//js//侧边栏Vue.component('vv-aside', { render: function(h) { var _this = this, ayy = this.list.map((v) => { return h('div', { 'class': { odd: v.odd }, attrs: { title: v.txt }, on: { click: function() { return _this.handelClick(v); } } }, v.txt); }); return h('div', ayy); }, props: { list: { type: Array, default: () => { return this.list || []; } } }, methods: { handelClick: function(item) { console.log(item, "item"); } }});var vm = new Vue({ el: "#app", data: { list: [{ id: 1, txt: 'javaScript', odd: true }, { id: 2, txt: 'Vue', odd: false }, { id: 3, txt: 'React', odd: true }] }});

v-model

之前的写法

//HTML
//js//inputVue.component('vv-models', { props: ['txt'], template: '
\

看官你输入的是:{

{txtcout}}

\
\
', computed: { txtcout:{ get(){ return this.txt; }, set(val){ this.$emit('input', val); } } }});var vm = new Vue({ el: "#app", data: { txt: '', }});

render这样写

//HTML
//js//inputVue.component('vv-models', { props: { txt: { type: String, default: '' } }, render: function(h) { var self=this; return h('div',[h('p','你猜我输入的是啥:'+this.txt),h('input',{ on:{ input(event){ self.$emit('input', event.target.value); } } })] ); },});var vm = new Vue({ el: "#app", data: { txt: '', }});

总结

render函数使用的是JavaScript 的完全编程的能力,在性能上是占用绝对的优势,小编只是对它进行剖析。至于实际项目你选择那种方式进行渲染依旧需要根据你的项目以及实际情况而定。

转载地址:http://hyxqa.baihongyu.com/

你可能感兴趣的文章
ROS 2编写包并用colcon编译
查看>>
gitlab重置root的密码
查看>>
关于C/C++中,对static关键字的理解
查看>>
Tomcat 5常用优化和配置
查看>>
几个性能测试工具
查看>>
(转)丰田公司精益管理的14项原则- [Lean and Agile]
查看>>
开发进度——2
查看>>
Java基础语法之Java初识
查看>>
Java Socket编程基础知识
查看>>
jenkins忘记管理员账号密码的补救方法-转
查看>>
jQuery基础三
查看>>
已Access为支持,书写一个C#写入的记录的方案
查看>>
JavaScript自适应调整文字大小
查看>>
实验报告一:网络侦查与网络扫描
查看>>
.net 接入微信商户企业支付API 问题总结
查看>>
防止SQL注入
查看>>
java中的动态代理(三)
查看>>
Ue4的UE_LOG
查看>>
自绘制HT For Web ComboBox下拉框组件
查看>>
基于 HTML5 WebGL 的低碳工业园区监控系统
查看>>