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)


相关推荐

  • RS232接口定义

    RS232接口定义RS232接口定义RS232接口定义  RS-232C接口定义(9芯)针脚定义符号1载波检测DCD2接收数据RXD3发送数据TXD4数据终端准备好DTR5信号地SG6数据准备好DSR7请求发送RTS8清除发送CTS9振铃提示RIPin1Receiv

  • you are not allowed to_BlankBlood

    you are not allowed to_BlankBloodisNotEmpty:判断某字符串是否非空StringUtils.isNotEmpty(null)=falseStringUtils.isNotEmpty(“”)=falseStringUtils.isNotEmpty(“”)=trueStringUtils.isNotEmpty(“bob”)=trueisNotBlank:判断某字符串是否不为空且长度不为0且不

  • windows各版本序列号集合

    windows各版本序列号集合因经常使用,避免每次都上网到处找,在此做了集合(不定期更新)windows2003R2Sp264位企业版MR78C-GF2CY-KC864-DTG74-VMT73windows2003R232位企业版JCDPY-8M2V9-BR862-KH9XB-HJ3HMwindows764位旗舰版使用激活工具,附件1,出处:http://www.xpg…

  • elasticsearch数据库搭建 linux版

    elasticsearch数据库搭建 linux版介绍Elasticsearch是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎ApacheLucene(TM)基础上的搜索引擎.当然Elasticsearch并不仅仅是Lucene那么简单,它不仅包括了全文搜索功能,还可以进行以下工作:分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。 实时分析的分布式搜索引擎。 可以扩展到上百台服务器,处理P…

  • 网页跳转qq聊天代码_html全屏代码

    网页跳转qq聊天代码_html全屏代码偶尔从某地得到我去看了看,果然可以但是又想了想他是怎么样和TENCENT数据库连接的呢?呵呵~自己做一个吧!原代码如下,自己有PHP空间的话,你也可以提供QQ在线的js代码服务了!连接代码把下面的代码保存成PHP文件就可以了!我想他也是连接别人的数据吧~那我也连接一下他的http://www.gaodaima.com/45503.html让你拥有自己的QQ在线显示代码(又是转_php$file=f…

    2022年10月17日
  • shell编程和shell脚本_shell脚本语言入门pdf

    shell编程和shell脚本_shell脚本语言入门pdf看了一遍,小有问题,但是可以览个大概了。 Shell编程基础http://wiki.ubuntu.org.cn/Shell%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80

发表回复

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

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