provide和inject父子组件的方法或字段的传参 - 依赖注入
1、一般用法
父组件:
// 写法1
provide(){
// 使用函数的形式,可以访问到 `this`
// 如果我们需要提供依赖当前组件实例的状态 (比如那些由 data() 定义的数据属性),那么可以以函数形式使用 provide
// 然而,请注意这不会使注入保持响应性
return {
isExecute:this.isExecute
}
},
methods:{
isExecute(){
console.log("子组件调用了该方法")
}
}
// 写法2
provide: {
message: 'hello!'
}
子组件:
inject: ['isExecute'],
引入后直接this.reload()即可
2、传递响应式数据
// 为保证注入方和供给方之间的响应性链接,我们需要使用 computed() 函数提供一个计算属性
import { computed } from 'vue'
export default {
data() {
return {
message: 'hello!'
}
},
provide() {
return {
// 显式提供一个计算属性
message: computed(() => this.message)
}
}
}
3、升阶用法 - 使用 Symbol 作注入名
使用场景:
- 如果你正在构建大型的应用,包含非常多的依赖提供,或者你正在编写提供给其他开发者使用的组件库,建议最好使用 Symbol 来作为注入名以避免潜在的冲突。
- 通常推荐在一个单独的文件中导出这些注入名 Symbol:
// keys.js
export const myInjectionKey = Symbol()
// 在供给方组件中
import { myInjectionKey } from './keys.js'
export default {
provide() {
return {
[myInjectionKey]: {
/* 要提供的数据 */
}
}
}
}
// 注入方组件
import { myInjectionKey } from './keys.js'
export default {
inject: {
injected: { from: myInjectionKey }
}
}
4、栗子-Vue删除数据成功后刷新表格数据
template>
<div id="app">
<router-view v-if="isShow"></router-view>
</div>
</template>
<script>
export default {
name: 'App',
provide () {
return {
reload: this.reload
}
},
data () {
return {
isShow: true
}
},
methods: {
reload () {
this.isShow= false
this.$nextTick(function () {
this.isShow= true
})
}
}
}
</script>
然后再需要刷新的页面引入依赖:inject:[‘reload’]
<script>
export default{
name:'booklist',
inject:['reload'],
data(){
return{
在需要执行的地方直接调用方法即可:this.reload()
deletebook(val){
var formdata = new FormData()
formdata.append("val",this.val)
this.axios({
url:"自己的",
methods:'post',
data:formdata
}).then(res=>{
if(res.data.code == 200){
alert(res.data.message)
}else{
alert(res.data.message)
}
this.reload()
})
},
原理:
1、provide 用于向子组件(或子组件中的子组件,无限嵌套)提供自身的一些数据,或者将自身所有属性全部提供,但是提供的数据均为非响应式数据。provide:Object | () => Object
2、inject 用于引入父级组件所提供的数据。inject:Array
3、provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。是2.2.0版本 新增的。
4、不推荐直接使用在应用程序代码中是因为数据追踪比较困难,不知道是哪一个层级声明了这个或者不知道哪一层级或若干个层级使用了。
5、注意:子孙层的provide会掩盖祖父层provide中相同key的属性值
6、provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
为什么不使用父子组件props传值呢?
因为父子组件props传值需要需要知道往哪一个子组件传值,如el-form组件中会注入的子组件是不确定的。
provide只需要将传递的值抛出,不需要知道使用哪一个子组件,子组件通过inject注入获取数据,也不需要知道父组件是谁,因此再封装组件库的时候很便利。
使用场景:
由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject可以轻松实现跨级访问祖先组件的数据