Vue从入门到实战:render函数

来自CloudWiki
Cloud17讨论 | 贡献2021年2月20日 (六) 02:46的版本
跳转至: 导航搜索

背景

Vue推荐在大多数情况下使用模板来构建HTML,

然后在一些场景中,你可能需要Javascript的编程能力,这时可以使用render函数,它比模板更接近编译器。

Vue21022001.png

假设我们要生成一些带锚点的标题:

<h1>
  <a name="hello-world" href="#hello-world">
    Hello world!
  </a>
</h1>

对于上面的 HTML,你决定这样定义组件接口:

<anchored-heading :level="1">Hello world!</anchored-heading>

当开始写一个只能通过 level prop 动态生成标题 (heading) 的组件时,你可能很快想到这样实现:

<script type="text/x-template" id="anchored-heading-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>

Vue.component('anchored-heading', {
  template: '#anchored-heading-template',
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

虽然模板在大多数组件中都非常好用,但在本例中不太合适,模板代码冗长,且<slot>元素在每一级标题元素中都重复书写了。

render函数的引入

下面改用render函数重复上面的示例,代码精简了很多

render函数 又称渲染函数,字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script src="vue.js"></script>
	</head>
	<body>
		
		<div id="app">

			<anchored-heading :level="3">
				<a name="hello-world" href="#hello-world">
    			Hello world!
  			</a>
			</anchored-heading>


		</div>
		<script type = "text/javascript">
			Vue.component('anchored-heading', {
			  render: function (createElement) {
			    return createElement(
			      'h' + this.level,   // 标签名称
			      this.$slots.default // 子节点数组
			    )
			  },
			  props: {
			    level: {
			      type: Number,
			      required: true
			    }
			  }
			})
			new Vue({
			  el: '#app'
			})
		</script>
	</body>
</html>

注:$slots用于以编程方式访问由插槽分发的内容,每个命名的插槽都有其相应的属性。default属性包含了所有未包含在命名插槽中的节点或v-slot:default的内容。

==render函数的解释

createElement函数

该函数用于返回描述节点信息及其子节点子信息的一个对象,即虚拟节点(简称为VNode)

一般带有三个参数:

  • 第一个参数是要创建的元素节点的名字(字符串形式)或者组件选项(对象形式);
  • 第二个参数是元素的属性集合(包括普通属性、prop、事件属性、自定义指令等),以对象形式给出
  • 第三个参数是子节点的信息,以数组形式给出,如果该元素只有文本子节点,那么直接以字符串形式给出即可,如果还有子元素,则继续调用createElement函数。