diff --git a/src/guide/render-function.md b/src/guide/render-function.md
index 7b3b646cf..744ecb32f 100644
--- a/src/guide/render-function.md
+++ b/src/guide/render-function.md
@@ -19,8 +19,11 @@ Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在
```
当开始写一个只能通过 `level` prop 动态生成标题 (heading) 的组件时,我们很快就可以得出这样的结论:
+
```js
-const app = Vue.createApp({})
+const { createApp } = Vue
+
+const app = createApp({})
app.component('anchored-heading', {
template: `
@@ -51,17 +54,18 @@ app.component('anchored-heading', {
}
})
```
+
这个模板感觉不太好。它不仅冗长,而且我们为每个级别标题重复书写了 ``。当我们添加锚元素时,我们必须在每个 `v-if/v-else-if` 分支中再次重复它。
虽然模板在大多数组件中都非常好用,但是显然在这里它就不合适了。那么,我们来尝试使用 `render` 函数重写上面的例子:
```js
-const app = Vue.createApp({})
+const { createApp, h } = Vue
+
+const app = createApp({})
app.component('anchored-heading', {
render() {
- const { h } = Vue
-
return h(
'h' + this.level, // tag name
{}, // props/attributes
@@ -109,7 +113,7 @@ app.component('anchored-heading', {
```js
render() {
- return Vue.h('h1', {}, this.blogTitle)
+ return h('h1', {}, this.blogTitle)
}
```
@@ -120,7 +124,7 @@ render() {
Vue 通过建立一个**虚拟 DOM** 来追踪自己要如何改变真实 DOM。请仔细看这行代码:
```js
-return Vue.h('h1', {}, this.blogTitle)
+return h('h1', {}, this.blogTitle)
```
`h()` 到底会返回什么呢?其实不是一个*实际*的 DOM 元素。它更准确的名字可能是 createNodeDescription,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点,包括及其子节点的描述信息。我们把这样的节点描述为“虚拟节点 (virtual node)”,也常简写它为 **VNode**。“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼。
@@ -167,7 +171,9 @@ h(
有了这些知识,我们现在可以完成我们最开始想实现的组件:
```js
-const app = Vue.createApp({})
+const { createApp, h } = Vue
+
+const app = createApp({})
/** Recursively get text from children nodes */
function getChildrenTextContent(children) {
@@ -190,8 +196,8 @@ app.component('anchored-heading', {
.replace(/\W+/g, '-') // replace non-word characters with dash
.replace(/(^-|-$)/g, '') // remove leading and trailing dashes
- return Vue.h('h' + this.level, [
- Vue.h(
+ return h('h' + this.level, [
+ h(
'a',
{
name: headingId,
@@ -218,8 +224,8 @@ app.component('anchored-heading', {
```js
render() {
- const myParagraphVNode = Vue.h('p', 'hi')
- return Vue.h('div', [
+ const myParagraphVNode = h('p', 'hi')
+ return h('div', [
// 错误 - 重复的Vnode!
myParagraphVNode, myParagraphVNode
])
@@ -230,9 +236,9 @@ render() {
```js
render() {
- return Vue.h('div',
+ return h('div',
Array.from({ length: 20 }).map(() => {
- return Vue.h('p', 'hi')
+ return h('p', 'hi')
})
)
}
@@ -257,24 +263,24 @@ render() {
props: ['items'],
render() {
if (this.items.length) {
- return Vue.h('ul', this.items.map((item) => {
- return Vue.h('li', item.name)
+ return h('ul', this.items.map((item) => {
+ return h('li', item.name)
}))
} else {
- return Vue.h('p', 'No items found.')
+ return h('p', 'No items found.')
}
}
```
### `v-model`
- `v-model` 指令扩展为 `modelValue` 和 `onUpdate:modelValue` 在模板编译过程中,我们必须自己提供这些prop:
+`v-model` 指令扩展为 `modelValue` 和 `onUpdate:modelValue` 在模板编译过程中,我们必须自己提供这些 prop:
```js
props: ['modelValue'],
emits: ['update:modelValue'],
render() {
- return Vue.h(SomeComponent, {
+ return h(SomeComponent, {
modelValue: this.modelValue,
'onUpdate:modelValue': value => this.$emit('update:modelValue', value)
})
@@ -283,11 +289,11 @@ render() {
### `v-on`
-我们必须为事件处理程序提供一个正确的prop名称,例如,要处理 `click` 事件,prop名称应该是 `onClick`。
+我们必须为事件处理程序提供一个正确的 prop 名称,例如,要处理 `click` 事件,prop 名称应该是 `onClick`。
```js
render() {
- return Vue.h('div', {
+ return h('div', {
onClick: $event => console.log('clicked', $event.target)
})
}
@@ -295,13 +301,13 @@ render() {
#### 事件修饰符
-对于 `.passive` 、 `.capture`和 `.once` 事件修饰符,Vue提供了处理程序的对象语法:
+对于 `.passive` 、 `.capture`和 `.once` 事件修饰符,Vue 提供了处理程序的对象语法:
实例:
```javascript
render() {
- return Vue.h('input', {
+ return h('input', {
onClick: {
handler: this.doThisInCapturingMode,
capture: true
@@ -321,19 +327,19 @@ render() {
对于所有其它的修饰符,私有前缀都不是必须的,因为你可以在事件处理函数中使用事件方法:
-| 修饰符 | 处理函数中的等价操作 |
-| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
-| `.stop` | `event.stopPropagation()` |
-| `.prevent` | `event.preventDefault()` |
-| `.self` | `if (event.target !== event.currentTarget) return` |
-| 按键:
`.enter`, `.13` | `if (event.keyCode !== 13) return` (对于别的按键修饰符来说,可将 13 改为[另一个按键码](http://keycode.info/) |
-| 修饰键:
`.ctrl`, `.alt`, `.shift`, `.meta` | `if (!event.ctrlKey) return` (将 `ctrlKey` 分别修改为 `altKey`, `shiftKey`, 或 `metaKey`) |
+| 修饰符 | 处理函数中的等价操作 |
+| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
+| `.stop` | `event.stopPropagation()` |
+| `.prevent` | `event.preventDefault()` |
+| `.self` | `if (event.target !== event.currentTarget) return` |
+| 按键:
`.enter`, `.13` | `if (event.keyCode !== 13) return` (对于别的按键修饰符来说,可将 13 改为[另一个按键码](http://keycode.info/) |
+| 修饰键:
`.ctrl`, `.alt`, `.shift`, `.meta` | `if (!event.ctrlKey) return` (将 `ctrlKey` 分别修改为 `altKey`, `shiftKey`, 或 `metaKey`) |
这里是一个使用所有修饰符的例子:
```js
render() {
- return Vue.h('input', {
+ return h('input', {
onKeyUp: event => {
// 如果触发事件的元素不是事件绑定的元素
// 则返回
@@ -358,7 +364,7 @@ render() {
```js
render() {
// `
`
- return Vue.h('div', {}, this.$slots.default())
+ return h('div', {}, this.$slots.default())
}
```
@@ -366,7 +372,7 @@ render() {
props: ['message'],
render() {
// `
`
- return Vue.h('div', {}, this.$slots.default({
+ return h('div', {}, this.$slots.default({
text: this.message
}))
}
@@ -377,11 +383,13 @@ render() {
```js
+const { h, resolveComponent } = Vue
+
render() {
// `{{ props.text }}
`
- return Vue.h('div', [
- Vue.h(
- Vue.resolveComponent('child'),
+ return h('div', [
+ h(
+ resolveComponent('child'),
{},
// pass `slots` as the children object
// in the form of { name: props => VNode | Array }
@@ -398,13 +406,13 @@ render() {
如果你写了很多渲染函数,可能会觉得下面这样的代码写起来很痛苦:
```js
-Vue.h(
+h(
'anchored-heading',
{
level: 1
},
{
- default: () => [Vue.h('span', 'Hello'), ' world!']
+ default: () => [h('span', 'Hello'), ' world!']
}
)
```