Vue3$View-RenderMechanism-QA
1. 为什么 .vue 文件能够运行?
因为 Vue 会把 .vue 文件编译成 .js 和 .css 文件。运行 npm run build可查看编译后的文件。
其中 template 解析到页面的过程 VueRenderPipeline:
- 编译 compile:
template被编译为render 函数(这一步骤可以通过构建步骤提前完成,也可以通过使用运行时编译器 runtime compiler 即时完成。) - 挂载 mount:
render 函数执行返回虚拟 DOM 树(通过运行时渲染器 runtime renderer)(这一步会作为响应式副作用 reactive effect 执行,因此它会追踪其中所用到的所有响应式依赖。)虚拟 DOM 树被解析为 真实 DOM 树
- 更新 patch:依赖发生变化后,副作用会重新执行,生成新的
虚拟 DOM 树。 Runtime renderer 会对比新旧树,更新更改的部分 (更新 / 对比 / 协调 - patch / diffing / reconciliation)
2. 既然 template 会被编译为 render 函数,为什么不直接写 render 函数呢?
- 为什么更推荐 template:
- template 语法更接近 HTML,是声明式的,便于开发和维护。
- Vue 会在编译 template 时做优化,编译后的 render 函数比手写的 render 函数多了些信息,性能更好。VueCompilerInformedVirtualDOM
- 何时使用 render 函数:render 函数的优点是灵活。当需要动态生成一些内容的时候(使用 template 不方便时 )使用。
3. Render 函数是什么,如何使用?
在 setup() 中 return 的函数就是 render function。Render function 的返回值分三种情况:
- 字符串(如果不需要实例状态,可简写成函数。函数式组件)
- vnode(虚拟 DOM 节点,可通过 Vue 的
h()生成。) - 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 只需要表明:
- 类型 type
- 属性 attribute
- 内容 content
<div id="hello">你好</div>
类似的,要表达一个 DOM 元素, 在 JavaScript 中只需要表明:
- 类型type
- 属性 property
- 内容 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>