Vue2.x 的provide 和 inject使用(组件是嵌套关系,但是并不是父子关系)
文章目录文章参考问题描述官方案例问题描述说明?解决思路如何理解 provide 和 inject使用场景使用方式例子文章参考vue中provide和inject使用Vue官网-依赖注入Vue 依赖注入 - Provide/Inject问题描述在工作中,发现 一个组件中添加一个添加搜索按钮的属性,就会影响到另外一个搜索的组件,这两个组件同时被一个“布局”组件包裹,不管我怎么控制相关的属性,都没有办法
·
文章目录
文章参考
问题描述
- 在工作中,发现 一个组件中添加一个添加搜索按钮的属性,就会影响到另外一个搜索的组件,这两个组件同时被一个“布局”组件包裹,不管我怎么控制相关的属性,都没有办法让搜索内容显示出来,最后查看了源码,了解到了使用的技术点 —— 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>
问题描述说明?
- <google-map-region> 和 <google-map-markers> 这两个组件都需要依赖 gooogleMap 实例对象
- 而gooogleMap 实例对象是在 <google-map>组件中的
- <google-map> 与 (<google-map-region> )这两个
组件是嵌套关系,但是并不是父子关系
- 问题是如何把这个实例对象传递给嵌套在里面两个组件中去呢?
解决思路
- 把gooogleMap 实例对象 放到他们共用的父组件中,然后通过父组件传递给子组件
- 使用Vuex存储 googleMap对象
- 使用provide 和 inject; 也是我们今天要学习的内容
如何理解 provide 和 inject
- provide 选项允许我们指定我们想要提供给后代组件的数据/方法
- 使用 inject 选项来接收指定的我们想要添加在这个实例上的 property
个人理解:
就是说在组件中定以了一个provide属性,提供当前组件中的某些数据或者方法,组件的 children 节点组件使用inject方式就能获取到提供provide的数据或者方法,类似于React中的Provider 和 Consumer
使用场景
组件是嵌套关系,但是并不是父子关系
API 使用说明
provide:Object | () => Object
值是对象
export default {
...
// 父级组件提供 'foo'
provide: {
foo: 'bar'
}
}
要访问组件实例(this) property,我们需要将 provide 转换为返回对象的函数
值是一个function返回对象(推荐,Vue3不支持)
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脚手架中使用
- provider 提供数据给子组件
export default {
name: 'Screen',
provide: function () {
return {
screenContext: this // 把当前Vue对象提供给所有子组件可以访问
}
},
}
- 子组件使用inject 接受父组件传递的值
export default {
inject: {
screenContext: {
from: 'screenContext'
}
},
methods: {
createLineChart () {
this.screenContext.selectCreateTime = 'fghjkl' // 直接改变父组件的值
}
}
}
HTML页面中使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>provide + inject</title>
<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: `
<div>
<B></B>
</div>
`,
provide: {
msg: '1234124'
}
})
Vue.component('B', {
template: `
<div>
<label>B:</label>
<span>{{ this.msg }}</span>
<C></C>
</div>
`,
provide: {
msg: '42341234',
name: 'asdasda'
},
inject: ['msg'],
})
Vue.component('C', {
template: `
<div>
<label>C:</label>
<span>{{ this.xingming }}</span>
<span>{{ this.msg }}</span>
</div>
`,
inject: {
xingming: { // 给变量重命名
from: 'name',
default: ''
},
msg: {
from: 'msg',
default: ''
}
},
data() {
return {
}
},
})
var app=new Vue({
el: '#app',
template: `
<div>
<A />
</div>
`
});
</script>
- inject定以的数据使用
this.名
方式调用,例如 this.msg- this.xingming 重新定义了变量,但是值是从父组件定义的 msg 名字的值
运行结果:
更多推荐
已为社区贡献32条内容
所有评论(0)