vue 跨层组件通讯 provide inject

原创
2019/11/11 23:21
阅读数 556

 

原文链接: vue 跨层组件通讯 provide inject

上一篇: vue 跨层组件通讯 $attrs $listeners

下一篇: ts reference path 类型声明文件

https://cn.vuejs.org/v2/api/#provide-inject

  • 类型

    • provideObject | () => Object
    • injectArray<string> | { [key: string]: string | Symbol | Object }
  • 详细

    provide 和 inject 主要为高阶插件 / 组件库提供用例。并不推荐直接用于应用程序代码中。

    这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

    provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作。

    inject 选项应该是:

    • 一个字符串数组,或
    • 一个对象,对象的 key 是本地的绑定名,value 是:
      • 在可用的注入内容中搜索用的 key (字符串或 Symbol),或
      • 一个对象,该对象的:
        • from 属性是在可用的注入内容中搜索用的 key (字符串或 Symbol)
        • default 属性是降级情况下使用的 value

    提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

 

 

对象不是响应式的,但是对象的属性是响应式的

 

A

如果只是传递值, 则直接传递即可, 但要是想使用响应式数据, 需要包装

不仅可以传递data, 也可以传递方法, 这种通讯方式灵活, 并且代码量少且直观

<template>
  <div>
    <h1>A</h1>
    <h3>{{a}} - {{b.name}} - {{c}}</h3>
    ---
    <B @text-change="change"></B>
  </div>
</template>

<script>
  import B from './B'

  export default {
    components: {
      B
    },
    data() {
      return {
        a: "Aa",
        b: {name: "Ab"},
        c: "Ac"
      }
    },
    provide() {
      return {
        a: this.a,
        b: this.b,
        c: this.c,
        change: this.change
      }
    },
    methods: {
      change(val) {
        console.log("A change, ", val)
        this.b.name += "C"
      }
    }
  }
</script>

<style scoped>

</style>

 

B

<template>
  <div>
    <h1>B</h1>
    <h3>{{a}} - {{b.name}} - {{c}}</h3>
    ---
    <C></C>
  </div>
</template>

<script>
  import C from './C'

  export default {
    components: {
      C
    },
    props: ['a'],
    inject: ['a', 'b', 'c']
  }
</script>

<style scoped>

</style>

 

C

可以调用A中的方法, 并且对象的属性时响应式的, A中变化后, C中也会同步变化

<template>
  <div>
    <h1>C</h1>
    <h3>{{Ca}} - {{Cb.name}} - {{Cd}}</h3>
    <button @click="change">change</button>
  </div>
</template>

<script>
  export default {
    inject: {
      'Ca': {
        from: 'a'
      },
      'Cb': {
        from: 'b',
      },
      "Cd": {
        from: 'd',
        // 可以使用值或者函数
        default: () => 'Cd'
      },
      "Achange": {
        from: "change"
      }
    },
    methods: {
      change() {
        // 直接赋值不会触发更新
        // this.$attrs['b'] = 'Cb'

        console.log("C change")
        this.Achange("Cb")
        // this.$emit('text-change', "Cb")
      }
    }
  }
</script>

<style scoped>

</style>

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部