组件通信-跨级通信Provide | Inject

使用 provide/inject ,只需要向后代注入组件本身(this),后代组件中可以无视层级任意访问祖先组件中的状态。

当然它也有缺点:因为 provide/inject 中变量的修改是无法控制的。换句话说,不知道是哪个组件修改了这个全局状态

Vue 的设计理念借鉴了 React 中的单向数据流原则(虽然有 sync 这种破坏单向数据流的家伙),而 provide/inject 明显破坏了单向数据流原则。试想,如果有多个后代组件同时依赖于一个祖先组件提供的状态,那么只要有一个组件修改了该状态,那么所有组件都会受到影响。这一方面增加了耦合度,另一方面,使得数据变化不可控。如果在多人协作开发中,这将成为一个噩梦。

下面我们来看看一个小案列:

我的四个组件 App.vue(祖组件) App.vue下面有一个Navbar.vue 和一个Tabbar.vue 而Tabbar.vue组件下有一个TabbarItem.vue的组件

现在要实现的的功能是在TabbarItem.vue组件中改变Navbar.vue组件中的值

App.vue

html 复制代码
<template>
  <div>
    <Navbar :nvartitle="nvaTitle"></Navbar>
    <Tabbar></Tabbar>
  </div>
</template>
<script>
import Navbar from "./components/Navbar.vue" //导入AChild组件模板
import Tabbar from "./components/Tabbar.vue";
export default {
  inheritAttrs: false,
  data() {
    return {
      nvaTitle:"首页"
    }
  },
  components: {
    Navbar,
    Tabbar
  },
  provide(){
    return{
      myNvarTitle:this.nvaTitle, //向外提供一个值(可以供其他组件可以直接获取到)
      app:this, //向外提供一个值,这个值的名称是我们自己定义的,this表示当前根组件对象(可以供其他组件可以直接获取到)
      appMythod:this.MyAppMethod  //向外提供一个方法。
    }

  },
  methods: {
    MyAppMethod(){
      console.log("我的根组件中的方法")
    }
  }
}
</script>
<style>
#app{
  width: 100%;
  max-width: 95%;
}
* {
  margin: 0px;
  padding: 0px
}

ul {
  list-style: none;
}
body{
  display:block
}
</style>

Navbar.vue

html 复制代码
<template>
    <div>
        <button>返回</button>
        <span>{{app.nvaTitle}}</span>
        <button>首页</button>
    </div>
</template>
<script>
export default {
    props:["nvartitle"],
    inject:["myNvarTitle","app"],//在App.vue根组件中通过provide向外提供了一个myNvarTitle,和app的值,我们可以通过注入的方式获取
    components: {
    }
}
</script>
<style scoped>
div {
    display: flex;
    width: 100%;
    justify-content: space-between;
    height: 50px;
    line-height: 50px;
    background: gray;

}
</style>

Tabbar.vue

html 复制代码
<template>
    <ul>
        <TabbarItem v-for="item in datalist" :key="item" :itemStr="item"></TabbarItem>
    </ul>
</template>
<script>
import TabbarItem from "./TabbarItem.vue"
export default {
    data() {
        return {
            datalist: ["首页", "列表", "我的"]
        }
    },
    components: {
        TabbarItem
    }
}
</script>
<style scoped>
ul {
    display: flex;
    position: fixed;
    bottom: 0;
    width: 100%;
    height: 50px;
    line-height: 50px;
}

li {
    flex: 1;
    text-align: center;
}
</style>

TabbarItem.vue

html 复制代码
<template>
    <li @click="handelClick">
        {{ itemStr }}
    </li>
</template>
<script >
export default {
    props: ["itemStr"],
    inject: ["app","appMythod"],//在App.vue根组件中通过provide向外提供了一个app的值和一个appMythod的方法,我们可以通过注入的方式获取
    methods: {
        handelClick() {
            this.app.nvaTitle = this.itemStr //这个app就是根组件,根组件中有一个nvaTitle的对象,我们可以重新给他赋值,它的值变化后就会自动流向需要这个值的子组件。
            this.appMythod(); //直接调用跟组件中的方法。
        }
    }
}
</script>
相关推荐
百锦再9 小时前
第1章 Rust语言概述
java·开发语言·人工智能·python·rust·go·1024程序员节
开开心心就好12 小时前
电脑音质提升:杜比全景声安装详细教程
java·开发语言·前端·数据库·电脑·ruby·1024程序员节
hfdz_00421 天前
BUCK电路原理和设计
电源·硬件设计·1024程序员节
hazy1k1 天前
51单片机基础-IO扩展(并转串 74HC165)
stm32·单片机·嵌入式硬件·fpga开发·51单片机·1024程序员节
unable code2 天前
攻防世界-Misc-pdf
网络安全·ctf·misc·1024程序员节
第七序章2 天前
【C + +】C + + 11(中)——Lambda 表达式 + 可变参数模板
c语言·c++·算法·1024程序员节
qq19257230272 天前
23种设计模式
设计模式·1024程序员节
美狐美颜sdk2 天前
直播美颜SDK特效功能实战:从API调用到效果调优的全过程
人工智能·1024程序员节·美颜sdk·直播美颜sdk·第三方美颜sdk
码力引擎2 天前
【零基础学MySQL】第十二章:DCL详解
数据库·mysql·1024程序员节
代码村新手3 天前
数据结构-链表
1024程序员节