组件通信(非父子组件)

非父子组件通信(父传孙)

父组件传递给孙组件:通过provide/inject来共享数据。

在一些深度嵌套的场景中,子组件要想获取父组件里面的部分数据,可以使用props逐级传递的方法,但这样会显得非常麻烦。所以在这种场景下,一般父组件使用provide来提供数据,而子孙组件使用inject来使用父组件提供的数据。

一般使用

三个组件,app.vue home.vue homecontent.vue,这三个为层层嵌套关系。

""" app.vue """
<template>
  <home/>
</template>

<script>
  import Home from "./home";
  export default {
    name: "App",
    components: {Home},
  }
</script>

""" home.vue """
<template>
  <homecontent/>
</template>

<script>
  import Homecontent from "./homecontent";
  export default {
    name: "home",
    components: {Homecontent}
  }
</script>

""" homecontent.vue """
<template>
  <div>
    孙组件
  </div>
</template>

<script>
  export default {
    name: "homecontent"
  }
</script>

在父组件中使用provide来定义数据。

""" app.vue 父组件 """
<template>
  <home/>
</template>

<script>
  import Home from "./home";
  export default {
    name: "App",
    components: {Home},
    provide: {
      name: "xxcfun",
      age: "18"
    }
  }
</script>

在孙组件中使用inject来使用这些数据。

""" homecontent.vue 孙组件 """
<template>
  <div>
    孙组件 <br/>
    {{name}} - {{age}}
  </div>
</template>

<script>
  export default {
    name: "homecontent",
    inject: ["name", "age"]
  }
</script>

这样就能实现非父子组件之间共享数据:

zjtxfs.png
拓展用法
  • 使用data定义的数据

如果在父组件中想使用data里面定义的数据,直接在provide中使用this来指向data数据是行不通的,在provide作用域里面是拿不到data数据的,会出现undefined的情况。

如果有这样的需求,得在provide中做下修改,把对象数据改为函数返回对象的格式。

""" app.vue """
<template>
  <home/>
</template>

<script>
  import Home from "./home";
  export default {
    name: "App",
    components: {Home},
    provide() {
      return {
        name: "xxcfun",
        age: "18",
        hobby: this.hobby,
        hobbynum: this.hobby.length
      }
    },
    data() {
      return {
        hobby: ["football", "bike"]
      }
    }
  }
</script>
""" homecontent.vue """
<template>
  <div>
    孙组件 <br/>
    {{name}} - {{age}} <br/>
    {{hobby}} - {{hobbynum}}
  </div>
</template>

<script>
  export default {
    name: "homecontent",
    inject: ["name", "age", "hobby", "hobbynum"]
  }
</script>
zjtxdata.png
  • 使用响应式数据

在父组件中添加一个点击事件,增加一个hobby。

""" app.vue """
<template>
  <home/>
  <button @click="addHobby">添加一个hobby</button>
</template>

<script>
  import Home from "./home";
  export default {
    name: "App",
    components: {Home},
    provide() {
      return {
        name: "xxcfun",
        age: "18",
        hobby: this.hobby,
        hobbynum: this.hobby.length
      }
    },
    data() {
      return {
        hobby: ["football", "bike"]
      }
    },
    methods: {
      addHobby() {
        this.hobby.push("games")
      }
    }
  }
</script>

在点击一次按钮后,会发现孙组件hobby的内容添加上了games,但后面的长度还是显示2。

zjtxerro.png

有这样的需求的话,这里得需要用到一个计算属性,每次hobby改变的时候,length也实时进行计算。

""" app.vue """
<template>
  <home/>
  <button @click="addHobby">添加一个hobby</button>
</template>

<script>
  import Home from "./home";
  import { computed } from "vue";
  export default {
    name: "App",
    components: {Home},
    provide() {
      return {
        name: "xxcfun",
        age: "18",
        hobby: this.hobby,
        hobbynum: computed(() => this.hobby.length)
      }
    },
    data() {
      return {
        hobby: ["football", "bike"]
      }
    },
    methods: {
      addHobby() {
        this.hobby.push("games")
      }
    }
  }
</script>

这样点击两次后,增加了两个games,后面的数量也变成了4。

zjtxcom.png

~END

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容