Please enable Javascript to view the contents

Vue 中的 h 函数

 ·  ☕ 2 分钟

1. createElement 方法

HTML 中常见的 DOM 操作是,修改 DOM 节点,访问 DOM 节点。

除此之外,W3C 还发布了创建 DOM 节点、删除 DOM 节点的技术标准。

createElement 方法,被用于创建一个 DOM 节点。createElement() 通常需要与 appendChild() 或 insertBefore() 方法配合使用。

其中:

  • appendChild() 方法,用来在指定的子节点列表末,插入新的节点。
  • insertBefore() 方法,用来在指定的已有子节点之前,插入新的节点。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <div id="parentElement">
    <span id="childElement">子节点</span>
  </div>
  <button onclick="myFunction()">点我新增子节点</button>
  <script>
  function myFunction(){
      var btn = document.createElement("BUTTON");
      var text = document.createTextNode("新增加的按钮");
      btn.appendChild(text);
      var exist_node = document.getElementById("childElement");
      document.getElementById("parentElement").insertBefore(btn, exist_node);
      //window.document.body.appendChild(btn);
  };
</script>
</body>
</html>

2. Vue 自定义渲染

在 Vue 中有两种渲染页面的写法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 使用 template
new Vue({
  template: '<div>{{ hi }}</div>'
})

// 使用 render 方法
new Vue({
  render (h) {
    return h('div', this.hi)
  }
})

实际上,在 Vue 调用 mounted 方法时,会将 template 编译成 render 方法。使用 template 的渲染效率没有使用 render 效率高。

Vue 的渲染与 W3C 的 createElement 方法功能上类似。Vue 中也有 createElement 方法。不同于 W3C 的 createElement 方法,Vue 中的 createElement 方法不是直接对 DOM 进行操作,而是操作 VNode。

3. Vue 中的 h 方法

Vue 中的 h 方法是 createElement 方法的缩写。

首先分析一下,Vue 中是如何渲染的:

Vue 中使用 _render 将一个实例渲染成 VNode。在 _render 中主要的处理逻辑是:

1
vnode = render.call(vm._renderProxy, vm.$createElement)

可以看到,Vue 将 vm.$createElement 传递给了 render 方法。而 createElement 方法又是对 _createElement 方法的封装。

1
2
3
4
5
6
7
_createElement (
  context: Component,
  tag?: string | Class<Component> | Function | Object,
  data?: VNodeData,
  children?: any,
  normalizationType?: number
)

这里的 context 是 VNode 的上下文环境。这样就能理解 createElement 方法或者说 h 方法的参数列表了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// @returns {VNode}
 createElement(
  // {String | Object | Function}
  // 一个 HTML 标签字符串,组件选项对象,或者
  // 解析上述任何一种的一个 async 异步方法,必要参数。
  'div',

  // {Object}
  // 一个包含模板相关属性的数据对象
  // 这样,您可以在 template 中使用这些属性。可选参数。
  {
    // (详情见下一节)
  },

  // {String | Array}
  // 子节点 (VNodes),由 `createElement()` 构建而成,
  // 或使用字符串来生成“文本节点”。可选参数。
  [
    '先写一些文字',
    createElement('h1', '一则头条'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'
      }
    })
  ]
)

4. 参考


微信公众号
作者
微信公众号