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)


相关推荐

  • 块存储、文件存储、对象存储这三者和分布式文件存储系统的本质区别[通俗易懂]

    块存储、文件存储、对象存储这三者和分布式文件存储系统的本质区别[通俗易懂]https://blog.csdn.net/enweitech/article/details/51445087 块存储和文件存储是我们比较熟悉的两种主流的存储类型,而对象存储(Object-basedStorage)是一种新的网络存储架构,基于对象存储技术的设备就是对象存储设备(Object-basedStorageDevice)简称OSD。       首先,我们介绍这两种传统的存储类…

  • grahphics_blitz

    grahphics_blitz1.前言Graphics的Blit方法是比较简单也是比较常用的方法。最简单的作用是将一张纹理绘制到另一张纹理中。而在此方法中可以指定一种材质来实现特殊的效果,所以常和OnRenderImage方法配

  • 再议公交查询算法

    再议公交查询算法

  • 几个vbs代码

    几个vbs代码使用方法:新建一个txt文档,将上面的代码复制到txt,然后将文档的后缀名改成vbs。鼠标双击即可执行。第一个:msgbox”做我女朋友好吗”,vbQuestion,”在吗”msgbox(“房产写你名字”)msgbox(“保大”)msgbox(“我妈会游泳”)dimjdowhilej<1SelectCasemsgbox(“做我女朋友好吗”,68,”请郑重的回答我”)Case6j=1Case7msgbox(“再给你一次机会”)endSelect

  • pycharm安装pyside2_python pycharm安装

    pycharm安装pyside2_python pycharm安装一、Python IDE安装 python的IDE软件多种多样,可自行选择;下面是来自知乎9种ide的推荐:(https://zhuanlan.zhihu.com/p/26146374 点击打开链接) pycharm 下载地址:https://www.jetbrains.com/pycharm/download/#section=windows1.首先从网站下载pycharm:…

  • MATLAB快速搭建一个神经网络以及神经网络工具箱的使用

    MATLAB快速搭建一个神经网络以及神经网络工具箱的使用文章目录0.导读1.神经网络工具箱2.如何利用MATLAB工具箱建立神经网络人工神经网络学习笔记2——MATLAB神经网络工具箱神经网络工具箱的使用MATLAB中神经网络工具箱的使用0.导读首先声明,这篇文章的内容并不全是本人的原创内容,凡是引用了别人的博客或者文章的地方,我都会标注出来,以便大家阅读原文。现在最前面的,当然是提纲挈领的废话。凡是商品都有目标人群,文章也该如此,一篇文章写了…

发表回复

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

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