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

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

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

相关推荐
雨季mo浅忆15 小时前
Cursor快速实现上传Excel功能
前端·vue3·ai编程
韩曙亮15 小时前
【Flutter】Flutter 编译 Web 网站 ① ( Tomcat 部署 Web 网站 )
前端·flutter·tomcat·web
古怪今人15 小时前
手工搭建PC端:pnpm + Vite + Vue3 + Element Plus + Electron
前端·vue.js·electron
共创splendid--与您携手16 小时前
AI读取前端项目生成skill.md
前端·人工智能·ai
San813_LDD17 小时前
[C语言]《Dev-C++ 报错解决手册(Day0607 精华版)》
java·前端·javascript
xiaofeichaichai1 天前
Webpack
前端·webpack·node.js
问心无愧05131 天前
ctf show web入门111
android·前端·笔记
唐某人丶1 天前
模型越来越强,我们还需要 Agent 工程吗?—— 从价值重估到 Harness 实践
前端·agent·ai编程
智码看视界1 天前
现代Web开发基础:全栈工程师的起航点
前端·后端·c5全栈
JS菌1 天前
手写一个 AI Agent 全栈项目:从沙箱执行到子智能体的完整实现
前端·人工智能·后端