指南
基础概要
- 安装
- 介绍
- Vue 实例
- 模板语法
- computed 属性和 watcher
- class 和 style 绑定
- 根据条件进行渲染
- 列表渲染
- 事件处理
- 表单 input 绑定
- 组件基础
过渡 & 动画
- 进入、离开和列表的过渡
深入组件
- 组件注册
- props
- 自定义事件
- slot
- 动态组件和异步组件
- Handling Edge Cases
- 状态间的过渡
可重用 & 合成
- mixin
- 自定义指令
- render 函数 & jsx
- 插件
- 过滤器
工具
- 生产环境部署
- 单文件组件
- 单元测试
- TypeScript 支持
扩展升级
- 路由
- 状态管理
- 服务端渲染
内部原理
- 深入响应式原理
升级迁移
- 从 Vue 1.x 迁移
- 从 Vue Router 0.7.x 迁移
- 从 Vuex 0.6.x 迁移到 1.0
其他更多
- 对比其他框架
- 加入 Vue.js 社区
- 认识团队
自定义事件
本页面会假定你已经阅读过 组件基础。如果你还不熟悉组件,请先阅读组件基础后再阅读本页面。
事件名称(event names)
与 components 和 props 不同,事件名称并不提供命名自动转换。反之,触发的事件名称必须与监听时的名称完全匹配。例如,如果触发事件名称是以驼峰式命名(camelCased):
this.$emit('myEvent') |
而监听处是以串联式命名(kebab-cased)时,无法接收到事件:
<my-component v-on:my-event="doSomething"></my-component> |
与 components 和 props 不同,事件名称永远不会用作 JavaScript 变量或属性名称,所以没有理由去使用驼峰式命名(camelCase)或帕斯卡命名(PascalCase)。此外,DOM 模板中的 v-on
事件监听器会自动转换为小写(这是因为 HTML 属性名称不区分大小写),所以 v-on:myEvent
会变为 v-on:myevent
- 由此 myEvent
就不可能监听到事件触发。
由于这些原因,我们建议你总是使用串联式命名(kebab-cased)来命名事件名称。
定制组件 v-model
2.2.0+ 新增
在一个组件中,v-model
默认使用 value
作为 prop,以及默认使用 input
作为监听事件,然而,对于某些类型的 input 元素(例如 checkbox 和 radio),由于这些类型的 input 元素本身具有 不同用法,可能会占用 value
特性。在这种情况下,使用组件的 model
选项可以避免冲突:
Vue.component('base-checkbox', { |
现在,在这个组件中使用 v-model
:
<base-checkbox v-model="lovingVue"></base-checkbox> |
lovingVue
的值就会传递给 checked
prop。当 <base-checkbox>
内部触发一个 change
事件,并且传递一个新值,lovingVue
属性就会进行更新。
注意,仍然需要在组件 props
选项中声明 checked
prop 属性。
为组件绑定本地事件(binding native events to components)
有时候,你可能希望某个组件的根元素能够直接监听到组件所处位置的本地事件。在这种场景中,你可以在 v-on
上使用 .native
修饰符:
<base-input v-on:focus.native="onFocus"></base-input> |
有时绑定本地事件会很有用,但是注意,如果你试图监听一个非常特殊的元素(例如 <input>
元素),则不是正确用法(译注:)。举例说明,上面的 <base-input>
组件或许会进行重构,因此其根元素可能实际上是一个 <label>
元素:
<label> |
在这种场景中,由于 input 不是根元素,所以与父组件中那些使用 .native
修饰符的监听器(listener)之间的关联被静默破坏。这没有任何错误提醒,只是 onFocus
处理函数并没有按照我们的预期被调用。
为了解决这个问题,Vue 提供了一个 $listeners
属性,它是包含组件中所有监听器的对象。例如:
{ |
你可以将所有父组件中由 v-on="$listeners"
绑定的监听器,通过 $listeners
属性转发到子组件的特定元素。对于像 <input>
这样的元素,你还需要实现 v-model
机制,通常会创建返回一个新的 listeners 对象的 computed 属性,类似如下 inputListeners
:
Vue.component('base-input', { |
现在,<base-input>
组件是一个毫无疑惑的容器组件(fully transparent wrapper)了,也就是说,可以像使用一个普通的 <input>
元素一样去使用它:所有的特性和监听器,都能够如同普通 input 元素一样正常运行。
.sync
修饰符
2.3.0+ 新增
在某些场景中,我们可能需要为某个 prop 属性进行「双向绑定」。不幸的是,真正的双向绑定会产生一些维护问题,由于子组件可以修改父组件中的状态,所以无法确认修改的源头是来自父组件还是子组件。
这也就是为什么我们放弃这种机制的原因,我们更推荐通过子组件触发 update:my-prop-name
事件的方式,来更新父组件的状态。例如,在一个接收 title
prop 的假想组件中,我们想要分配一个子组件的新值给父组件的意图,可以通过通信机制来实现:
this.$emit('update:title', newTitle) |
然后,父组件可以监听到这个事件,并且(如果需要的话)更新一个本地数据属性。例如:
<text-document |
为了简便,我们使用 .sync
修饰符,提供了这个模式的简写:
<text-document v-bind:title.sync="doc.title"></text-document> |
.sync
修饰符还可以用于 v-bind
,使用一个对象一次性设置多个 prop:
<text-document v-bind.sync="doc"></text-document> |
这会传递 doc
对象中的每个属性(例如 title
),作为单独的 prop,然后为每个属性添加相应的 v-on:update
监听器。
对一个字面量对象使用 v-bind.sync
(例如 v-bind.sync=”{ title: doc.title }”
),则不会正常运行,因为在解析像这种复杂表达式时,需要考虑太多的边界情况。