【vue】vue 组件事件监听”$listeners”,重写父组件事件传递
vue 组件事件监听”$listeners”,重写父组件事件传递
基本环境库:vue.js、element-ui
初始版本代码
<div id="app" >
<el-button>你好世界</el-button>
<test-componend @change="onParentChange" ></test-componend>
</div>
<template id='testComponend' >
<el-select v-model="value" v-on="$listeners" placeholder="请选择" @change="onSelectChange">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
const testComponend = Vue.component( 'testComponend',{
template: '#testComponend',
data(){
return {
options: [
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' }
],
value: ''
}
},
methods: {
onSelectChange(value) {
const selectObj = this.options.find((item) => (item.value === value));
this.$emit('change', selectObj);
}
}
})
var app = new Vue({
el: '#app',
components: {
'test-componend': testComponend
},
methods: {
onParentChange(select) {
console.log('使用层:', select);
}
}
})
执行情况:
操作步骤:点击选择器,选中一个选项;
期望输出结果:
使用层: { value: '选项1', label: '黄金糕' }
实际输出结果:
使用层: { value: '选项1', label: '黄金糕' }
使用层: 选项1
改进后代码
<div id="app" >
<el-button>你好世界</el-button>
<test-componend
@change="onParentChange"
></test-componend>
</div>
<template id='testComponend' >
<el-select v-model="value" v-on="new$listeners" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
const testComponend = Vue.component( 'testComponend',{
template: '#testComponend',
data(){
return {
options: [
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' }
],
value: ''
}
},
computed: {
new$listeners() {
return Object.assign(this.$listeners, {
change: this.onSelectChange
})
}
},
methods: {
onSelectChange(value) {
const selectObj = this.options.find((item) => (item.value === value));
this.$emit('change', selectObj);
}
}
})
var app = new Vue({
el: '#app',
components: {
'test-componend': testComponend
},
methods: {
onParentChange(select) {
console.log('使用层:', select);
}
}
})
执行情况:
操作步骤:点击选择器,选中一个选项;
期望输出结果:
使用层: { value: '选项1', label: '黄金糕' }
实际输出结果:
使用层: { value: '选项1', label: '黄金糕' }
问题分析
-
为什么收到两次回调返回值不一样:
使用层: { value: '选项1', label: '黄金糕' } 使用层: 选项1
第一行 返回值打印是自定义testComponend组件处理的返回结果;
第二行 返回值打印是监听到el-select组件原有事件回调;
-
为什么选择一次改变会发生两次事件回调:
<el-select v-model="value" v-on="$listeners" placeholder="请选择" @change="onSelectChange">
因为有两个事件监听函数,第一个是
v-on="$listeners"
第二个是@change="onSelectChange"
;
解决思路
-
自定义组件testComponend内,移除
@change="onSelectChange"
<el-select v-model="value" v-on="$listeners" placeholder="请选择" >
解决收到两次事件;
-
自定义组件testComponend内,重新计算
$listeners
对象,并将自定义事件赋值给对象内change
属性;computed: { new$listeners() { return Object.assign(this.$listeners, { change: this.onSelectChange }) } }
解决出现el-select原有事件回调值,将自定义change事件函数覆盖el-select组件change事件函数;
总结
自定义组件 监听 $listeners
,不会因为我们在自定义组件使用自定义事件而拦截原有父作用域事件回调,如需要使用 v-on="new$listeners"
继承原有父作用域事件并使用自定义回调参数,需覆写原有事件并监听;
测试mode
快乐的狗蛋
快乐的狗蛋
宣传栏
目录
vue 组件事件监听”$listeners”,重写父组件事件传递
基本环境库:vue.js、element-ui
初始版本代码
<div id="app" >
<el-button>你好世界</el-button>
<test-componend @change="onParentChange" ></test-componend>
</div>
<template id='testComponend' >
<el-select v-model="value" v-on="$listeners" placeholder="请选择" @change="onSelectChange">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
const testComponend = Vue.component( 'testComponend',{
template: '#testComponend',
data(){
return {
options: [
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' }
],
value: ''
}
},
methods: {
onSelectChange(value) {
const selectObj = this.options.find((item) => (item.value === value));
this.$emit('change', selectObj);
}
}
})
var app = new Vue({
el: '#app',
components: {
'test-componend': testComponend
},
methods: {
onParentChange(select) {
console.log('使用层:', select);
}
}
})
执行情况:
操作步骤:点击选择器,选中一个选项;
期望输出结果:
使用层: { value: '选项1', label: '黄金糕' }
实际输出结果:
使用层: { value: '选项1', label: '黄金糕' }
使用层: 选项1
改进后代码
<div id="app" >
<el-button>你好世界</el-button>
<test-componend
@change="onParentChange"
></test-componend>
</div>
<template id='testComponend' >
<el-select v-model="value" v-on="new$listeners" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
const testComponend = Vue.component( 'testComponend',{
template: '#testComponend',
data(){
return {
options: [
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' }
],
value: ''
}
},
computed: {
new$listeners() {
return Object.assign(this.$listeners, {
change: this.onSelectChange
})
}
},
methods: {
onSelectChange(value) {
const selectObj = this.options.find((item) => (item.value === value));
this.$emit('change', selectObj);
}
}
})
var app = new Vue({
el: '#app',
components: {
'test-componend': testComponend
},
methods: {
onParentChange(select) {
console.log('使用层:', select);
}
}
})
执行情况:
操作步骤:点击选择器,选中一个选项;
期望输出结果:
使用层: { value: '选项1', label: '黄金糕' }
实际输出结果:
使用层: { value: '选项1', label: '黄金糕' }
问题分析
-
为什么收到两次回调返回值不一样:
使用层: { value: '选项1', label: '黄金糕' } 使用层: 选项1
第一行 返回值打印是自定义testComponend组件处理的返回结果;
第二行 返回值打印是监听到el-select组件原有事件回调;
-
为什么选择一次改变会发生两次事件回调:
<el-select v-model="value" v-on="$listeners" placeholder="请选择" @change="onSelectChange">
因为有两个事件监听函数,第一个是
v-on="$listeners"
第二个是@change="onSelectChange"
;
解决思路
-
自定义组件testComponend内,移除
@change="onSelectChange"
<el-select v-model="value" v-on="$listeners" placeholder="请选择" >
解决收到两次事件;
-
自定义组件testComponend内,重新计算
$listeners
对象,并将自定义事件赋值给对象内change
属性;computed: { new$listeners() { return Object.assign(this.$listeners, { change: this.onSelectChange }) } }
解决出现el-select原有事件回调值,将自定义change事件函数覆盖el-select组件change事件函数;
总结
自定义组件 监听 $listeners
,不会因为我们在自定义组件使用自定义事件而拦截原有父作用域事件回调,如需要使用 v-on="new$listeners"
继承原有父作用域事件并使用自定义回调参数,需覆写原有事件并监听;
测试mode