组件通信-跨级通信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>
相关推荐
BruceGerGer11 天前
flutter开发实战-flutter web加载html及HtmlElementView的使用
flutter·1024程序员节
网络冒险家2 个月前
【软考】系统集成项目管理工程师【第二版】
职场和发展·软考·集成学习·1024程序员节·系统集成项目工程师
BruceGerGer2 个月前
flutter开发实战-AssetBundle读取指定packagename的文件
flutter·1024程序员节
sheng12345678rui2 个月前
最新缺失msvcp140.dll的多种解决方法,有效解决电脑dll问题
windows·microsoft·电脑·dll文件·1024程序员节
a5553338202 个月前
电脑显示mfc140u.dll丢失的修复方法,总结7种有效的方法
java·经验分享·dll·dll文件丢失·1024程序员节
行十万里人生2 个月前
C++ 智能指针
linux·c++·git·阿里云·容器·蓝桥杯·1024程序员节
a5553338202 个月前
启动鸣潮提示错误代码126:加载d3dcompiler_43.dll错误或缺失的7个解决方法
前端·经验分享·dll·dll文件丢失·1024程序员节
BruceGerGer2 个月前
flutter开发实战-Webview及dispose关闭背景音
flutter·1024程序员节
BruceGerGer3 个月前
flutter开发实战-ListWheelScrollView与自定义TimePicker时间选择器
flutter·1024程序员节
askah66443 个月前
电脑提示msvcr120.dll丢失怎样修复
经验分享·microsoft·dll修复·dll丢失·1024程序员节