vue的render函数用法[通俗易懂]

vue的render函数用法[通俗易懂]1.render简介前面我们的组件的模板都是在模板里写的(template),模板最后都会被vue编译成virtualdom(虚拟dom),在某些情况下模板可能不好用,例如需要实现一个动态的文章标题,根据父组件的level属性,动态的渲染成h1~hx标签,用模板写部分代码如下。<article-header:level=”1″>Helloworld</article-h…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

1.render简介

前面我们的组件的模板都是在模板里写的(template),模板最后都会被vue编译成virtual dom(虚拟dom),在某些情况下模板可能不好用,例如需要实现一个动态的文章标题,根据父组件的level属性,动态的渲染成h1~hx标签,用模板写部分代码如下。

<article-header :level="1">Hello world</article-header>
<script type="text/x-template" id="article-header-template"> <h1 v-if="level === 1"> <slot></slot> </h1> <h2 v-else-if="level === 2"> <slot></slot> </h2> <h3 v-else-if="level === 3"> <slot></slot> </h3> <h4 v-else-if="level === 4"> <slot></slot> </h4> <h5 v-else-if="level === 5"> <slot></slot> </h5> <h6 v-else-if="level === 6"> <slot></slot> </h6> </script>
<script> Vue.component('article-header', { 
     template: '#article-header-template', props: { 
     level: { 
     type: Number, required: true } } }) </script>

Jetbrains全家桶1年46,售后保障稳定

代码写的很死板,不灵活。这时候使用render函数会变得非常的方便。改写如下

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		
		
		<div id="app">
			
			<article-title :level="level">
				hello world
			</title>
		</div>
		
		
		<script> Vue.component("article-title", { 
     render:function(createElement){ 
     return createElement( 'h'+this.level, { 
     style:{ 
     color:'red' } }, this.$slots.default) }, props:{ 
     level:{ 
     type:Number, required:true } }, data:function(){ 
     return { 
     } } }); var app11 = new Vue({ 
     el:'#app', data:{ 
     level:1 } }) </script>
	</body>
</html>

2. createElement

其实render函数返回的createElement就是一个虚拟dom,来看下广告对createElement参数描述

// @returns {VNode}
createElement(
// {String | Object | Function}
// 一个 HTML 标签名、组件选项对象,或者
// resolve 了上述任何一种的一个 async 函数。必填项。
'div',
// {Object}
// 一个与模板中属性对应的数据对象。可选。
{ 

// 与 `v-bind:class` 的 API 相同,
// 接受一个字符串、对象或字符串和对象组成的数组
'class': { 

foo: true,
bar: false
},
// 与 `v-bind:style` 的 API 相同,
// 接受一个字符串、对象,或对象组成的数组
style: { 

color: 'red',
fontSize: '14px'
},
// 普通的 HTML 特性
attrs: { 

id: 'foo'
},
// 组件 prop
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<VNode> }
scopedSlots: { 

default: props => createElement('span', props.text)
},
// 如果组件是其它组件的子组件,需为插槽指定名称
slot: 'name-of-slot',
// 其它特殊顶层属性
key: 'myKey',
ref: 'myRef',
// 如果你在渲染函数中给多个元素都应用了相同的 ref 名,
// 那么 `$refs.myRef` 会变成一个数组。
refInFor: true
},
// {String | Array}
// 子级虚拟节点 (VNodes),由 `createElement()` 构建而成,
// 也可以使用字符串来生成“文本虚拟节点”。可选。
[
'先写一些文字',
createElement('h1', '一则头条'),
createElement(MyComponent, { 

props: { 

someProp: 'foobar'
}
})
]
)

render函数内返回的createElement函数的第一个参数必填,一般是标签名,第二个参数,数据对象可选参数,第三个为子级虚拟节点。

3.约束

所有组件树中,如果VNode是组件或含有组件的slot,那么Vnode必须唯一,例如。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id='app'>
<ele></ele>
<div>
<script> var Child = { 
 render: function (createElement) { 
 return createElement("p", "text"); } }; Vue.component("ele", { 
 render: function (createElement) { 
 var ChildNode = createElement(Child); return createElement("div", [ ChildNode , ChildNode ]); } }) var app11 = new Vue({ 
 el:'#app', data:{ 
 } }) </script>
</body>
</html>

简单的渲染看上去没问题,但是如果使用中涉及到其他复杂的特性,就可能会出问题,
正确的渲染多个重复的组件

Vue.component("ele", { 

render: function(createElement) { 

return createElement("div",
Array.apply(null, { 

length: 20
}).map(function() { 

return createElement(child);
})
)
}
});

使用javascript代替某些模板指令,向v-if,v-for,v-model等指令在render函数中都无法使用,都需要自己用js实现相同的逻辑,这就是深入底层的代价。
例如

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id='app'>
<ele :type="type" :len="len"></ele>
</div>
<script> var child = { 
 render: function(createElement) { 
 return createElement("p", "text"); } }; Vue.component("ele", { 
 render: function(createElement) { 
 if(this.type == 1){ 
 return createElement("div", Array.apply(null, { 
 length: this.len }).map(function() { 
 return createElement("p","one type"); }) ); }else{ 
 return createElement("div", Array.apply(null, { 
 length: this.len }).map(function() { 
 return createElement("p","two type"); }) ) } }, props:{ 
 type:{ 
 type:Number, required:true, default:1 }, len:{ 
 type:Number, required:true, default:5 } } }); var app11 = new Vue({ 
 el: '#app', data: { 
 type:2, len:6 } }) </script>
</body>
</html>

4. 在render函数中使用插槽

在render函数内,在父组件定义的插槽也是一个vnode,在render中可以通过this.$slots.插槽名去访问。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<article-title>
<template v-slot:default>
hello world
</template>
<template v-slot:nameslot="nameslot">
hello {
{nameslot.name}}
</template>
</title>
</div>
<script> var child = { 
 render: function(createElement) { 
 return createElement('p', 'hello'); } } Vue.component("article-title", { 
 render: function(createElement) { 
 var node = createElement(child); return createElement( 'div', [node, this.$slots.default, //向作用域插槽传值 createElement('div', [ this.$scopedSlots.nameslot({ 
 name: 'ly' }) ]) ]) }, props: { 
 }, data: function() { 
 return { 
 } } }); var app11 = new Vue({ 
 el: '#app', data: { 
 } }) </script>
</body>
</html>

如果要用渲染函数向子组件中传递作用域插槽,可以利用 VNode 数据对象中的 scopedSlots 字段。

5.函数式组件

函数式组件是无状态的,无实例(没有this),入参是渲染上下文context,一切的参数都通过,context传递

属性名 作用
props 提供所有 prop 的对象
children VNode 子节点的数组
slots 一个函数,返回了包含所有插槽的对象
scopedSlots (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通
data 传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
parent 对父组件的引用
listeners (2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
injections (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性

组件定义时,有个functional属性设置为true就表示当前组件是一个函数式组件,render函数新增context上下文,属性如上表,返回的对象。获取默认插槽由this.$slots.default改为了context.children,context.children会返回所有子元素。
也可以用slots().default获取默认插槽,

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<article-title :level="level">
hello world
</title>
</div>
<script> Vue.component("article-title", { 
 functional:true, render:function(createElement,context){ 
 var props = context.props; return createElement( 'h'+props.level, context.data, context.children) }, props:{ 
 level:{ 
 type:Number, required:true } }, data:function(){ 
 return { 
 } } }); var app11 = new Vue({ 
 el:'#app', data:{ 
 level:1 } }) </script>
</body>
</html>

参考
https://cn.vuejs.org/v2/guide/render-function.html#slots-和-children-对比

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/230939.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • php隐式转换,隐式转换如何使用?总结隐式转换实例用法「建议收藏」

    php隐式转换,隐式转换如何使用?总结隐式转换实例用法「建议收藏」JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object。object是引用类型,其它的五种是基本类型或者是原始类型。我们可以用typeof方法打印来某个是属于哪个类型的。不同类型的变量比较要先转类型,叫做类型转换,类型转换也叫隐式转换。隐式转换通常发生在运算符加减乘除,等于,还有小于,大于等。。typeof’11’…

    2022年10月11日
  • 2019年最新PHP面试题

    2019年最新PHP面试题

  • python处理xps文件_xps/pdf/png/json转换

    python处理xps文件_xps/pdf/png/json转换问题11.如何移植最新版本的pdf.js到pdf2json库中来2.如何实现坐标换算参考源码x/px=PDFUnit.toPixelX(x+0.25)y/px=PDFUnit.toPixelY(x+0.75)w/px=PDFUnit.toFixedFloat(maxWidth),Theunitforallwidth,height,length,etc,isin”…

  • 滚动条的颜色_Java滚动条里面怎么添加控件

    滚动条的颜色_Java滚动条里面怎么添加控件对里面样式的介绍:语法:scrollbar-face-color:color参数:color: 指定颜色。说明:设置或检索滚动条3D表面(ThreedFace)的颜色。(演示)语法:scrollbar-highlight-color:color参数:color: 指定颜色。说明:设置或检索滚动条3D界面的亮边(ThreedHighlight)颜色。(演示)语法:scrollbar-arro…

    2022年10月23日
  • console.log详解

    console.log详解console.log方法用于在控制台输出信息。它可以接受一个或多个参数,将它们连接起来输出。console.log(‘HelloWorld’)//HelloWorldconsole.log(‘a’,’b’,’c’)//abcconsole.log方法会自动在每次输出的结尾,添加换行符。console.log(1);console.log(2);conso…

  • 【matlab】常用函数importdata

    importdata没有头文件并且全是数字用load,有头文件并且数据类型统一用importdata。查看帮助用helploadhelpimportdatadata.txt内容如下:a1a2a3b1b2b3123444656测试代码:delimiterIn=”;%字符分隔符headerlinesIn=2;%文件头的行数A=

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号