事件名
跟组件和prop不同,事件名不存在自动化的大小写转换,而是触发的事件名需要完全匹配监听这个事件所有的名称。举个例子,如果触发了一个camelcase名字的事件
this.$emit('myevent')
则监听这个名字的kebab-case的版本是不会有任何特效的
跟组件和prop不同,事件名不会被用作一个javascript变量名或属性名,所以就没有理由使用camelcase或Pascalcase了,并且v-on事件监听器在dom模板中会被自动转化为全小写(因为html是大小写不敏感的)。所以v-on:myEvent将会变成v-on:myevent——导致myEvent不可能被监听到。
因此,我们推荐你使用kebab-case事件名
自定义组件的v-model
一个组件上的v-model默认会利用名为value的prop和名为input的事件,但是想单选框、复选框等类型的输入控件可能会将value特性用于不同的目的。model选项可以用来避免这样的冲突
vue.component('cccc',{
model:{
prop:'checked',
event:'change'
},
props:{
checked:boolean
},
template:
v-bind:checked="checked"
v-on:change="$emit('change',$event.target.checked)">
})
现在在这个组件上使用v-model的时候
这里的dddd的值会传入名为checked的prop。同时cccc触发一个change事件并附带一个新的值的时候,这个dddd的属性将会被更新
注意你仍然需要在组件的props选项里生命checked这个prop
将原生事件绑定到组件
你可能有很多次想要在一个组件的根元素上直接监听一个原生事件。这是,你可以使用v-on的.native修饰符
在有的时候这是很有用的,不过在你尝试监听一个的非常特定的元素时,这并不是好主意,比如上述
{{label}}
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input',$event.target.value)">
这时,父级的.native监听器将静默失败,他不会产生任何报错,但是onfocus处理函数不会如你预期的被调用,
为了解决这个问题,vue提供了一个$listeners属性,他是一个对象,里面包含了作用在这个组件上的所有监听器,
{focus:function(event){}
input:function(value){}}
有了这个$listener属性,你就可以配合v-on=“$listener”将所以的事件监听器指向这个组件的某个特定的子元素。对于类似的你希望他也可以配合v-model工作的组件来说,为这些监听器创建一个类似下述的inputlisteners的计算属性通常是非常有用的,
vue.component('ddd',{
inheritAttrs:false,
props:['label','value'],
computed:{
inputlisteners:function(){
var vm=this
将所有的对象合并为一个新对象
return object.assign({},
我们从父级添加所有的监听器
this.$listeners,
然后我们添加自定义监听器,或覆写一些监听器的行为)
}{
这里确保组件配合v-model工作
input,function(evnet){
vm.$emit('inout'.event.target.value)
}
}
}})
template:
{{ label }}
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
`
})可以
现在
.sync修饰符
在有些情况下 ,我们可能需要对一个prop进行双向绑定,不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。
这也是为什么我们推荐以update:my-prop-name的模式触发事件取而代之。举个例子,在一个包含title prop的假设的组件中,我们可以用以下方法表达对其赋新值的意图;
this.$emit(‘update:title’,newtitle)
然后父组件可以监听那个事件并根据需要更新一个本地的数据属性。
v-bind:title="doc.title" v-on:update:title="doc.title=$event">
为了方便起见,我们为这种模式提供了一个缩写,即.sync修饰符
当我们用一个对象同时设置多个prop的时候,也可以将这个.sync修饰符和v-bind配合使用
这样会把doc对象中的每一个属性都作为一个独立的prop传进去,然后各自添加用于更新的v-on监听器。
将v-bind.sync用在一个字面量的对象上,例如v-bind.sync="{title:doc.title}"是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。