Skip to content

Commit 64e701a

Browse files
committed
update: render function docs
1 parent d75a1cc commit 64e701a

File tree

1 file changed

+61
-54
lines changed

1 file changed

+61
-54
lines changed

src/guide/render-function.md

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ Vue 推荐使用在绝大多数情况下使用 template 来创建你的 HTML。
1010

1111
让我们先深入一个使用 `render` 函数的简单例子,假设你想生成一个带锚链接的标题:
1212

13-
Vue recommends using templates to build your HTML in the vast majority of cases. There are situations however, where you really need the full programmatic power of JavaScript. That's where you can use the **render function**, a closer-to-the-compiler alternative to templates.
14-
15-
Let's dive into a simple example where a `render` function would be practical. Say you want to generate anchored headings:
1613

1714
``` html
1815
<h1>
@@ -22,13 +19,13 @@ Let's dive into a simple example where a `render` function would be practical. S
2219
</h1>
2320
```
2421

25-
For the HTML above, you decide you want this component interface:
22+
HTML 层, 我们决定这样定义组件接口:
2623

2724
``` html
2825
<anchored-heading :level="1">Hello world!</anchored-heading>
2926
```
3027

31-
When you get started with a component that just generates a heading based on the `level` prop, you quickly arrive at this:
28+
当我们开始写一个通过 `level` prop 动态生成heading 标签的组件,你可很快能想到这样实现:
3229

3330
``` html
3431
<script type="text/x-template" id="anchored-heading-template">
@@ -67,9 +64,9 @@ Vue.component('anchored-heading', {
6764
})
6865
```
6966

70-
That template doesn't feel great. It's not only verbose, but we're duplicating `<slot></slot>` for every heading level and will have to do the same when we add the anchor element. The whole thing is also wrapped in a useless `div` because components must contain exactly one root node.
67+
template 在这种场景中就表现的有些冗余了。虽然我们可以使用 `<slot></slot>` 来接收每一个级别的标题标签,在标题标签中添加相同的锚点元素。但是些都会被包裹在一个无用的 `div` 中,因为组件必须有根节点。
7168

72-
While templates work great for most components, it's clear that this isn't one of them. So let's try rewriting it with a `render` function:
69+
虽然模板在大多数组件中都非常好用,但是在这里它就不是很简洁的了。那么,我们来尝试使用 `render` 函数重写上面的例子:
7370

7471
``` js
7572
Vue.component('anchored-heading', {
@@ -88,11 +85,12 @@ Vue.component('anchored-heading', {
8885
})
8986
```
9087

91-
Much simpler! Sort of. The code is shorter, but also requires greater familiarity with Vue instance properties. In this case, you have to know that when you pass children without a `slot` attribute into a component, like the `Hello world!` inside of `anchored-heading`, those children are stored on the component instance at `$slots.default`. If you haven't already, **it's recommended to read through the [instance properties API](/api/#Instance-Properties) before diving into render functions.**
88+
简单清晰很多!简单来说,这样代码精简很多,但是需要非常熟悉 Vue 的实例属性。在这个例子中,你需要知道当你不使用 `slot` 属性向组件中传递内容时,比如 `anchored-heading` 中的 `Hello world!`, 这些子元素被存储在组件实例中的 `$slots.default`中。如果你还不了解,** 在深入 render 函数之前推荐阅读 [instance properties API](/api/#Instance-Properties)**
89+
9290

93-
## `createElement` Arguments
91+
## `createElement` 参数
9492

95-
The second thing you'll have to become familiar with is how to use template features in the `createElement` function. Here are the arguments that `createElement` accepts:
93+
第二件你需要熟悉的是如何在 `createElement` 函数中生成模板。这里是 `createElement` 接受的参数:
9694

9795
``` js
9896
// @returns {VNode}
@@ -123,54 +121,51 @@ createElement(
123121
)
124122
```
125123

126-
### The Data Object In-Depth
124+
### 完整数据对象
127125

128126
``` js
129127
{
130-
// Normal HTML attributes
128+
// 普通的 HTML 属性
131129
attrs: {
132130
id: 'foo'
133131
},
134-
// Component props
132+
// 组件 props
135133
props: {
136134
myProp: 'bar'
137135
},
138-
// DOM properties
136+
// DOM 属性
139137
domProps: {
140138
innerHTML: 'baz'
141139
},
142-
// Event handlers are nested under "on", though
143-
// modifiers such as in v-on:keyup.enter are not
144-
// supported. You'll have to manually check the
145-
// keyCode in the handler instead.
140+
// 事件监听器基于 "on"
141+
// 所以不再支持如 v-on:keyup.enter 修饰器
142+
// 需要手动匹配 keyCode。
146143
on: {
147144
click: this.clickHandler
148145
},
149-
// For components only. Allows you to listen to
150-
// native events, rather than events emitted from
151-
// the component using vm.$emit.
146+
// 仅对于组件,用于监听原生事件,而不是组件使用 vm.$emit 触发的事件。
152147
nativeOn: {
153148
click: this.nativeClickHandler
154149
},
155-
// Same API as `v-bind:class`
150+
// `v-bind:class` API 一致
156151
'class': {
157152
foo: true,
158153
bar: false
159154
},
160-
// Same API as `v-bind:style`
155+
// `v-bind:style` API 一致
161156
style: {
162157
color: 'red',
163158
fontSize: '14px'
164159
},
165-
// Other special top-level properties
160+
// 其他特殊顶层属性
166161
key: 'myKey',
167162
ref: 'myRef'
168163
}
169164
```
170165

171-
### Complete Example
166+
### 完整示例
172167

173-
With this knowledge, we can now finish the component we started:
168+
有了这方面的知识,我们现在可以完成我们最开始想实现的组件:
174169

175170
``` js
176171
var getChildrenTextContent = function (children) {
@@ -210,11 +205,11 @@ Vue.component('anchored-heading', {
210205
})
211206
```
212207

213-
### Constraints
208+
### 约束
214209

215-
#### VNodes Must Be Unique
210+
#### VNodes 必须唯一
216211

217-
All VNodes in the component tree must be unique. That means the following render function is invalid:
212+
所有组件树中的 VNodes 必须唯一。这意味着,下面的 render function 是无效的:
218213

219214
``` js
220215
render: function (createElement) {
@@ -226,7 +221,7 @@ render: function (createElement) {
226221
}
227222
```
228223

229-
If you really want to duplicate the same element/component many times, you can do so with a factory function. For example, the following render function is a perfectly valid way of rendering 20 identical paragraphs:
224+
如果你真的需要重复很多次的元素/组件,你可以使用工厂函数来实现。例如,下面这个例子 render 函数完美有效地渲染了 20 个重复的段落:
230225

231226
``` js
232227
render: function (createElement) {
@@ -239,18 +234,17 @@ render: function (createElement) {
239234
}
240235
```
241236

242-
## Replacing Template Features with Plain JavaScript
237+
## 使用 JavaScript 代替模板功能
243238

244-
Wherever something can be easily accomplished in plain JavaScript, Vue render functions do not provide an appropriate alternative. For example, in a template using `v-if` and `v-for`:
239+
无论什么都可以使用普通的 JavaScript 实现,而不用依赖 Vue render 函数额外提供 API。比如, template 中的 `v-if` `v-for`:
245240

246241
``` html
247242
<ul v-if="items.length">
248243
<li v-for="item in items">{{ item.name }}</li>
249244
</ul>
250245
<p v-else>No items found.</p>
251246
```
252-
253-
This could be rewritten with JavaScript's `if`/`else` and `map` in a render function:
247+
这些都会在 render 函数中被 JavaScript 的 `if`/`else``map` 重写:
254248

255249
``` js
256250
render: function (createElement) {
@@ -266,15 +260,16 @@ render: function (createElement) {
266260

267261
## JSX
268262

269-
If you're writing a lot of `render` functions, it might feel painful that we're using 14 lines above in place of this much simpler and arguably more readable template:
263+
如果你写了很多 `render` 函数,可能会觉得痛苦,在多于 14 行代码的场景中还是模板简单、易读很多。
270264

271265
``` html
272266
<anchored-heading :level="1">
273267
<span>Hello</span> world!
274268
</anchored-heading>
275269
```
276270

277-
That's why there's a [Babel plugin](https://github.com/vuejs/babel-plugin-transform-vue-jsx) to use JSX with Vue, getting us back to a syntax that's closer to templates:
271+
这就是会有一个 [Babel plugin](https://github.com/vuejs/babel-plugin-transform-vue-jsx) 插件,用于在 Vue 中使用 JSX 语法的原因,它可以让我们回到于更接近模板的语法上。
272+
278273

279274
``` js
280275
import AnchoredHeading from './AnchoredHeading.vue'
@@ -290,47 +285,55 @@ new Vue({
290285
}
291286
})
292287
```
288+
<p class="tip">将 `h` 作为 `createElement` 的别名是一个惯例,你会发现在 Vue 生态中,实际上必须依赖 JSX,如果 `h` 不可用, 会在应用中触发报错。</p>
293289

294-
<p class="tip">Aliasing `createElement` to `h` is a common convention you'll see in the Vue ecosystem and is actually required for JSX. If `h` is not available in the scope, your app will throw an error.</p>
290+
更多关于 JSX 映射到 JavaScript,阅读 [使用文档](https://github.com/vuejs/babel-plugin-transform-vue-jsx#usage)
295291

296-
For more on how JSX maps to JavaScript, see the [usage docs](https://github.com/vuejs/babel-plugin-transform-vue-jsx#usage).
297292

298-
## Functional Components
293+
## 函数化组件
299294

300-
The anchored heading component we created earlier is relatively simple. It doesn't manage any state, watch any state passed to it, and it has no lifecycle methods. Really, it's just a function with some props.
295+
之前创建的锚点标题组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法。它只是一个接收参数的函数。
296+
在这个例子中,我们标记组件为 `functional`, 这意味它是无状态(没有 `data`),无实例(没有 `this` 上下文)。
297+
一个 **函数化组件** 就像这样:
301298

302-
In cases like this, we can mark components as `functional`, which means that they're stateless (no `data`) and instanceless (no `this` context). A **functional component** looks like this:
303299

304300
``` js
305301
Vue.component('my-component', {
306302
functional: true,
307-
// To compensate for the lack of an instance,
308-
// we are now provided a 2nd context argument.
303+
// 为了弥补缺少的实例
304+
// 提供第二个参数作为上下文
309305
render: function (createElement, context) {
310306
// ...
311307
},
312-
// Props are optional
308+
// Props 可选
313309
props: {
314310
// ...
315311
}
316312
})
317313
```
318314

319-
Everything the component needs is passed through `context`, which is an object containing:
315+
组件需要的一切都是通过上下文传递,包括:
316+
317+
- `props`: 提供props 的对象
318+
- `children`: VNode 子节点的数组
319+
- `slots`: slots 对象
320+
- `data`: 传递给组件的 data 对象
321+
- `parent`: 对父组件的引用
320322

321-
- `props`: An object of the provided props
322-
- `children`: An array of the VNode children
323-
- `slots`: A slots object
324-
- `data`: The entire data object passed to the component
325-
- `parent`: A reference to the parent component
323+
在添加 `functional: true` 之后,锚点标题组件的 render 函数之间简单更新增加 `context` 参数,`this.$slots.default` 更新为 `context.children`,之后`this.level` 更新为 `context.props.level`
326324

327-
After adding `functional: true`, updating the render function of our anchored heading component would simply require adding the `context` argument, updating `this.$slots.default` to `context.children`, then updating `this.level` to `context.props.level`.
325+
函数化组件只是一个函数,所以渲染开销也低很多。但同样它也有完整的组件封装,你需要知道这些, 比如:
328326

329327
Since functional components are just functions, they're much cheaper to render. They're also very useful as wrapper components. For example, when you need to:
330328

329+
- 程序化地在多个组件中选择一个
330+
- 在将 children, props, data 传递给子组件之前操作它们。
331+
331332
- Programmatically choose one of several other components to delegate to
332333
- Manipulate children, props, or data before passing them on to a child component
333334

335+
下面是一个依赖传入 props 的值的 `smart-list` 组件例子,它能代表更多具体的组件:
336+
334337
Here's an example of a `smart-list` component that delegates to more specific components, depending on the props passed to it:
335338

336339
``` js
@@ -368,9 +371,9 @@ Vue.component('smart-list', {
368371
})
369372
```
370373

371-
### `slots` vs `children`
374+
### `slots` `children` 对比
372375

373-
You may wonder why we need both `slots` and `children`. Wouldn't `slots.default` be the same as `children`? In some cases, yes - but what if you have a functional component with the following children?
376+
你可能想知道为什么同时需要 `slots` `children``slots.default` 不是和 `children` 类似的吗?在一些场景中,是这样,但是如果是函数式组件和下面这样的 children 呢?
374377

375378
``` html
376379
<my-functional-component>
@@ -381,9 +384,13 @@ You may wonder why we need both `slots` and `children`. Wouldn't `slots.default`
381384
</my-functional-component>
382385
```
383386

387+
对于这个组件,`children` 会给你两个段落标签,而 `slots.default` 只会传递第二个匿名段落标签,`slots.foo` 会传递第一个具名段落标签。同时拥有 `children``slots` ,因此你可以选择组件通过插槽系统或者简单的通过 `children` 接收。
388+
384389
For this component, `children` will give you both paragraphs, `slots.default` will give you only the second, and `slots.foo` will give you only the first. Having both `children` and `slots` therefore allows you to choose whether this component knows about a slot system or perhaps delegates that responsibility to another component by simply passing along `children`.
385390

386-
## Template Compilation
391+
## 模板编译
392+
393+
你可能有兴趣知道,Vue 的模板实际是编译成了 render 函数。这是一个实现细节,通常不需要关心,但如果你想看看模板的功能是怎样被编译的,你会发现会非常有趣。下面是一个使用 `Vue.compile` 来实时编译模板字符串的简单 demo:
387394

388395
You may be interested to know that Vue's templates actually compile to render functions. This is an implementation detail you usually don't need to know about, but if you'd like to see how specific template features are compiled, you may find it interesting. Below is a little demo using `Vue.compile` to live-compile a template string:
389396

0 commit comments

Comments
 (0)