首页 > 编程笔记 > JavaScript笔记
阅读:180
Vue render渲染函数和JSX的用法
通常情况下,Vue.js 推荐使用 template 定义视图内容(html),然而有时使用渲染函数生成视图内容要方便得多。
用 template 定义一个子组件,用
在上面的案例中,createElement('h'+this.level,this.$slots.default)执行的结果,也是创建一个 h 的节点对象,只是这个对象不是原汁原味的 DOM 节点,而是 Vue.js 中的节点描述对象,包含所有描述信息,以便 Vue.js 将其渲染到页面。这种节点,通常称为虚拟节点(Virtual Node),简称为 VNode。虚拟 DOM 是在 Vue.js 里面对所有 Vue.js 组件数的总称。
关于第 2 个参数,经常又称为数据对象,里面包含的是组件属性对象对应的数据,代码如下:
特别要注意的是,在 Vue.js 组件树中,VNode 是唯一的。如下代码是不正确的,因为在渲染出来的对象里面有两个一样的 VNode 对象,代码如下:
用 template 定义一个子组件,用
h n显示插槽里面的内容,代码如下:<!-- 定义 Vue.js 的视图 --> <div id="app"> <sub-component :level="1"> Hello </sub-component> <sub-component :level="2"> Hello </sub-component> <sub-component :level="4"> Hello </sub-component> </div> <script type="text/JavaScript"> const SubComponent = { // template定义视图 template: '<div> <h1 v-if="level === 1"><slot></slot></h1> <h2 v-else-if="level === 2"><slot></slot></h2> <h3 v-else><slot></slot></h3> </div>', props: { level: { type: Number, required: true } } }; // 创建 Vue.js 对象 const vm = new Vue({ el: "#app", components: { SubComponent } }); </script>在 template 里面,用 v-if 根据 level 的不同值,渲染不同的 h,如果代码量太大,则可改成渲染函数生成子组件的 html,代码如下:
<!-- 定义 Vue.js 的视图 -->
<div id="app">
<sub-component :level="1"> Hello </sub-component>
<sub-component :level="2"> Hello </sub-component>
<sub-component :level="4"> Hello </sub-component>
</div>
<script type="text/JavaScript">
const SubComponent = {
// 用render()函数渲染视图的HTML
render: function(createElement) {
return createElement(
'h' + this.level,
this.$slots.default
)
},
props: {
level: {
type: Number,
required: true
}
}
}
// 创建Vue.js对象
const vm = new Vue({
el: "#app",
components: {
SubComponent
}
})
</script>
这种情况下,渲染函数的使用要比 template 实现方便很多。虚拟DOM
浏览器接收到 html 页面后,会先将页面内容解析成树形结构,保存在内存中,再显示到页面上。每个元素是一个独立的节点对象,文本也是。在上面的案例中,createElement('h'+this.level,this.$slots.default)执行的结果,也是创建一个 h 的节点对象,只是这个对象不是原汁原味的 DOM 节点,而是 Vue.js 中的节点描述对象,包含所有描述信息,以便 Vue.js 将其渲染到页面。这种节点,通常称为虚拟节点(Virtual Node),简称为 VNode。虚拟 DOM 是在 Vue.js 里面对所有 Vue.js 组件数的总称。
createElement参数
createElement 的语法是:
createElement({String|Object|function},{Object},{String, Array})
带 3 个参数:
- 第 1 个参数可以是 String|Object|Function 类型,必选,可以是 html 元素名称、组件选项对象或者分解成 String 或 Object 的任何一种异步函数。
- 第 2 个参数是 Object 类型,可选,同模板中的属性对象对应的数据对象。
- 第 3 个参数可以是 String|Array 类型,可选,可以是虚拟节点的子文本节点,或者其他子虚拟节点。
关于第 2 个参数,经常又称为数据对象,里面包含的是组件属性对象对应的数据,代码如下:
// 与 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.js 已经自动进行了同步
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
}
特别要注意的是,在 Vue.js 组件树中,VNode 是唯一的。如下代码是不正确的,因为在渲染出来的对象里面有两个一样的 VNode 对象,代码如下:
render: function (createElement) {
var myParagraphVNode = createElement('p', 'hi')
return createElement('div',
// 错误,重复的VNode
myParagraphVNode, myParagraphVNode
)
}
ICP备案:
公安联网备案: