Vue 的provide 和 inject使用(组件是嵌套关系,但是并不是父子关系)

文章目录

    • 文章参考
    • 问题描述
    • 官方案例
      • 问题描述说明?
      • 解决思路
    • 如何理解 provide 和 inject
    • 使用场景
    • API 使用说明
      • provide:Object | () => Object
        • 值是对象
        • 值是一个function返回对象
      • inject:Array | { [key: string]: string | Symbol | Object }
        • 数组接收父组件的provider
        • JSON对象接收
        • 设置默认值使其变成可选项
    • 例子
      • Vue-cli脚手架中使用
      • HTML页面中使用

文章参考

  1. vue中provide和inject使用
  2. Vue官网-依赖注入
  3. Vue 依赖注入 - Provide/Inject
  4. provide-inject API 官网例子

问题描述

  1. 在工作中,发现 一个组件中添加一个添加搜索按钮的属性,就会影响到另外一个搜索的组件,这两个组件同时被一个“布局”组件包裹,不管我怎么控制相关的属性,都没有办法让搜索内容显示出来,最后查看了源码,了解到了使用的技术点 —— inject 和 provider

官方案例

看了很多网上的博客,场景应用大部分都形容的不怎么贴切,我个人更喜欢官网的例子

<google-map>
  <google-map-region v-bind:shape="cityBoundaries">
    <google-map-markers v-bind:places="iceCreamShops">google-map-markers>
  google-map-region>
google-map>

问题描述说明?

  1. 这两个组件都需要依赖 gooogleMap 实例对象
  2. 而gooogleMap 实例对象是在 组件中的
  3. 与 ( )这两个组件是嵌套关系,但是并不是父子关系
  4. 问题是如何把这个实例对象传递给嵌套在里面两个组件中去呢?

解决思路

  1. 把gooogleMap 实例对象 放到他们共用的父组件中,然后通过父组件传递给子组件
  2. 使用Vuex存储 googleMap对象
  3. 使用provide 和 inject; 也是我们今天要学习的内容

如何理解 provide 和 inject

  1. provide 选项允许我们指定我们想要提供给后代组件的数据/方法
  2. 使用 inject 选项来接收指定的我们想要添加在这个实例上的 property

个人理解:

就是说在组件中定以了一个provide属性,提供当前组件中的某些数据或者方法,组件的 children 节点组件使用inject方式就能获取到提供provide的数据或者方法,类似于React中的Provider 和 Consumer

使用场景

组件是嵌套关系,但是并不是父子关系

API 使用说明

provide:Object | () => Object

值是对象

export default {
  ...
  // 父级组件提供 'foo'
  provide: {
    foo: 'bar'
  }
}

值是一个function返回对象

export default {
  ...
  provide: function () {
    return {
      screenContext: this
    }
  }
}

inject:Array | { [key: string]: string | Symbol | Object }

数组接收父组件的provider

// 子组件注入 'foo'
export default {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

JSON对象接收

export default {
  inject: { 
	foo: "foo"
  },
  // ...
}

设置默认值使其变成可选项

如果它需要从一个不同名字的 property 注入,则使用 from 来表示其源 property

export default {
  inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
  }
}

例子

Vue-cli脚手架中使用

  1. provider 提供数据给子组件
export default {
  name: 'Screen',
  provide: function () {
    return {
      screenContext: this // 把当前Vue对象提供给所有子组件可以访问
    }
  },
}  
  1. 子组件使用inject 接受父组件传递的值
export default {
  inject: {
    screenContext: {
      from: 'screenContext'
    }
  },
  methods: {
    createLineChart () {
      this.screenContext.selectCreateTime = 'fghjkl' // 直接改变父组件的值
    }
  }
}

HTML页面中使用


<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>provide + injecttitle>
  <script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js">script>
head>
<body>
  <div id="app">div>
body>
html>

<script>
  Vue.component('A', {
    template: `
      
`
, provide: { msg: '1234124' } }) Vue.component('B', { template: `
{{ this.msg }}
`
, provide: { msg: '42341234', name: 'asdasda' }, inject: ['msg'], }) Vue.component('C', { template: `
{{ this.xingming }} {{ this.msg }}
`
, inject: { xingming: { // 给变量重命名 from: 'name', default: '' }, msg: { from: 'msg', default: '' } }, data() { return { } }, }) var app=new Vue({ el: '#app', template: ` ` });
script>
  1. inject定以的数据使用 this.名 方式调用,例如 this.msg
  2. this.xingming 重新定义了变量,但是值是从父组件定义的 msg 名字的值

运行结果:
在这里插入图片描述

你可能感兴趣的:(Vue2.x,vuex,iview,vux)