内容提要:
- 事件名称命名注意事项
- 自定义组件v-model的不同用法
- 为组件绑定本地事件
- .sync修饰符的用法
这页假定你已经阅读了组件基础Components Basics,如果你是组件新手请先阅读它。
不像组件和props,事件名称不存在自动大小写转换。相反,事件被发出的名字必须与被监听的名字完全一致,例如,如果发送了一个 cameCased的事件名称:
this.$emit('myEvent')
若监听kebab-cased版本的则没有效果:
不像组件和props,在JavaScript中,事件名称将绝对不会被用于事件名或属性名,所以没有理由去使用camelCase 或 PascalCase的书写格式。另外,v-on
事件监听在DOM模板内部将自动被转化为小写(由于HTML是大小写不敏感的),所以 v-on:myEvent
将变成myEvent-使事件无法被监听。
由于这些理由,我们建议你总是用kebab-case(横线分隔)书写格式的事件名。
v-model
2.2.0 + 新增
默认的,在组件中的v-model
使用value
作为prop,使用input
作为事件。但是一些输入类型像是选择框和单选按钮可能使用属性的value用于不同的目的different purpose。使用model
能避免这个例子里的冲突:
Vue.component('base-checkbox',{
model:{
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
`
})
现在当在这个组件上使用v-model
的时候:
loveVue
的值将被传递给checked
prop。当base-checkbox标签使用一个新值发出一个change
事件的时候,The loveingVue
属性将被更新。
注意:你必须声明
checked
prop在组件的用props
操作符。
有时候你可能想要在组件的根元素直接监听原生事件。在这些例子中,你能够使用在v-on
的.native
修饰符:
这有时是有用的,但当你试着监听一个特定的元素的时候可能并不是一个好主意。像一个input标签。例如,base-input标签组件之上可能被重构,使其根元素实际上是一个元素。
在那种情况下,.native
在父视图的监听器将会默默的断开。不会有错误,但是onFocus
管理者不会在我们希望的时候被调用。
为了解决这个问题,Vue提供了一个$listeners
属性,该属性包含在组件上使用的一个监听器对象。例如:
{
focus:function (event) { /* ... */ }
input: function (value) { /* ... */ }
}
使用$listeners
属性,你可以使用v-on="$listeners"
将组件上所有的事件监听者给到指定的子元素。对于元素像,你也想和v-model
一起工作,为监听器创建一个新的计算属性通常很有用,像如下inputListeners
:
Vue.component('base-input',{
inheritAttrs:false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// 'Object.assign'将对象合并到一起形成一个新对象
return Object.assign({},
// 我们从父节点添加所有的监听器
this.listeners,
// 然后我们增加自定义的监听器或腹泻一些监听器的行为
{
// 这会保证v-model和model一起工作
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template:`
`
})
.sync
修饰符2.3.0+ 新增
在一些情况下,我们需要为prop做双向绑定。不巧的是,真正的双向绑定会产生维护问题,因为子组件能够改变父组件,且子组件和父组件都没有明显的改变来源。
这就是为什么,我们建议使用update:myPropeName
模式触发事件代替。例如,假设组件有一个title
prop,我们可以用以下方法表达分配一个新值的意图:
this.$emit('update:title', newTitle)
然后父组件能够监听到事件,而后可以根据需要更新本地的属性数据,例如:
为了方便,我们使用.sync
修饰符提供了这个模式的一个快捷方式:
注意:使用
.sync
修饰符的v-bind
不能和表达式一起工作(eg:v-bind:title.sync="doc.title + '!'"
是无效的)。相反,你必须提供一个你想要去绑定的属性名,类似v-model
。
当使用一个对象一次去设置多个props,也可以用.sync修饰符:
这会传递给每一个在doc
对象中的属性(例如:title
)作为一个单独的prop,而后提交v-on
为每一个prop更新监听器。
在一个字面值对象使用
v-bind.sync
例如在v-bind.sync="{ title: doc.title }"
,将不能工作,因为在解析这个复杂表达式的时候有很多边缘情况要考虑。