You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
16
13
17
14
```html
18
15
<h1>
@@ -22,13 +19,13 @@ Let's dive into a simple example where a `render` function would be practical. S
22
19
</h1>
23
20
```
24
21
25
-
For the HTML above, you decide you want this component interface:
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.
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.**
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:
All VNodes in the component tree must be unique. That means the following render function is invalid:
212
+
所有组件树中的 VNodes 必须唯一。这意味着,下面的 render function 是无效的:
218
213
219
214
```js
220
215
render:function (createElement) {
@@ -226,7 +221,7 @@ render: function (createElement) {
226
221
}
227
222
```
228
223
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:
@@ -239,18 +234,17 @@ render: function (createElement) {
239
234
}
240
235
```
241
236
242
-
## Replacing Template Features with Plain JavaScript
237
+
## 使用 JavaScript 代替模板功能
243
238
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`:
@@ -266,15 +260,16 @@ render: function (createElement) {
266
260
267
261
## JSX
268
262
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:
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:
<pclass="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>
For more on how JSX maps to JavaScript, see the [usage docs](https://github.com/vuejs/babel-plugin-transform-vue-jsx#usage).
297
292
298
-
## Functional Components
293
+
## 函数化组件
299
294
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.
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:
303
299
304
300
```js
305
301
Vue.component('my-component', {
306
302
functional:true,
307
-
//To compensate for the lack of an instance,
308
-
//we are now provided a 2nd context argument.
303
+
//为了弥补缺少的实例
304
+
//提供第二个参数作为上下文
309
305
render:function (createElement, context) {
310
306
// ...
311
307
},
312
-
// Props are optional
308
+
// Props 可选
313
309
props: {
314
310
// ...
315
311
}
316
312
})
317
313
```
318
314
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`: 对父组件的引用
320
322
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
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
+
函数化组件只是一个函数,所以渲染开销也低很多。但同样它也有完整的组件封装,你需要知道这些, 比如:
328
326
329
327
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:
330
328
329
+
- 程序化地在多个组件中选择一个
330
+
- 在将 children, props, data 传递给子组件之前操作它们。
331
+
331
332
- Programmatically choose one of several other components to delegate to
332
333
- Manipulate children, props, or data before passing them on to a child component
Here's an example of a `smart-list` component that delegates to more specific components, depending on the props passed to it:
335
338
336
339
```js
@@ -368,9 +371,9 @@ Vue.component('smart-list', {
368
371
})
369
372
```
370
373
371
-
### `slots`vs`children`
374
+
### `slots`和`children` 对比
372
375
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 呢?
374
377
375
378
```html
376
379
<my-functional-component>
@@ -381,9 +384,13 @@ You may wonder why we need both `slots` and `children`. Wouldn't `slots.default`
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`.
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:
0 commit comments