1. 父组件向子组件传值
父组件通过 prop 给子组件下发数据,子组件通过$emit触发事件给父组件发送消息,即 prop 向下传递,事件向上传递。
- 新建父组件文件
<template>
<div>
父组件:
<input type="text" v-model="name">
<!--引入子组件-->
//这里传的是一个变量值(可修改的,所以要使用v-bind属性)
<son :inputName="name"></son>
</div>
</template>
<script>
// 引入子组件
import son from './son'
export default {
name: 'father',
data () {
return {
name: '',
}
},
components: { //接收组件
son
}
}
</script>
- 新建子组件文件
<template>
<div>
子组件:
<span>{{inputName}}</span> //接收父组件传过来的值
</div>
</template>
<script>
export default {
name: 'son',
data () {
return {}
},
// 接受父组件的值
props: {
inputName: String, //声明的类型
required: true
}
}
</script>
image.png
另一种(在封装组件里传值)父组件向子组件传值
局部封装
image.png image.png
‘a’是字符串数组
2. 子组件向父组件传值
vue是禁止子组件直接向父组件传值的,所以只能通过$emit触发事件来达到目的。
- 新建子组件文件
<template>
<div>
子组件:
<span>{{sonValue}}</span>
<!-- 定义一个子组件传值的方法 -->
<button @click="sonClick">点击触发</button> //绑定一个点击事件
</div>
</template>
<script>
export default {
name: 'son',
data () {
return {
sonValue: '我是子组件的数据'
}
},
methods: {
sonClick () {
// sonByValue是在父组件on监听的方法
// 第二个参数this.sonValue是需要传给父组件的值,就是return中的值
this.$emit('sonByValue', this.sonValue)
}
}
}
</script>
- 新建父组件文件
<template>
<div>
父组件:
<span>{{name}}</span>
<!-- 引入子组件 定义一个on的方法监听子组件的状态-->
//@sonByValue是接收子组件的事件名称,需要和子组件保持一致
<son @sonByValue="outSon"></son> //outSon自定义名称方法
</div>
</template>
<script>
import son from './son'
export default {
name: 'father',
data () {
return {
name: ''
}
},
methods: {
// sonValue就是子组件传过来的值
outSon(sonValue) {
// 把子组件里传过来的值赋值给this.name,当点击触发方法时,就把值传过来了并显示在页面上了
this.name = sonValue
}
},
components: {
son
}
}
</script>
image.png
3.非父子组件传值(兄弟组件传值)
需要新建一个公共的公共实例文件bus.js,作为中间仓库来传值
- 1.在src目录下新建一个bus.js文件
import Vue from 'vue'
export default new Vue()
- 2.新建组件A
<template>
<div id="emit">
A组件:
<span>{{elementValue}}</span>
<button @click="elementByValue">点击触发</button>
</div>
</template>
<script>
// 引入公共的bug,来做为中间传达的工具
import Bus from './bus.js'
export default {
name: 'componentA',
data () {
return {
elementValue: '我要给兄弟组件传值啦'
}
},
methods: {
elementByValue () {
// 用$emit来触发
Bus.$emit('val', this.elementValue)
// console.log(this.elementValue)
}
}
}
</script>
- 新建组件B
<template>
<div>
B组件:
<!--<button @click="getBata">点击触发</button>-->
<span>{{name}}</span>
</div>
</template>
<script>
// 引入公共的bug,来做为中间传达的工具
import Bus from './bus.js'
export default {
name: 'componentB',
data () {
return {
name: ''
}
},
mounted () {
var vm = this
// 用$on来接收
Bus.$on('val', (data) => {
console.log(data)
vm.name = data
})
}
// methods: {
// getBata () {
// this.name++
// }
// }
}
</script>
4. 袓孙隔代传值
当一个模板里嵌套了很多层时,如:组先、儿子、孙子、曾孙等,你要从最里层曾孙组件里去访问最外层袓先的数据,如果你要一层一层的去传值的话,那这会非常麻烦,并且数据容易出错。这时就需要用到provide 和inject方法,它们俩需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
不推荐直接用于应用程序代码中。一般使用的场景是自定义组件库的时候,底层组件之间需要通信的时候使用。
-
provide: 一个对象或返回一个对象的函数
-
inject:一个字符串数组,或 一个对象,对象的 key 是本地的绑定名
- 新建袓先级组件
<template>
<div>
<span>祖先级组件:parent</span>
<input type="text" v-model="toGdata.name">
<div>
<dadC></dadC> // 定义父组件
</div>
</div>
</template>
<script>
// 引入父组件
import dadC from './dadC'
export default {
name: 'parent',
data () {
return {
toGdata: {name: '李三'} // 存放数据
}
},
// import引入的组件需要注入到对象中才能使用
components: {
dadC
},
// 注入数据
provide () {
return {
toGdata: this.toGdata
}
}
}
</script>
- 新建儿子级组件
<template>
<div>
<span>儿子级组件C:dadC</span>
<div>
<grandSon></grandSon> // 定义孙子组件
</div>
</div>
</template>
<script>
// 引入孙子组件
import grandSon from './grandSon'
export default {
name: 'dadC',
data () {
return {}
},
// import引入的组件需要注入到对象中才能使用
components: {
grandSon
}
}
</script>
- 新建孙子级组件
<template>
<div>
<span>孙子级组件G:grandSon</span>
<div>
接受来自袓父级组件parent的数据【toGdata】:{{toGdata}}
<input type="text" v-model="fromParentData.name">
</div>
</div>
</template>
<script>
export default {
name: 'grandSon',
data () {
return {
fromParentData: this.toGdata
}
},
// 接受袓先级传过来的数据
inject: ['toGdata'],
components: {}
}
</script>
注意:这里不论子组件嵌套有多深, 只要调用了 inject 那么就可以注入 provide 中的数据,而不局限于只能从当前父组件的props属性中回去数据
image.png总结:
在简单的功能模块,可以通过传递对象实现跨级组件通信,复杂的功能模块不建议使用,因为传递的数据,如果其他的儿子级组件,其他儿子级组件的孙子级组件也在使用的话,会造成数据的混乱,甚至无法理解数据是在哪里变化的,排查故障艰难。
跨级组件通信可以定义一个中央事件总线(eventBus),但是更复杂的系统,还是建议使用vuex。
参考以下资料:
https://blog.csdn.net/weihaifeng163/article/details/88338822
https://www.cnblogs.com/pangchunlei/p/12112318.html
网友评论