Vue3$View-RenderMechanism-QA

41 阅读1分钟

Vue3$View-RenderMechanism-QA

1. 为什么 .vue 文件能够运行?

因为 Vue 会把 .vue 文件编译成 .js.css 文件。运行 npm run build可查看编译后的文件。

其中 template 解析到页面的过程 VueRenderPipeline

  1. 编译 compiletemplate 被编译为 render 函数 (这一步骤可以通过构建步骤提前完成,也可以通过使用运行时编译器 runtime compiler 即时完成。)
  2. 挂载 mount
    1. render 函数 执行返回 虚拟 DOM 树(通过运行时渲染器 runtime renderer)(这一步会作为响应式副作用 reactive effect 执行,因此它会追踪其中所用到的所有响应式依赖。)
    2. 虚拟 DOM 树 被解析为 真实 DOM 树
  3. 更新 patch:依赖发生变化后,副作用会重新执行,生成新的 虚拟 DOM 树。 Runtime renderer 会对比新旧树,更新更改的部分 (更新 / 对比 / 协调 - patch / diffing / reconciliation) VueRenderPipeline

2. 既然 template 会被编译为 render 函数,为什么不直接写 render 函数呢?

  1. 为什么更推荐 template:
    1. template 语法更接近 HTML,是声明式的,便于开发和维护。
    2. Vue 会在编译 template 时做优化,编译后的 render 函数比手写的 render 函数多了些信息,性能更好。VueCompilerInformedVirtualDOM
  2. 何时使用 render 函数:render 函数的优点是灵活。当需要动态生成一些内容的时候(使用 template 不方便时 )使用。

3. Render 函数是什么,如何使用?

setup() 中 return 的函数就是 render function。Render function 的返回值分三种情况:

  1. 字符串(如果不需要实例状态,可简写成函数。函数式组件)
  2. vnode(虚拟 DOM 节点,可通过 Vue 的 h() 生成。)
  3. vnode 数组

# Vue3$View-RenderFunction&VueJSX

export default {
  setup() {
    return () => 'hello world!'
  }
}
function Hello() {
  return 'hello world!'
}
import { ref, h } from 'vue'

export default {
  props: {
    /* ... */
  },
  setup(props) {
    const count = ref(1)

    // 返回渲染函数
    return () => h('div', props.msg + count.value)
  }
}
import { h } from 'vue'

export default {
  setup() {
    // 使用数组返回多个根节点
    return () => [
      h('div'),
      h('div'),
      h('div')
    ]
  }
}

4. 什么是虚拟 DOM (virtual DOM)

虚拟 DOM 是真实 DOM 的 JavaScript 映射。

要表达一个 DOM 元素,在 HTML 只需要表明:

  1. 类型 type
  2. 属性 attribute
  3. 内容 content
<div id="hello">你好</div>

类似的,要表达一个 DOM 元素, 在 JavaScript 中只需要表明:

  1. 类型type
  2. 属性 property
  3. 内容 children
const vnode = {
  type: 'div',
  props: {
    id: 'hello'
  },
  children: [
    /* more vnodes */
  ]
}

5. JSX 是什么

JSX 是 JavaScript 的一个类似 XML 的扩展。和 template 类似,是另一种表达“动态 HTML”的语法。

Vue 的 JSX 语法和 React 的有些差别:

  • 可以使用 HTML attributes 作为 props ( class 和 for - 而不是 className 或 htmlFor。)
  • 传递子元素给组件 (比如 slots) 的方式不同
const vnode = <div id={dynamicId}>hello, {userName}</div>

Links

VueRenderingMechanism