子组件和父组件之间优雅通信---松耦合

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而导致运行时错误

优点:松耦合,子组件完全不需要知道父组件具体有哪些方法,它只需要知道自己需要触发什么指令。父组件则负责接收指令并执行对应的逻辑,这使得子组件的复用性非常高,可以轻松被不同父组件使用,只要这些父组件都实现了相应的指令并监听了对应的事件即可。

相关推荐
东东5165 分钟前
校园求职招聘系统设计和实现 springboot +vue
java·vue.js·spring boot·求职招聘·毕设
rosmis16 分钟前
地铁病害检测系统软件改进记录-2-02
开发语言·前端·javascript
css趣多多20 分钟前
解决ui组件flex1容器底部被撑开的问题
前端
乔江seven35 分钟前
【python轻量级Web框架 Flask 】2 构建稳健 API:集成 MySQL 参数化查询与 DBUtils 连接池
前端·python·mysql·flask·web
Alaaaaaaan44 分钟前
[DevOps]使用github-action工具部署docker容器(实现提交代码一键推送部署到服务器)
服务器·前端·docker·容器·github
摇滚侠1 小时前
css 设置边框
前端·css
星爷AG I1 小时前
9-24 视觉叙事(AGI基础理论)
前端·人工智能
2501_940007892 小时前
Flutter for OpenHarmony三国杀攻略App实战 - 鸿蒙适配与打包发布
前端·flutter
css趣多多2 小时前
跨域问题及Vue项目中本地/线上解决方法核心总结
前端
光影少年2 小时前
前端 AIGC
前端·aigc