1、传统的写法
js
// 父组件
<!-- 父组件 -->
<template>
<ChildComponent
@tabActiveFn="onTabActiveUpdate"
/>
<button @click="goOrder"></button>
</template>
<script>
export default {
methods: {
refresh() {
console.log('刷新数据');
},
onTabActiveUpdate(newValue) {
this.tabActive = newValue;
this.refresh();
},
goOrder(){
this.$router.replace({ name: 'order' });
},
}
}
</script>
js
// 子组件
<!-- 子组件 -->
<template v-for="(item, index) in TAB">
<span :key="index" :class="[tabActive === item.index ? 'active' : 'tab']" @click="changeTab(item)"> {{ item.name }}</span>
<button @click="goOrder"></button>
</template>
<script>
export default {
data() {
return {
tabActive: 1,
TAB: [
{ index: 1, name: 'xxx服务' },
{ index: 2, name: 'xxx服务' }
],
},
methods: {
changeTab(item) {
this.$emit('tabActiveFn', item.index);
this.tabActive = item.index;
},
goOrder(){
this.$router.replace({ name: 'order' });
},
}
}
</script>
2、使用语法糖
- (1)父组件定义一个万能方法
onInvoke(action) { this[action]?.(); },根据传入的字符串调用对应方法。 - (2)父组件通过自定义事件@invokeFn
<ChildComponent @invokeFn="onInvoke"/>暴露给子组件。 - (3)子组件
<button @click="$emit('invokeFn', 'goOrder')"></button>,点击时,触发父组件invokeFn事件并传值goOrder - (4)父组件收到事件,执行
onInvoke('goOrder'),最终安全调用goOrder方法。
js
// 父组件
<!-- 父组件 -->
<template>
<ChildComponent
@tabActiveFn="onTabActiveUpdate"
@invokeFn="onInvoke"
/>
</template>
<script>
export default {
methods: {
refresh() {
// 刷新数据
console.log('刷新数据');
},
onTabActiveUpdate(newValue) {
this.tabActive = newValue;
this.refresh();
},
goOrder(){
this.$router.replace({ name: 'order' });
},
onInvoke(action) {
this[action]?.();
},
}
}
</script>
js
// 子组件
<!-- 子组件 -->
<template v-for="(item, index) in TAB">
<span :key="index" :class="[tabActive === item.index ? 'active' : 'tab']" @click="changeTab(item)"> {{ item.name }}</span>
<button @click="$emit('invokeFn', 'goOrder')"></button>
</template>
<script>
export default {
data() {
return {
tabActive: 1,
TAB: [
{ index: 1, name: 'xxx服务' },
{ index: 2, name: 'xxx服务' }
],
},
methods: {
changeTab(item) {
this.$emit('tabActiveFn', item.index);
this.tabActive = item.index;
}
}
}
</script>
其中,this.[action],使用方括号语法,动态的访问当前对象(this)上名为action变量值的属性或者方法。例如:action是'goOrder',它就试图获取this.goOrder。
?()是可选链操作符 和函数 的结合,如果this.[action]的值不是null或者undefined,则调用该函数;如果是,则整个表达式短路,返回undefined,而不会抛出错误。
可选链?.是ES2020中引入的一个非常实用的语法。它的核心价值是在于防止在访问嵌套属性或者方法时,因中间某个值为null或者undefined而导致运行时错误。