前言
定制小程序开发费用父子组件传参可以通过props
和emit
来实现,定制小程序开发费用但是当组件的层次结构比较深时,props
和emit
定制小程序开发费用就没什么作用了。vue为了解决这个提出了Provide / Inject
,知道这个东西,但是一直没用过,最近碰到了一个问题,踩了一些坑,在这里记录一下
备注:
我安装的是vue3.x,v-用的是3.x的语法。
2.x和3.x用法一致,我这里是用2.x写的
通用知识
基本用法
provide 选项应该是:一个对象或返回一个对象的函数
inject 选项应该是:一个字符串数组,或 一个对象,对象的 [key] 是本地的绑定名
provide 和 inject 绑定并不是可响应的。这是刻意为之的。
代码执行顺序
data->provide->created->mounted
基本代码
主要使用grandpa
和grandson
这两个组件,son
在这里充当一个层级
//grandpa.vue<template> <div> <h3 style="margin-bottom: 20px">爷爷组件</h3> <el-button type="primary" @click="lookDetail">查看</el-button> <!-- 儿子组件 --> <son v-model:visible="openDialog"></son> </div></template><script>import Son from "./son.vue";export default { components: { Son }, data() { return { message: "aa", openDialog: false, }; }, methods: { lookDetail() { this.openDialog = true; }, },};</script>//son.vue<template> <div> <el-dialog v-model="visible" title="父组件" width="50%" append-to-body @close="closeDialog"> <el-button type="primary" @click="lookDetail">查看</el-button> </el-dialog> <!-- 孙子组件 --> <grandson v-model:visible="openDialog"></grandson> </div></template><script>//孙子组件import grandson from "./grandson.vue";export default { components: { grandson, }, props: { visible: { type: Boolean, default: false, }, }, emit: ["update:visible"], data() { return { openDialog: false, }; }, methods: { closeDialog() { this.$emit("update:visible", false); }, lookDetail() { this.openDialog = true; }, },};</script>//grandson.vue<template> <div> <el-dialog v-model="visible" title="孙子组件" width="30%" @close="closeDialog"> </el-dialog> </div></template><script>export default { props: { visible: { type: Boolean, default: false, }, }, emit: ["update:visible"], data() { return {}; }, methods: { closeDialog() { this.$emit("update:visible",false) }, },};</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
如图:
基础用法: 传个字符串
简单修改一下组件
//grandpa.vueexport default { components: { Son }, provide:{ grandpaMsg:'哈哈哈' }//grandson.vue<template> <div> <el-dialog v-model="visible" title="孙子组件" width="30%" @close="closeDialog"> <div> 信息:{{grandpaMsg}} </div> </el-dialog> </div></template><script>export default { props: { visible: { type: Boolean, default: false, }, }, inject:['grandpaMsg'],
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
数据过来了,如图:
中级用法
传个字符串没啥用,如果要传data
里的一个属性呢?简单修改一下组件
//grandpa.vue components: { Son }, provide:{ grandpaMsg:this.message }, data() { return { message: "aa", openDialog: false, }; },
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
嗯,直接报错,哈哈哈。
如果要使用data
里的参数,需要这样写
//grandpa components: { Son }, provide(){ return { grandpaMsg:this.message }},
- 1
- 2
- 3
- 4
- 5
- 6
- 7
结果:
高级用法
一开始就说了这个不是响应式,简单看一下
<h3 style="margin-bottom: 20px">爷爷组件</h3> <el-button type="primary" @click="lookDetail">查看</el-button> <el-button type="primary" @click="message='abcde'">改变数据</el-button>
- 1
- 2
- 3
如图:
那如何变成响应式的呢,再简单改一下
//grandpa provide(){ return { grandpaMsg:()=>this.message } },//grandson<el-dialog v-model="visible" title="孙子组件" width="30%" @close="closeDialog"> <div> 信息:{{grandpaMsg()}} </div> </el-dialog>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
如图:
拓展:你可以直接传一个this
过去,这样孙子组件会获得爷爷组件的实例对象,这种方式也是响应式的
provide(){ return { grandpaMsg:this } },
- 1
- 2
- 3
- 4
- 5