上述的这个和一些接下来的示例使用了 JavaScript 的[模板字符串](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Template_literals)来让多行的模板更易读。它们在 IE 下并没有被支持,所以如果你需要在不 (经过 Babel 或 TypeScript 之类的工具) 编译的情况下支持 IE,请使用[折行转义字符](https://css-tricks.com/snippets/javascript/multiline-string-variables-in-javascript/)取而代之。
-与绑定到任何普通的 HTML 特性相类似,我们可以用 `v-bind` 来动态地将 prop 绑定到父组件的数据。每当父组件的数据变化时,该变化也会传导给子组件:
+问题是这个按钮不会做任何事:
-``` html
-
-
-
-
+
{% endraw %}
-如果你想把一个对象的所有属性作为 prop 进行传递,可以使用不带任何参数的 `v-bind` (即用 `v-bind` 而不是 `v-bind:prop-name`)。例如,已知一个 `todo` 对象:
-
-``` js
-todo: {
- text: 'Learn Vue',
- isComplete: false
-}
-```
+### 使用事件抛出一个值
-然后:
+有的时候用一个事件来抛出一个特定的值是非常有用的。例如我们可能想让 `
` 组件决定它的文本要放大多少。这时可以使用 `$emit` 的第二个参数来提供这个值:
-``` html
-
+```html
+
```
-将等价于:
+然后当在父级组件监听这个事件的时候,我们可以通过 `$event` 访问到被抛出的这个值:
-``` html
-
+```html
+
```
-### 字面量语法 vs 动态语法
-
-初学者常犯的一个错误是使用字面量语法传递数值:
+或者,如果这个事件处理函数是一个方法:
-``` html
-
-
+```html
+
```
-因为它是一个字面量 prop,它的值是字符串 `"1"` 而不是一个数值。如果想传递一个真正的 JavaScript 数值,则需要使用 `v-bind`,从而让它的值被当作 JavaScript 表达式计算:
+那么这个值将会作为第一个参数传入这个方法:
-``` html
-
-
+```js
+methods: {
+ onEnlargeText: function (enlargeAmount) {
+ this.postFontSize += enlargeAmount
+ }
+}
```
-### 单向数据流
-
-Prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。
-
-另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你**不应该**在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。
-
-在两种情况下,我们很容易忍不住想去修改 prop 中数据:
-
-1. Prop 作为初始值传入后,子组件想把它当作局部数据来用;
-
-2. Prop 作为原始数据传入,由子组件处理成其它数据输出。
+### 在组件上使用 `v-model`
-对这两种情况,正确的应对方式是:
+自定义事件也可以用于创建支持 `v-model` 的自定义输入组件。记住:
-1. 定义一个局部变量,并用 prop 的值初始化它:
+```html
+
+```
- ``` js
- props: ['initialCounter'],
- data: function () {
- return { counter: this.initialCounter }
- }
- ```
+等价于:
-2. 定义一个计算属性,处理 prop 的值并返回:
+```html
+
+```
- ``` js
- props: ['size'],
- computed: {
- normalizedSize: function () {
- return this.size.trim().toLowerCase()
- }
- }
- ```
+当用在组件上时,`v-model` 则会这样:
-注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它**会影响**父组件的状态。
+``` html
+
+```
-### Prop 验证
+为了让它正常工作,这个组件内的 `` 必须:
-我们可以为组件的 prop 指定验证规则。如果传入的数据不符合要求,Vue 会发出警告。这对于开发给他人使用的组件非常有用。
+- 将其 `value` 特性绑定到一个名叫 `value` 的 prop 上
+- 在其 `input` 事件被触发时,将新的值通过自定义的 `input` 事件抛出
-要指定验证规则,需要用对象的形式来定义 prop,而不能用字符串数组:
+写成代码之后是这样的:
-``` js
-Vue.component('example', {
- props: {
- // 基础类型检测 (`null` 指允许任何类型)
- propA: Number,
- // 可能是多种类型
- propB: [String, Number],
- // 必传且是字符串
- propC: {
- type: String,
- required: true
- },
- // 数值且有默认值
- propD: {
- type: Number,
- default: 100
- },
- // 数组/对象的默认值应当由一个工厂函数返回
- propE: {
- type: Object,
- default: function () {
- return { message: 'hello' }
- }
- },
- // 自定义验证函数
- propF: {
- validator: function (value) {
- return value > 10
- }
- }
- }
+```js
+Vue.component('custom-input', {
+ props: ['value'],
+ template: `
+
+```
-所谓非 prop 特性,就是指它可以直接传入组件,而不需要定义相应的 prop。
+到目前为止,关于组件自定义事件你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把[自定义事件](components-custom-events.html)读完。
-尽管为组件定义明确的 prop 是推荐的传参方式,组件的作者却并不总能预见到组件被使用的场景。所以,组件可以接收任意传入的特性,这些特性都会被添加到组件的根元素上。
+## 通过插槽分发内容
-例如,假设我们使用了第三方组件 `bs-date-input`,它包含一个 Bootstrap 插件,该插件需要在 `input` 上添加 `data-3d-date-picker` 这个特性。这时可以把特性直接添加到组件上 (不需要事先定义 `prop`):
+和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:
``` html
-
+
+ Something bad happened.
+
```
-添加属性 `data-3d-date-picker="true"` 之后,它会被自动添加到 `bs-date-input` 的根元素上。
+可能会渲染出这样的东西:
-### 替换/合并现有的特性
+{% raw %}
+
+
+ Something bad happened.
+
+
+
+
+{% endraw %}
-假设这是 `bs-date-input` 的模板:
+幸好,Vue 自定义的 `` 元素让这变得非常简单:
-``` html
-
+```js
+Vue.component('alert-box', {
+ template: `
+
+ Error!
+
+
+ `
+})
```
-为了给该日期选择器插件增加一个特殊的主题,我们可能需要增加一个特殊的 class,比如:
+如你所见,我们只要在需要的地方加入插槽就行了——就这么简单!
-``` html
-
-```
+到目前为止,关于插槽你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把[插槽](components-slots.html)读完。
-在这个例子当中,我们定义了两个不同的 `class` 值:
+## 动态组件
-- `form-control`,来自组件自身的模板
-- `date-picker-theme-dark`,来自父组件
+有的时候,在不同组件之间进行动态切换是非常有用的,比如在一个多标签的界面里:
-对于多数特性来说,传递给组件的值会覆盖组件本身设定的值。即例如传递 `type="large"` 将会覆盖 `type="date"` 且有可能破坏该组件!所幸我们对待 `class` 和 `style` 特性会更聪明一些,这两个特性的值都会做合并 (merge) 操作,让最终生成的值为:`form-control date-picker-theme-dark`。
+{% raw %}
+
+
+
+
+
+
+{% endraw %}
-## 自定义事件
+上述内容可以通过 Vue 的 `` 元素加一个特殊的 `is` 特性来实现:
-我们知道,父组件使用 prop 传递数据给子组件。但子组件怎么跟父组件通信呢?这个时候 Vue 的自定义事件系统就派得上用场了。
+```html
+
+
+```
-### 使用 `v-on` 绑定自定义事件
+In the example above, `currentTabComponent` can contain either:
+在上述示例中,`currentTabComponent` 可以包括
-每个 Vue 实例都实现了[事件接口](../api/#实例方法-事件),即:
+- 已注册组件的名字,或
+- 一个组件的选项对象
-- 使用 `$on(eventName)` 监听事件
-- 使用 `$emit(eventName, optionalPayload)` 触发事件
+你可以在[这里](https://jsfiddle.net/chrisvfritz/o3nycadu/)查阅并体验完整的代码,或在[这个版本](https://jsfiddle.net/chrisvfritz/b2qj69o1/)了解绑定组件选项对象,而不是已注册组件名的示例。
-Vue 的事件系统与浏览器的 [EventTarget API](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) 有所不同。尽管它们运行起来类似,但是 `$on` 和 `$emit` __并不是__`addEventListener` 和 `dispatchEvent` 的别名。
+到目前为止,关于动态组件你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把[动态和异步组件](components-dynamic-async.html)读完。
-另外,父组件可以在使用子组件的地方直接用 `v-on` 来监听子组件触发的事件。
+## 解析 DOM 模板时的注意事项
-不能用 `$on` 监听子组件释放的事件,而必须在模板里直接用 `v-on` 绑定,参见下面的例子。
+有些 HTML 元素,诸如 ``、``、`` 和 `