哪些网站动效做的不错,wordpress不兼容ie,设计师网民,个人网站建设价格表1.render函数
在编写vue单文件的大多数情况下#xff0c;我们都是使用template模板来创建HTML。然而在一些条件判断比较复杂的场景下#xff0c;使用JavaScript去描绘HTML的生成逻辑会显得更加的简洁直观。
使用Vue官网的例子来简单说明#xff1a;
如果自己在开发的时候… 1.render函数
在编写vue单文件的大多数情况下我们都是使用template模板来创建HTML。然而在一些条件判断比较复杂的场景下使用JavaScript去描绘HTML的生成逻辑会显得更加的简洁直观。
使用Vue官网的例子来简单说明
如果自己在开发的时候编写的每个标题包括h1~h6都需要带锚点如下所示
h1a namehello-world href#hello-worldHello world!/a
/h1如果用template模板进行编写会如下所示
templateh1 v-iflevel 1anchor :namename :contentcontent/anchor/h1h2 v-else-iflevel 2anchor :namename :contentcontent/anchor/h2h3 v-else-iflevel 3anchor :namename :contentcontent/anchor/h3h4 v-else-iflevel 4anchor :namename :contentcontent/anchor/h4h5 v-else-iflevel 5anchor :namename :contentcontent/anchor/h5h6 v-else-iflevel 6anchor :namename :contentcontent/anchor/h6
/template
script
export default {name:anchor-header,props:{level:Number,name:String,content:String},components:{anchor:{props:{content:String,name:String},template:a :idname :href#${name} {{content}}/a}}
}
/script
显然代码冗长累赘。但如果用render函数来编写则如下所示
script
export default {name:anchor-header,props:{level:Number,name:String,content:String},render:function(createElement){const anchor{props:{content:String,name:String},template:a :idname :href#${name} {{content}}/a}const anchorElcreateElement(anchor,{props:{content:this.content,name:this.name}})const elcreateElement(h${this.level},[anchorEl])return el}
}
/script
可见通过render函数编写出的逻辑更加简洁且可读性更高。
每一个render函数都要return一个VNode类型的变量是Vue中自定义的虚拟节点(virtual node)用于替换挂载元素$el。 Vue 选项中的 render 函数若存在则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。 但自己实践在vue单文件实践后发现如果同时存在template和render生成的html会以template的逻辑为主奇怪。
上述例子的代码可以知道render函数使用的场景是要根据不同条件切换不同HTML标签可以使用render函数。或者条件判断较多的template中用渲染函数编写会让代码的可读性更高的情况下也推荐使用render函数。
下面分析上面代码中出现的createElement函数。
2.createElement
createElement用于创建且return一个VNode类型的变量虚拟节点以下是该函数的传入参数
1一个 HTML 标签名、组件选项对象或者resolve前面两种之一类型的async函数。必填。
例如传入div表示想创建一个html标签为div的VNode如果传入transition代表创建transition组件。
上面作为粒子的代码就是根据传入的类型为Number的参数level用模板字符串拼接成标签名称。传入level为1则拼接出来的HTML标签名称为h1。代表要创建html标签为h1的VNode。
2所创建的VNode中所需参数为属性的数据对象。可选。
{class,style,attrs,props,domProps,on,nativeOn,directives:[{name,value,expression,arg,modifiers}],scopedSlots:{default:propscreateElement()},slot,key,ref,refInFor
}大部分属性和vue组件中存在的属性的作用一样我就只挑几个比较特殊的属性来说明
**nativeOn**用于监听原生事件而不是组件内使用。例如
nativeOn: {click: this.nativeClickHandler}相当于click.nativenativeClickHandler
scopedSlots定义作用域插槽的内部的内容
格式为{ name: props VNode | ArrayVNode }
举一个例子
script
export default {render (createElement) {var component {template: divslot/slotslot namefoo/slot/div}return createElement(component, {scopedSlots: {default: props createElement(span, 456),foo: props createElement(span, 789)},})}
}
/script最后渲染出来的html效果如下
divspan456/spanspan789/span
/divscope如果要生成的组件要插入到需为插槽指定名称。
举个例子
script
export default {render (createElement) {var component {template: divslot/slotslot namefoo/slot/div}const childrenEl createElement(span, { slot: foo }, 123)return createElement(component, {scopedSlots: {default: props createElement(span, 456)// foo: props createElement(span, 789) },}, [childrenEl])}
}
/script最后渲染出来的html效果如下
divspan456/spanspan123/span
/div注意如果去掉上面例子的代码中// foo: props createElement(span, 789)的注释则slotfoo插槽中显示内容依然为span789/span。
** refInFor**如果你在渲染函数中给多个元素都应用了相同的 ref 名那么 $refs.myRef 会变成一个数组。
3子级虚拟节点 (VNodes)。如果传入的是VNode则要用列Array传入另外也可以使用字符串来生成“文本虚拟节点”。可选。
3.函数式组件
函数式组件相比于一般的vue组件而言最大的区别是非响应式的。它不会监听任何数据也没有实例因此没有状态意味着不存在诸如createdmounted的生命周期。好处是因只是函数故渲染开销也低很多。
把开头的例子改成函数式组件代码如下
script
export default {name:anchor-header,functional:true, // 以functional:true声明该组件为函数式组件props:{level:Number,name:String,content:String},// 对于函数式组件render函数会额外传入一个context参数用来表示上下文即替代this。函数式组件没有实例故不存在thisrender:function(createElement,context){ const anchor{props:{content:String,name:String},template:a :idname :href#${name} {{content}}/a}const anchorElcreateElement(anchor,{props:{content:context.props.content, //通过context.props调用props传入的变量name:context.props.name}})const elcreateElement(h${context.props.level},[anchorEl])return el}
}
/script 渲染函数 JSX — Vue.js更多关于函数式组件内容请看官网函数式组件 4.element-ui的el-row组件
最后以el-row组件的源码来分析该源码的渲染逻辑在render函数上非常简洁明了
export default {name: ElRow,componentName: ElRow,props: {tag: {type: String,default: div},gutter: Number,type: String,justify: {type: String,default: start},align: {type: String,default: top}},computed: {style() {const ret {};if (this.gutter) {ret.marginLeft -${this.gutter / 2}px;ret.marginRight ret.marginLeft;}return ret;}},render(h) {return h(this.tag, {class: [el-row,this.justify ! start ? is-justify-${this.justify} : ,this.align ! top ? is-align-${this.align} : ,{ el-row--flex: this.type flex }],style: this.style}, this.$slots.default);}
};
对着el-row组件传入参数的说明图来解释
直接从render函数处进行分析
1.传入第一个参数为this.tag用于根据参数生成对应的html标签。
2.第二个参数中传入class和style是根据props中的type,gutter,justify,align生成的。
3.第三个参数传入子节点。此处通过this.$slots.default拿到传入的子节点。例如
el-rowdiv123/div
/el-row此时this.$slots.default 获取的数据则是一个包含上面div123/div的VNode的数组。
以下内容来自官网
拓展slots() 和 children 对比
你可能想知道为什么同时需要 slots() 和 children。slots().default 不是和 children 类似的吗在一些场景中是这样——但如果是如下的带有子节点的函数式组件呢
my-functional-componentp v-slot:foofirst/ppsecond/p
/my-functional-component对于这个组件children 会给你两个段落标签而 slots().default 只会传递第二个匿名段落标签slots().foo 会传递第一个具名段落标签。同时拥有 children 和 slots()因此你可以选择让组件感知某个插槽机制还是简单地通过传递 children移交给其它组件去处理。