vue组件通信的12种方式

27 篇文章 4 订阅
  • ##我们知道vue组件通信有很多种,这里我把自己所知道12种vue组件通信总结出来
1:父子组件通信 ,(v-bind和props实现父子传值)
  • parent.vue
  <template>
    <div class="parent">
      <Child name="张三"/>
    </div>
  </template>
 
  • child.vue
  <template>
    <div class="child">
      <h1> 接收父组件传递过来的值 {{name}}<h1/>
    </div>
  </template>

  <script>
   export default {
     props: {
       name: {
         type: String,
       }
     },
     data() {
       return {

       }
     }
   }
  </script>
 -当然在父组件中找到子组件标签,传递一个函数过去,在子组件接收这个函数,然后可以实现所谓的父子通信
2:子父组件通信
  • 第一种
  • parent.vue

  <template>
    <div class="parent">
      <Child @getMessage="getMessage"/>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
     methods: {
       getMessage(e) {
         console.log("e====",e) // 这个e就是子组件传递过来的值
       }
     } 

   }
  </script>
  • child.vue
  <template>
    <div class="parent">
     <button @click="sendMessage"></button>
    </div>
  </template>

  <script>
   export default {
     data() {
       return {

       }
     },
     methods: {
       sendMessage() {
         this.$emit("getMessage",{id:1,name:"张三"})
       }
     }
   }
  </script>

 
  • 第二种(v-model动态绑定)
  • A.vue

<template>
  <div>
    <h1>hello A</h1> 
    <B v-model:obj="value"></B>
    {{value}}
  </div>
</template>
<script>
import B from './B'
export default {
  props:{},
  components:{B},
  data() {
    return {
      value: "我是A组件的数据"
    }
  },
  methods: {},
  mounted() {}
}
</script>

  • B.vue
<template>
  <div>
    Hello b
    <input type="text" :value="obj" @input="mutationText">
  </div>
</template>
<script>
export default {
  props:{
    obj: {
      type: [String],
    }
  },
   model: {
 	 event:'updateValue'
   },
  components:{},
  data() {
    return {}
  },
  methods: {  
    mutationText(e) {
      this.$emit("updateValue",e.target.value)
    }
  },
  mounted() {}
}
</script>
<style scoped>

</style>
  • 第三种(v-model动态绑定)
  • A.vue

<template>
  <div>
    <h1>hello A</h1> 
    <B v-model:obj="value"></B>
    {{value}}
  </div>
</template>
<script>
import B from './B'
export default {
  props:{},
  components:{B},
  data() {
    return {
      value: "我是A组件的数据"
    }
  },
  methods: {},
  mounted() {}
}
</script>

  • B.vue v-bindl绑定
<template>
  <div>
    Hello b
    <input type="text" :value="obj" @input="mutationText">
  </div>
</template>
<script>
export default {
  props:{
    obj: {
      type: [String],
    }
  },
  components:{},
  data() {
    return {}
  },
  methods: {  
    mutationText(e) {
      // 一定是input事件
      // this.$emit("change",e.target.value)
      this.$emit("input",e.target.value)
    }
  },
  mounted() {}
}
</script>
<style scoped>

</style>
  • 第四种(v-model动态绑定)
  • A.vue

<template>
  <div>
    <h1>hello A</h1> 
    <B v-model:obj="value"></B>
    {{value}}
  </div>
</template>
<script>
import B from './B'
export default {
  props:{},
  components:{B},
  data() {
    return {
      value: "我是A组件的数据"
    }
  },
  methods: {},
  mounted() {}
}
</script>

  • B.vue v-model绑定
<template>
  <div>
    Hello b
    <input type="text" :v-model ="obj1"@input="mutationText">
  </div>
</template>
<script>
export default {
  props:{
    obj: {
      type: [String],
    }
  },
  components:{},
  data() {
    return {
      obj1: this.obj // 避免直接修改父组件
   }
  },
  methods: {  
    mutationText(e) {
      // 一定是input事件
      this.$emit("input",this.obj1)
    }
  },
  mounted() {}
}
</script>
<style scoped>

</style>
  • 第四种(sync语法糖)
  • A.vue

<template>
  <div>
    <h1>hello A</h1> 
     <!-- <B  @val="e => value = e"></B>  -->
    <!-- <B @update:val="v => value = v"></B> -->
    <!-- 简写 -->
    <!-- <B :val.sync="value"></B> -->
    {{value}}
  </div>
</template>
<script>
import B from './B'
export default {
  props:{},
  components:{B},
  data() {
    return {
      value: "我是A组件的数据"
    }
  },
  methods: {},
  mounted() {}
}
</script>
<style scoped>

</style>

  • B.vue
<template>
  <div>
    Hello b
    <input type="text" :value="obj" @input="mutationText">
  </div>
</template>
<script>
export default {
  props:["obj"],
  components:{},
  data() {
    return {}
  },
  methods: {  
    // 第一种方式
    mutationText(e) {
      // this.$emit("val",e.target.value)
      this.$emit("update:val",e.target.value)
    }
  },
  mounted() {}
}
</script>
<style scoped>

</style>
3:非父子组件通信(实例bus,发布订阅模式)
  • main.js
 vue.proptotype.$bus = new Vue()

  • grandpa.vue
  <template>
    <div class="grandpa">
     <button @click="sendMessage"></button>
    </div>
  </template>

  <script>
   export default {
     data() {
       return {}
     },
     methods: {
       sendMessage() {
         this.$bus.$emit("getMessage",{id:1,name:"张三"})
       }
     }
   }
  </script>
 
  • grandson.vue

  <template>
    <div class="grandson">
      <Child/>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
     mounted() {
       this.$bus.$on("getMessage",(e) => {
         console.log("e====",e) // 这个e就是接收传递过来的值
       })
     }

   }
  </script>
4:跨级组件传值(provide和inject)
  • grandpa.vue
  <template>
    <div class="grandpa">
     <button ></button>
    </div>
  </template>

  <script>
   export default {
     data() {
       return {
         name: "张三"
       }
     },
     provide() {
       return {
         app: this
       }
     }
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <h1>{{app.name}}</h1>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
     inject: ["app"]

   }
  </script>
5:跨级组件传值( a t t r s , 借 助 v − b i n d = " attrs,借助v-bind=" attrs,vbind="attrs",后代组件并不会继承传递的props属性)
  • grandpa.vue
  <template>
    <div class="grandpa">
     <father name="张三" age="18" gender="男"/>
    </div>
  </template>

  <script>
   export default {
     data() {
       return {}
     },
   }
  </script>
 
  • father.vue

  <template>
    <div class="father">
     <grandson v-bind="$attrs"/>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <h1> 姓名:{{$attrs.name}}-----年龄: {{$attrs.age}} ---- 性别: {{$attrs.gender}}</h1>
    </div>
  </template>
  <script>
   export default {
     inheritAttrs: false, (默认为true) // 如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false,说白/// 了就是不在子组件标签显示传递的自定义属性
     data() {
       return {}
     },
   }
  </script>
6:跨级组件传值( l i s t e n e r s , 借 助 v − o n = " listeners,借助v-on=" listeners,von="listeners",它是一个对象,里面包含了作用在这个组件上的所有监听器,不包括.native事件)
  • grandpa.vue
  <template>
    <div class="grandpa">
     <father @getMessage="getMessage"/>
    </div>
  </template>

  <script>
   export default {
     data() {
       return {}
     },
     methods: {
      getMessage(e) {
        console.log("接收孙子组件传递过来的参数",e)
      }
     }
   }
  </script>
 
  • father.vue

  <template>
    <div class="father">
      <!-- 在孙子组件上 绑定这个监听器 -->
      <grandson v-on="$listeners"/>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <button @click="sendMessage"> Button </button>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
     methods:{
        sendMessage() {
          console.log("发送")
          this.$emit("getMessage","你好爷爷")
        }
     }
   }
  </script>
7:父子组件通信 p a r e n t 和 parent和 parentchildren(一般不建议使用 c h i l d e n 和 childen和 childenparent,耦合度过高)
  • father.vue

  <template>
    <div class="father">
      <grandson/>
      <h1>子组件修改父组件的名字: {{name}}</h1>
      <button @click="mutateHandler"> Button </button>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {
         name: '张三'
       }
     },
     methods: {
       getMessage(e) {
         this.name = e;
       },
       mutateHandler() {
         this.$children[0].mutateName("张四")
       }
     }
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <button @click="sendMessage"> Button </button>
      <h1>父组件修改子组件的名字: {{name}}</h1>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {
         name: "张四"
       }
     },
     methods:{
        sendMessage() {
          this.$parents.getMessage("李四")
        },
        mutateName(e) {
          this.name = e
        }
     }
   }
  </script>
8:refs(可以获取组件对象,也可以获取dom对象)
  • father.vue

  <template>
    <div class="father">
      <grandson refs="son"/>
      <button @click="mutateHandler">修改值</button>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {
         name: '张三'
       }
     },
     methods: {
       mutateHandler() {
         this.$refs.son.mutateName("张四")
       }
     }
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <h1>父组件修改子组件的名字: {{name}}</h1>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {
         name: "张三"
       }
     },
     methods:{
        mutateName(e) {
          this.name = e
        }
     }
   }
  </script>
9:作用域插槽传值 (借助 v-slot:default=“value” 实现所谓的子父传值)
  • father.vue

  <template>
    <div class="father">
      <grandson>
      <!-- 可以使用 v-slot:grandson ="{}" 是#grandson的语法糖,slot-scoped="{}" 在vue 2.6.0 起被废弃,所以我就不写了 -->
       <template #grandson="{name}">
          {{name}}
       </template>
      </grandson>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
     methods: {}
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <slot name="grandson" :name="name"></slot>
      <button @click="mutateHandler">修改父组件值</button>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {
         name: "张三"
       }
     },
     methods:{
       mutateHandler() {
         this.name = "李四"
       }
     }
   }
  </script>
10:本地缓存(localStorage或者sessionStorage,本文我就以localStorage为例)
  • father.vue

  <template>
    <div class="father">
      <grandson></grandson>
      <h1>{{name}}</h1>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {}
     },
     methods: {},
     mounted() {
       this.name = localStorage.getItem("name")
     }
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <slot name="grandson" :name="name"></slot>
      <button @click="mutateHandler">修改父组件值</button>
    </div>
  </template>
  <script>
   export default {
     data() {
       return {
         name: "张三"
       }
     },
     methods:{
       mutateHandler() {
         this.name = "李四
         localStorage.setItem("name",this.name)
       }
     }
   }
  </script>
11:vuex (一般我们就是dispatch这个actions名字,然后action提交mutations这个名字,然后getters获取这个state(getters类似于vue中的computed),这里我使用的vuex的辅助函数)
  • store.js

 import Vue from 'vue'
 import Vuex from 'vuex'

 Vue.use(Vuex)

 export default new Vuex.Store({
   state: {
     name: '张三'
   },
   mutations: {
     setName(state,name) {
       state.name = name
     }
   },
   actions: {
     actionName({commit}) {
       commit("setName",name)
     }
   },
   getters: {
     name(state) {
       return state.state
     }
   },
   modules: {

   }
 })
 
  • main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'

new Vue({
  store,
  render: h => h(App)
}).$mount("#app")

  • father.vue

  <template>
    <div class="father">
      <grandson></grandson>
      <h1>{{name}}</h1>
    </div>
  </template>
  <script>
    import { mapGetters } from 'vuex'
   export default {
     data() {
       return {}
     },
     computed: mapGetters(["name"]),
   }
  </script>
  • grandson.vue

  <template>
    <div class="grandson">
      <button @click="actionName(name)">修改父组件值</button>
    </div>
  </template>
  <script>
   import { mapActions } from 'vuex'
   export default {
     data() {
       return {
         name: "张三"
       }
     },
     methods:{
       ...mapActions(["actionName"]),
     }
   }
  </script>
12: redux(这里我就不写了,原理类似于vuex)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lxslxskxs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值