12种方式实现vue组件通信

  • 我们知道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:子父组件通信 (借助$emit发送自定义事件,在父组件中找到子组件标签,绑定这个自定义事件)

  • 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>
 

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:跨级组件传值(attrs,借助v-bind="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:跨级组件传值(listeners,借助v-on="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:父子组件通信parent和children(一般不建议使用childen和parent,耦合度过高)

  • 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)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容

  • vue中组件之间的通信 组件可以有以下几种关系: A-B、B-C、B-D都是父子关系 C-D是兄弟关系 A-C、A...
    叶落疑秋阅读 106评论 0 2
  • 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一...
    虚竹_d36e阅读 158评论 0 0
  • 本篇文章带大家详细了解一下vue中8种组件通信方式。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助...
    浅浅而谈阅读 2,218评论 2 50
  • vue是数据驱动视图更新的框架,所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢? 首...
    小太阳可可阅读 244评论 0 0
  • 前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引...
    戚子宇阅读 1,059评论 0 0