vue 父子组件传值以及方法调用,平行组件之间传值以及方法调用大全
vue项目经常需要组件间的传值以及方法调用,具体场景就不说了,都知道。基本上所有的传值都可以用vuex状态管理来实现,只要在组件内监听vuex就好。
vue常用的传值方式以及方法有:
1. 父值传子(props)
1-1:解决一个项目中遇到的问题,父组件给子组件传值第一次子组件是可以接受的,
但是在父组件中这个值改变了,在子组件中这个prop的值还是第一次父组件传给的值。
2. 子值传父($emit) == 子调用父方法($emit):此方法较为常用。
3. 子调用父方法(props)== 子传父值:此方法不常见。
4. 父主动获取子方法以及数据($refs)
5. 子主动获取父方法以及数据:一种方法就是父先把值,方法通过props传给子,然后子在用即可,此法同3。这里讲另外方法一个方法。
6. 非父子 (eventBus)
7. vuex传值
补充:父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息,如下图所示:
详细示例:
1. 父组件向子组件进行传值
父组件:
<template> <div> 父组件: <input type="text" v-model="name"> <!-- 引入子组件 --> <child :inputName="name"></child> </div> </template> <script> import child from "./child"; export default { components: { child }, data() { return { name: "" }; } }; </script>
子组件:
<template> <div> 子组件: <span>{{inputName}}</span> </div> </template> <script> export default { // 接受父组件的值 props: { inputName: String, required: true } }; </script>
1-1:子组件接受props的值一次后,任父组件传的值怎么变,子组件就不变了。
解决方法:用一个中间值,页面绑定这个中间值。观察props值得变化->变化后把新值赋值给中间值。这样就同步了
<template> <input type="text" v-model="currentValue" @change="change" /> </template> <script> export default { data() { return { // 中间值来承接父组件传过来的值 currentValue: this.value, other:{}, }; }, props: { value: {//父传过来的值 type: String } }, watch: { value(val) { // value变换赋值给currentValue this.currentValue = val; }, other: { //深度观察对象 handler(val) { }, deep: true } }, methods: { } }; </script>
2. 子组件向父组件传值 -> 是通过方法传递的,也相当于子组件调用父组件方法。
父组件:
<template> <div> 父组件: <span>{{name}}</span> <!-- 引入子组件 定义一个on的方法监听子组件的状态--> <child v-on:onChildByValue="childByValue"></child> </div> </template> <script> import child from "./child"; export default { components: { child }, data() { return { name: "" }; }, methods: { childByValue: function(childValue) { // childValue就是子组件传过来的值 this.name = childValue; } } }; </script>
子组件:
<template> <div> 子组件: <span>{{childValue}}</span> <!-- 定义一个子组件传值的方法 --> <input type="button" value="点击触发" @click="childClick"> </div> </template> <script> export default { data() { return { childValue: "我是子组件的数据" }; }, methods: { childClick() { // childByValue是在父组件on监听的方法 // 第二个参数this.childValue是需要传的值 this.$emit("onChildByValue", this.childValue); } } }; </script>
3. 子调用父方法:
父组件:
<template> <editor :onSubmit="cccc"></editor> </template> <script> export default {
//省略了引入注册等代码 methods: { cccc: function (str) { alert(str) } } } </script>
子组件:
<template> <button @click="submit">提交</button> </template> <script> export default { props: { onSubmit: {//父组件把方法传过来 type: Function, default: null } }, methods: { submit: function () { if (this.onsubmit) {
// 调用父方法也相当于通过方法传值了 this.onsubmit('传给父组件ok') } } } } </script>
4. 父主动获取子方法以及数据
1. 调用子组件的时候 定义一个ref
<child ref="headerChild"></child>
2. 在父组件里面通过
this.$refs.headerChild.属性
this.$refs.headerChild.方法
5. 子主动获取父方法以及数据
在子组件里面通过以下方法获取,获取不到数据可以输出this.$parent看看数据是什么样的,有时候得通过this.$parent.$parent.属性 ...
用此方法前提得知道父组件有没有,如果有?是谁,不推荐用这个方法,如果组件嵌套过多就比较麻烦。
this.$parent.属性
this.$parent.方法
6. 非父子组件进行传值(不推荐平行组件相互传值,能避免就避免)
a: 方法一:如果相互传值的组件都公有一个父组件的话,共同父组件中设定一个data用于储存你要传递的数据,
然后两个子组件都通过props连接父组件的这个data,实现一个三方同步。
b: 方法二:通过url,缓存来传数据,这个得看组件间怎么设计的。
c: 方法三:event bus,vue2.0里面的event bus(其实就是个发布订阅模式):
可以在main.js里面设置全局方法:window.eventBus = new Vue();
组件A:订阅方法。
<template> <div> A组件: <input type="button" value="点击触发" @click="getData"> <span>{{name}}</span> </div> </template> <script> export default { data () { return { name: 0 } }, methods: { getData: function () { this.name++ }, showLog: function (){ console.log('调用了A组件方法') } } mounted: function () { var that = this // 用$on事件来接收 eventBus.$on('sendEvent', function(data){ // 在这里处理数据或者调用要执行的方法 console.log(data) that.name = data; that.showLog(); }) }, }
组件B:调用方法
<template> <div> B组件: <span>{{elementValue}}</span> <input type="button" value="点击触发" @click="elementByValue"> </div> </template> <script> export default { data() { return { elementValue: 4 }; }, methods: { elementByValue: function() { // 在这里触发这个让别的组件观察的方法。 eventBus.$emit("sendEvent", this.elementValue); } } }; </script>
7.vuex传值:只需要在相应组件改变,以及监听变化就可以。
<template> <div> <el-button @click="change">change</el-button> {{this.$store.state.sendData}} {{getSendData}} </div> </template> <script> export default { data() { return {}; }, computed: { getSendData(){ return this.$store.state.sendData; }, }, watch: { //观察数据变化,执行相应的方法 getSendData(val,oldval){ console.log(val); }, }, methods: { change(){ this.$store.commit("newSendData", this.$store.state.sendData+1); } }, mounted() {} }; </script>
基本上所有的方法都在这里了,有问题可以留言。