vue组件通信传值的⼏⼤⽅法及组件通信provideinject的使⽤
  我们可以总结下组件通信的⼏⼤⽅法:
⼀、props属性传递数据
⼆、$emit、@on,事件触发与事件监听
三、状态管理 vuex,或者 Vue.observale()进⾏状态管理
四、ref引⽤获取组件实例
五、$parent、$children,获取当前组件的⽗组件、⼦组件
六、通过 provide / inject 来实现共享数据
  我们主要看下 provide 和 inject ⽅式。先可以看官⽹描述:
  provider/inject:简单的来说就是在⽗组件中通过provider来提供变量,然后在⼦组件中通过inject来注⼊变量。
  这种⽅式可以避免在使⽤props传值时,必须将每⼀个属性都传递给⼦组件的写法,当使⽤的公共组件不确定会被传递什么值的时候,使⽤这种写法⾮常⽅便。
<div>
<childCom></childCom>
</div>
</template>
<script>
import childCom from'../components/childCom'
export default {
name: "Parent",
provide: {      //重要⼀步,在⽗组件中注⼊⼀个变量
msg: "demo"
},
components:{
childCom
}
}
//⼦组件⽰例,这个不管嵌套了多少层,都能请求到⽗组件中注册的变量
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default {
name: "childCom",
inject: ['msg'],//⼦孙组件中使⽤inject接住变量即可
}
</script>
1、基本使⽤⽅法:
// 祖先组件提供foo
//第⼀种
export default {
name: "grandfather",
provide(){
return{
foo:'halo'
}
},
}
//第⼆种
export default {
name: "grandfather",
provide:{
foo:'halo~~~~'
},
}
/
/后代组件注⼊foo
export default {
inject:['foo'],
}
  上⾯两种的区别:如果你只是传⼀个字符串,像上⾯的‘halo’,那么是没有区别的,后代都能读到。如果你需要传⼀个对象(如下所⽰代码),那么第⼆种是传不了的,后代组件拿不到数据。所以建议只写第⼀种
//当你传递对象给后代时
provide(){
return{
test:this.msg
}
},
  注意:⼀旦注⼊了某个数据,⽐如上⾯⽰例中的 msg、foo,那这个组件中就不能再声明 msg、foo 这个数据了,因为它已经被⽗级占有。
2、实例
  我们来看个例⼦:孙组件 D、E 和 F 获取 A 组件传递过来的 color 值,并能实现数据响应式变化,即 A 组件的 color 变化后,组件 D、E、F 跟着变(核⼼代码如下:)
  ⽅法⼀:provide 祖先组件的实例,然后在⼦孙组件中注⼊依赖,这样就可以在⼦孙组件中直接修改祖先组件的实例的属性,不过这种⽅法有个缺点就是这个实例上挂载很多没有必要的东西⽐如 props,methods
  ⽅法⼆:使⽤ 2.6 最新 API Vue.observable 优化响应式 provide(推荐)
// A 组件
<div>
<h1>A 组件</h1>
<button @click="() => changeColor()">改变color</button>
<ChildrenB />
<ChildrenC />
</div>
......
color: "blue"
};
},
// provide() {
//  return {
//    theme: {
//      color: lor //这种⽅式绑定的数据并不是可响应的
//    } // 即A组件的color变化后,组件D、E、F不会跟着变
//  };
// },
provide() {
return {
vue中reactive
theme: this //⽅法⼀:提供祖先组件的实例
};
},
methods: {
changeColor(color) {
if (color) {
} else {
}
}
}
// F 组件
<template functional>
<div class="border2">
<h3 :>F 组件</h3>
</div>
</template>
<script>
export default {
inject: {
theme: {
//函数式组件取值不⼀样
default: () => ({})
}
}
};
</script>
  ⽅案1的⽅法就是因为provide提供的数据不是双向绑定的,所以祖⽗组件变化,孙组件获取的inject注⼊的值不变。为了实现双向绑定呢,就采⽤了直接在provide⾥把整个祖⽗组件的实例都传给了孙组件,那么祖⽗组件的值变化了,孙组件从祖⽗组件实例⾥拿的值也变化了。缺点就是这个祖⽗组件实例挂载了太多不需要的东西。
// ⽅法⼆:使⽤2.6最新API Vue.observable 优化响应式 provide
provide () {
this.theme = Vue.observable({
color: "blue"
});
return {
theme: this.theme
};
},
methods: {
changeColor(color) {
if (color) {
lor = color;
} else {
lor = lor === "blue" ? "red" : "blue";
}
}
}
  ⽅法三:provide⾥返回⼀个函数,获取组件的动态数据。
  实际情况中往往我们需要的是共享⽗组件⾥⾯的动态数据,这些数据可能来⾃于data 或者 store。就是说⽗组件⾥⾯的数据发⽣变化之后,需要同步到⼦孙组件⾥⾯。这时候该怎么做呢?
  我想的是将⼀个函数赋值给provide的⼀个值,这个函数返回⽗组件的动态数据,然后在⼦孙组件⾥⾯调⽤这个函数。实际上这个函数存储了⽗组件实例的引⽤,所以每次⼦组件都能获取到最新的数据。代码长下⾯的样⼦:
  Parent组件:
<template>
<div class="parent-container">
Parent组件
<br/>
<button type="button" @click="changeName">改变name</button>
<br/>
Parent组件中 name的值: {{name}}
<Child  v-bind="{name: 'k3vvvv'}" />
</div>
</template>
<style scoped>
.parent-container {
padding: 30px;
border: 1px solid burlywood;
}
</style>
<script>
import Child from'./Child'
export default {
name: 'Parent',
data () {
return {
name: 'Kevin'
},
methods: {
changeName (val) {
this.name = 'Kev'
}
},
provide: function () {
return {
nameFromParent: this.name,
getReaciveNameFromParent: () => this.name
}
},
components: {
Child
}
}
</script>
  GrandSon组件:
<template>
<div class="grandson-container">
Grandson组件
<br/>
{{nameFromParent}}
<br/>
{{reactiveNameFromParent}}
</div>
</template>
<style scoped>
.grandson-container {
padding: 30px;
border: 1px solid burlywood;
}
</style>
<script>
export default {
inject: ['nameFromParent', 'getReaciveNameFromParent'],
computed: {
reactiveNameFromParent () {
ReaciveNameFromParent()
}
},
watch: {
'reactiveNameFromParent': function (val) {
console.log('来⾃Parent组件的name值发⽣了变化', val)
}
},
mounted () {
console.log(this.nameFromParent, 'nameFromParent')
}
}
</script>
  第⼀个kevin 是来⾃于⾮响应式的 provide变量 nameFromParent
  第⼆个来⾃于reactiveNameFromParent ,随着祖先组件变化⽽变化了

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。