render属性
-
字符串模板的代替方案,接收一个createElement方法作为第一个参数用来创建VNode,如果组件是一个函数组件,渲染函数还会接收一个额外的context参数,为没有实例的函数组件提供上下文信息(createElement方法可以通过Vue实例中的
$
createElement()获得 --> const h = this.$createElement())
注意:Vue选项中render函数弱存在,则Vue构造函数不会从template选项或通过el选项指定的挂载元素中提取出的HTML模板编译渲染函数 -
渲染函数中使用插槽
- this.$slots访问静态插槽的内容(即使得组件能够使用插槽),每个插槽都是一个VNode数组
render: function (createElement) { // `<div><slot></slot></div>` return createElement('div', this.$slots.default) }
- this.$scopedSlots访问作用域插槽,每个作用域插槽都是一个返回若干VNode的函数
props: ['message'], render: function (createElement) { // `<div><slot :text="message"></slot></div>` return createElement('div', [ this.$scopedSlots.default({ text: this.message }) ]) }
- 如果要用渲染函数想子组件中传递作用域插槽(使用子组件的作用域插槽),可以利用VNode数据对象中的scopedSlots字段
render: function (createElement) { // `<div><child v-slot="props"><span>{ { props.text }}</span></child></div>` return createElement('div', [ createElement('child', { // 在数据对象中传递 `scopedSlots` // 格式为 { name: props => VNode | Array<VNode> } scopedSlots: { default: function (props) { return createElement('span', props.text) } } }) ]) }
-
数据对象(createElement第二个(可选)参数)
{ // 接受一个字符串、对象或字符串和对象组成的数组 'class': { foo: true, bar: false, }, // 接受一个字符串、对象,或对象组成的数组 style: { color: 'red', fontSize: '14px' }, // HTML元素属性 attrs: { id: 'foo' }, // 组件prop props: { myProp: 'bar' } // DOM的属性 (innerHTML、textContent、style、value等) domProps: { innerHTML: 'baz' }, // 事件监听 on: { click: this.clickHandler }, // 仅用于组件,用于监听原生事件,而不是组件内部使用 // `vm.$emit` 触发的事件。 nativeOn: { click: this.nativeClickHandler }, // 作用域插槽的格式为 // { name: props => VNode | Array<VNode> } scopedSlots: { default: props => createElement('span', props.text) }, // 如果此组件是其它组件的子组件,需为插槽指定名称 slot: 'name-of-slot', key: 'myKey', ref: 'myRef', }
-
渲染函数中实现v-model
Vue.component("inp", {
props: ["value"],
render(createElement: Function) {
let that = this;
return createElement("div", {
}, [
createElement(
"input",
{
attrs: {
value: that.value
},
on: {
input: function(e: any) {
that.$emit("input", e.target.value);
}
}
},
),
createElement("div", that.value)
]);
}
});
<!-- 使用 -->
<inp :value="val" @input="newVal=>val=newVal"></inp>
函数式组件
- 组件比较简单,没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法,实际上它只是接收一些porp。在这样的场景下,可以将组件标记为functional,这意味着它无状态(没有响应式数据),也没有实例(this上下文)
Vue.component('hello-world',{
functional:true,
props:{
// ...
},
// 为了弥补缺少的实例,提供了第二个参数contxt作为上下文
render:function( createElement, context ){
// ...
}
})
- context参数属性
props:提供所有prop的对象
children:VNode子节点的数组
slots:一个函数,返回了包含所有插槽的对象
scopedSlots:一个暴露传入的作用域插槽的对象,也以函数形式暴露普通插槽
data: 传递给组件的整个数据对象
parent:对父组件的引用
listeners:一个包含了所有父组件为当前组件注册的事件监听的对象,是data.on的一个别名
injections:如果使用了inject选项,则该对象包含了应当被注入的property
renderError
当render函数遭遇错误时,提供另外一种渲染输出。其错误将会作为第二个参数传递到renderError
new Vue({
render (h) {
throw new Error('oops')
},
renderError (h, err) {
return h('pre', {
style: {
color: 'red' }}, err.stack)
}
}).$mount('#app')