.native
vue自定义组件中我们一般在父组件中定义一个事件,然后在子组件中利用emit触发这个事件。此时,如果我们的父组件中的事件用.native修饰,那么就相当于这个事件给子组件的根元素绑定了。
import child from './child'
export default{
name:'index',
components:{child},
methods:{
click(ev){
console.log('click');
}
}
}
export default {
name: 'child',
}
加了.native后,相当于给子组件的根元素绑定了事件,也就是上面的input外的div元素。
$listeners
上面.native表示将事件绑定到子组件的根元素上,那如果不想绑定到根元素上,除了用emit主动触发外,还可以用v-on='$listeners',这个操作就表示把外层的事件绑定到自己这。
import child from './child'
export default{
name:'index',
components:{child},
methods:{
click(ev){
console.log('click');
}
}
}
export default {
name: 'child',
}
$listeners返回从父组件上绑定的各种事件。注意,$listeners中的事件不包括.native中的事件,因为.native事件已经给了子组件的根节点。
如果父组件中使用的是v-model,那么$listeners里面会包含一个input事件的方法,如果要让这个事件正常运转(把子组件的内容传达给父组件),需要稍微改写一下。
import child from './child'
export default{
name:'index',
components:{child},
data(){
return{
name:'张三'
}
},
}
export default {
name: 'child',
computed: {
inputListeners() {
var vm = this
// `Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `v-model` 的工作
input: function(event) {
vm.$emit('input', event.target.value)
}
});
}
}
}
因为默认的v-model中的input事件传递的是事件对象本身,我们需要将$listeners中的input事件改写成传递内容的。
$attrs,$props,inheritAttrs
从父组件中通过v-bind,v-model或者直接写的属性值在子组件中都会在$attrs中(style和class不在其中),子组件中可以通过配置props定义子组件中的变量,props最大选择就是$attrs,props每选一个,$attrs中就少一个变量了。因此$props和$attrs的合集就是父组件传递下来的所有属性。
默认情况下$attrs属性(注意不是所有属性)会继承到子组件的根元素上,如果不想$attrs属性继承到子组件的根元素上,可以在子组件中设置inheritAttrs:false,同时可以用v-bind='$attrs'将$attr属性给到某个指定的元素上。(无论inheritAttrs设置true或false,class和style都不受的影响,它们会和子组件的根元素的class和style内容合并)
import child from './child'
export default{
name:'index',
components:{child},
data(){
return{
name:'张三',
}
},
}
export default {
inheritAttrs: false,
name: 'child',
props:['name'],
}
上面的例子中,父组件传了两个属性,name和title,props中取了一个name属性,那么$attrs中还剩下title。同时我们用inheritAttrs:false不让子组件的根元素继承$attr属性,并利用v-bind='$attr'把$attrs属性放到了input上。
v-bind.sync='***'
.sync和v-model比较像,可以同时绑定属性值和一个回调方法,例如v-bind:name.sync='name',那么相当于v-bind:name='name',v-on:update:name='name=$event'。也就是说在子组件中,可以通过emit('update:name',event.target.value)给父组件传回值。
比较注意的是bind.sync='obj'这种写法,这里的obj是一个对象,内部会把对象展开,然后每个属性执行一次v-bind:[key].sync='[key]'。
import child from './child'
export default{
name:'index',
components:{child},
data(){
return{
obj:{
name:'张三',
age:20
}
}
},
}
{{name}}
{{age}}
change name
change age
export default {
name: 'child',
props:['name','age'],
}