我的编程空间,编程开发者的网络收藏夹
学习永远不晚

vue的组件通讯方法总结大全

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

vue的组件通讯方法总结大全

1.通过属性传值props?

父组件向子组件传送数据,这应该是最常用的方式了
子组件接收到数据之后,不能直接修改父组件的数据。会报错,所以当父组件重新渲染时,数据会被覆盖。如果子组件内想要修改的话,推荐使用computedprops 可以是数组或对象,用于接收来自父组件的数据。

// 父组件 List.vue
<template>
  <div>
    <List-item :str="str" :obj="obj" :arr="arr"></List-item>
  </div>
</template>
<script>
import ListItem from "./ListItem";
export default {
  data() {
    return {
      str: "给子组件传值",
      obj: {msg: "给子组件传值"},
      arr: [1, 2, 3]
    }
  },
  components: {
    ListItem
  }
}
</script>
// 子组件 ListItem.vue
<template>
  <div>
    <div>{{msg}}</div>
    <div>{{obj}}</div>
    <div>{{arr}}</div>
  </div>
</template>
<script>
export default {
  props: {
    msg: String, // props是字符串
    obj: Object, // props是对象
    arr: Array   // props是数组
  }
}
</script>

2.修饰符 .sync?

修饰符 .sync,它对 props 起到了一种修饰的作用,使用 .sync 进行修饰的 props 意味子组件有修改它的意图,这种情况下它只起到一个标注性作用,有它没它都不会影响逻辑
使用 .sync 修改上边的代码:

// 父组件 List.vue
<template>
  <!-- 这里不写 .sync 也不会影响结果 -->
  <List-item :title.sync="title" @update:title="updataTitle"></List-item>
</template>
<script>
import ListItem from "./ListItem";
export default {
  data() {
    return {
      title: "我是title",
    }
  },
  components: {
    ListItem
  },
  methods: {
   updataTitle(res) {
    this.title = res;
   }
  }
}
</script>
// 子组件 ListItem.vue
<template>
  <div>
    <button @click="handleClick">Click me</button>
    <div>{{title}}</div>
  </div>
</template>
<script>
export default {
  props: {
    title: String, 
  },
  methods: {
   handleClick() {
    // 子组件向父组件传值
    this.$emit('update:title', '我要父组件更新 title');
   }
  }
}
</script>

3.使用.sync 向子组件传递 多个props:?

当我们用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用:

<text-document v-bind.sync="doc"></text-document>

这样会把 doc 对象中的每一个属性 (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器

4.通过 ref 注册子组件引用?

尽管存在 prop 和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件。为了达到这个目的,可以通过 ref 特性为这个子组件赋予一个 ID 引用。

<template>
  <div>
    <List-item ref="item" :title="title"></List-item>
    <div>{{data}}</div>
  </div>
</template>
<script>
import ListItem from "./List-item";
export default {
  data() {
    return {
      title: "我是title",
      data: ""
    }
  },
  components: {
    ListItem
  },
  mounted() {
    this.data = this.$refs.item.message;
  }
}
</script>

5.通过$parent获取父组件实例的方法或者属性?

这种方式,从严格意思上讲不是值的传递,而是一种"取"(不推荐直接通过实例进行值的获取)。

可以通过 Vue 的实例属性 $parent 获得父组件的实例,借助实例可以调用父实例中的方法,或者获取父实例上的属性,从而达到取值的目的。

// 父组件 List.vue
...
<script>
export default {
  data() {
    return {
      message: "hello children",
      msg: "hello"
    }
  },
  methods: {
    sendMessage() {
      return this.message;
    }
  }
}
</script>
// 子组件 ListItem.vue
<template>
  <div>
    <div>{{data}}</div>
    <div>{{msg}}</div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      data: "",
      msg: ""
    }
  },
  mounted() {
    this.data = this.$parent.sendMessage(); // 调用父实例中的方法
    this.msg = this.$parent.msg; // 获取父实例中的属性
  }
}
</script>

???:

  • 通过 $parent 获取父实例 this.$parent.event
  • 通过 props 传递方法。
  • 通过 $emit 监听父组件中的方法 this.$emit("envnt")

6. 通过事件传值 $emit?

子组件使用 $emit 发送一个自定义事件,事件名称是一个字符串。
父组件使用指令 v-on 绑定子组件发送的自定义事件。

// 父组件 List.vue
<template>
  <div>
    <!-- 监听自定义事件 -->
    <List-item v-on:welcome="getWelcome"></List-item>
  </div>
</template>
<script>
import ListItem from "./List-item";
export default {
  components: {
    ListItem
  },
  methods: {
    getWelcome(data) {
      alert(data)
    }
  }
}
</script>
// 子组件 ListItem.vue
<template>
  <button @click="handleClick">Click me</button>
</template>
<script>
export default {
  methods: {
    handleClick() {
   // 使用 $emit 发送自定义事件 welcome
      this.$emit('welcome', 'hello');
    }
  }
}
</script>

7.$children?

获取父组件下的所有子组件的实例,返回的是一个数组 使用范围:该属性只针对vue组件,与js中childNodes还是有区别的。

$ildren: 获取子组件实例集合hildNodes: 获取子节点集合使用方法:

&lt;template&gt;
    &lt;A&gt;&lt;/A&gt;
    &lt;B&gt;&lt;/B&gt;
&lt;/template&gt;
&lt;script&gt;
    export default{
        data(){},
        mounted(){
            //  通过$children可以获取到A和B两个子组件的实例
            console.log('children:',this.$children)
        }
    }
&lt;/script&gt;
其中,
this.$children[0]
可以获取到A组件的实例,一样的,我们可以使用A组件的属性以及他的方法。

8.Vuex?

Vuex介绍

  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.
  • Vuex 解决了多个视图依赖于同一状态和来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上

Vuex各个模块

  • state:用于数据的存储,是store中的唯一数据源
  • getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
  • mutations:类似函数,改变state数据的唯一途径,且不能用于处理异步事件
  • actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
  • modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

Vuex实例应用

这里我们先新建 store文件夹, 对Vuex进行一些封装处理
在 store 文件夹下添加 index.js 文件

// index.js
// 自动挂载指定目录下的store
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let modules = {}
// @/store/module 目录下的文件自动挂载为 store 模块
const subModuleList = require.context('@/store/modules', false, /.js$/)
subModuleList.keys().forEach(subRouter => {
  const moduleName = subRouter.substring(2, subRouter.length - 3)
  modules[moduleName] = subModuleList(subRouter).default
})
export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules
})

在 store 文件夹下添加 module 文件夹,在module文件夹再新建 user.js 文件

// user.js
import user from '@/utils/user.js'
import userApi from '@/apis/user'
import { OPEN_ACCOUNT_STAGE, STAGE_STATUS } from '@/constant'
let getUserPromise = null
export default {
  namespaced: true,
  state() {
    return {
      userInfo: null, // 用户信息
      isLogined: !!user.getToken(), // 是否已经登录
    }
  },
  mutations: {
    // 更新用户信息
    updateUser(state, payload) {
      state.isLogined = !!payload
      state.userInfo = payload
    },
  },
  actions: {
    // 获取当前用户信息
    async getUserInfo(context, payload) {
      // forceUpdate 表示是否强制更新
      if (context.state.userInfo && !payload?.forceUpdate) {
        return context.state.userInfo
      }
      if (!getUserPromise || payload?.forceUpdate) {
        getUserPromise = userApi.getUserInfo()
      }
      // 获取用户信息
      try {
        const userInfo = await getUserPromise
        context.commit('updateUser', userInfo)
      } finally {
        getUserPromise = null
      }
      return context.state.userInfo
    },
    // 登出
    async logout(context, payload = {}) {
      // 是否手动退出
      const { manual } = payload
      if (manual) {
        await userApi.postLogout()
      }
      user.clearToken()
      context.commit('updateUser', null)
    },
  }
}

然后在项目的 main.js 文件中引入

import Vue from 'vue'
import App from '@/app.vue'
import { router } from '@/router'
import store from '@/store/index'
const vue = new Vue({
  el: '#app',
  name: 'root',
  router,
  store,
  render: h => h(App),
})

封装完成,即可正常操纵

this.$store.state.user.isLogined
this.$store.state.user.userInfo
this.$store.commit('user/updateUser', {})
 await this.$store.dispatch('user/logout', { manual: true })

9.eventBus?

ventBus够简化各组件间的通信,让我们的代码书写变得简单,能有效的分离事件发送方和接收方(也就是解耦的意思),能避免复杂和容易出错的依赖性和生命周期问题。

  • Event 事件。它可以是任意类型。
  • Subscriber 事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
  • Publisher 事件的发布者。我们可以在任意线程里发布事件,一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

10. provide / inject?

provide / inject 是vue2.2.0新增的api, 简单来说就是父组件中通过provide来提供变量, 然后再子组件中通过inject来注入变量。

provide 选项应该是

  • 一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作。

inject 选项应该是:

  • 一个字符串数组
  • 一个对象(详情点击这里) 基本用法:
// 祖先组件 提供foo
//第一种
export default {
  name: "father",
  provide() {
    return {
      foo: 'hello'
    }
  },
}
//第二种
export default {
  name: "father",
  provide: {
    foo:'hello~~~~'
  },
}
//后代组件 注入foo, 直接当做this.foo来用
export default {
  inject:['foo'],
}

上面的两种用法有什么区别吗?

  • 如果你只是传一个字符串,像上面的hello,那么是没有区别的,后代都能读到。
  • 如果你需要this对象属性的值(如下所示代码),那么第二种是传不了的,后代组件拿不到数据。所以建议只写第一种
//当你传递对象给后代时
provide() {
    return {
        test: this.msg
    }
},

注意:一旦注入了某个数据,比如上面示例中的 foo,那这个组件中就不能再声明 foo 这个数据了,因为它已经被父级占有。

provide 和 inject 绑定并不是可响应的。

这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。因为对象是引用类型。

先来个值类型的数据(也就是字符串)例子,不会响应

provide(){
  return{
    test:this.msg
  }
},
data() {
  return {
    msg: "Welcome to Your Vue.js App",
  }
}
mounted(){
  setTimeout(()=>{
    this.msg = "halo world";
    console.log(this._provided.msg)
    //log:Welcome to Your Vue.js App
  },3000)
},

如上所示,这样做是不行的,打印出来的 _provided 中的数据并没有改,子组件取得值也没变。

你甚至可以直接给 this._provided.msg 赋值,但是即使是_provided.msg 里面的值改变了,子组件的取值,依然没有变。

当你的参数是对象的时候,就可以响应了,如下:

provide(){
  return{
    test:this.activeData
  }
},
data() {
  return {
    activeData:{name:'halo'},
  }
}
mounted(){
  setTimeout(()=>{
    this.activeData.name = 'world';
  },3000)
}

这就是vue官方中写道的对象的属性是可以响应的

provide/inject 实现全局变量

provide/inject不是只能从祖先传递给后代吗?是的,但是,如果我们绑定到最顶层的组件app.vue,是不是所有后代都接收到了,就是当做全局变量来用了。

//app.vue
export default {
  name: 'App',
  provide(){
    return{
      app:this
    }
  },
  data(){
    return{
      text:"it's hard to tell the night time from the day"
    }
  },
  methods:{
    say(){
      console.log("Desperado, why don't you come to your senses?")
    }
  }
}
//其他所有子组件,需要全局变量的,只需要按需注入app即可
export default {
  inject:['foo','app'],
  mounted(){
    console.log(this.app.text); // 获取app中的变量
    this.app.say(); // 可以执行app中的方法,变身为全局方法!
  }
}

provide/inject 实现页面刷新,不闪烁

  • vue-router重新路由到当前页面,页面是不进行刷新的
  • 采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好

那我们怎么做呢?

跟上面的原理差不多,我们只在控制路由的组件中写一个函数(使用v-if控制router-view的显示隐藏,这里的原理不作赘述),然后把这个函数传递给后代,然后在后代组件中调用这个方法即可刷新路由啦。

//app.vue
<router-view v-if="isShowRouter"/>
export default {
  name: 'App',
  provide() {
    return {
      reload: this.reload
    }
  },
  data() {
    return {
      isShowRouter: true,
    }
  },
  methods:{
    reload() {
      this.isShowRouter = false;
      this.$nextTick(() => { 
        this.isShowRouter = true;
      })
    }
  }
}
//后代组件
export default {
  inject: ['reload'],  
}

这里 provide 使用了函数传递给后代,然后后代调用这个函数,这种思路,也是可以做子后代向父组件传参通讯的思路了。这里的原理,和 event 事件订阅发布就很像了

11.通过 $root 访问根实例?

通过 $root,任何组件都可以获取当前组件树的根 Vue 实例,通过维护根实例上的 data,就可以实现组件间的数据共享

//main.js 根实例
new Vue({
    el: '#app',
    store,
    router,
    // 根实例的 data 属性,维护通用的数据
    data: function () {
        return {
            author: ''
        }
    },
    components: { App },
    template: '<App/>',
});
<!--组件A-->
<script>
export default {
    created() {
        this.$root.author = '于是乎'
    }
}
</script>
<!--组件B-->
<template>
    <div><span>本文作者</span>{{ $root.author }}</div>
</template>

注意:通过这种方式,虽然可以实现通信,但在应用的任何部分,任何时间发生的任何数据变化,都不会留下变更的记录,这对于稍复杂的应用来说,调试是致命的,不建议在实际应用中使用。

12. attrs与attrs 与 attrs与listenter?

多层嵌套组件传递数据时,如果只是传递数据,而不做中间处理的话就可以用这个,比如父组件向孙子组件传递数据时

$attrs:包含父作用域里除 class 和 style 除外的非 props 属性集合。通过this.attrs获取父作用域中所有符合条件的属性集合,然后还要继续传给子组件内部的其他组件,就可以通过v−bind = " attrs 获取父作用域中所有符合条件的属性集合,然后还要继续传给子组件内部的其他组件,就可以通过 v-bind="attrs获取父作用域中所有符合条件的属性集合,然后还要继续传给子组件内部的其他组件,就可以通过v−bind="attrs"

$listeners:包含父作用域里 .native 除外的监听事件集合。如果还要继续传给子组件内部的其他组件,就可以通过 v-on=“$linteners”

使用方式是相同的:

// Parent.vue
<template>
    <child :name="name" title="1111" ></child>
</template
export default{
    data(){
        return {
            name:"小解"
        }
    }
}
// Child.vue
<template>
    // 继续传给孙子组件
    <sun-child v-bind="$attrs"></sun-child>
</template>
export default{
    props:["name"], // 这里可以接收,也可以不接收
    mounted(){
        // 如果props接收了name 就是 { title:1111 },否则就是{ name:"小解", title:1111 }
        console.log(this.$attrs)
    }
}

总结

常见使用场景可以分为三类:

  • 父子组件通信: props$parent / $children provide / inject 、 ref \ $refs 、 $attrs / $listeners
  • 兄弟组件通信: eventBus 、 vuex、 自己实现简单的 Store 模式
  • 跨级通信: eventBus、 Vuex、 自己实现简单的 Store 模式、 provide / inject 、 $attrs / $listeners

以上就是vue的组件通讯方法总结大全的详细内容,更多关于vue组件通讯的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

vue的组件通讯方法总结大全

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vue组件间通信方式全面汇总介绍

这篇文章主要介绍了Vue组件间通信方式全面汇总,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-05-16

vue组件传值的11种方式总结

这篇文章主要介绍了vue组件传值的11种方式总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-01-13

Vue中关于重新渲染组件的方法及总结

这篇文章主要介绍了Vue中关于重新渲染组件的方法及总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-12-03

Vue组件间的通讯方式有哪些

本篇内容主要讲解“Vue组件间的通讯方式有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue组件间的通讯方式有哪些”吧!前言Vue 提供了各种各样的通讯,其中包括兄弟间的通讯和非兄弟间的通
2023-06-27

Angular父子组件通讯的方法

这篇文章主要介绍Angular父子组件通讯的方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!概述Angular组件间通讯组件树,1号是根组件AppComponent。组件之间松耦合,组件之间知道的越少越好。组件4里
2023-06-15

vue组件间的通信,子组件向父组件传值的方式汇总

这篇文章主要介绍了vue组件间的通信,子组件向父组件传值的方式汇总,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-20

vue3中组件传值的多种方法总结

学习过vue2的宝子们肯定知道,组件传值是vue项目开发过程中必不可少的功能场景,下面这篇文章主要给大家介绍了关于vue3中组件传值的多种方法,文中通过图文介绍的非常详细,需要的朋友可以参考下
2023-01-06

Angular中组件间通讯的实现方法

这篇文章主要介绍Angular中组件间通讯的实现方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Angular 组件间的通讯组件间三种典型关系:父好组件之间的交互(@Input/@Output/模板变量/@View
2023-06-14

Vue3中组件通讯的方法有哪些

这篇文章主要讲解了“Vue3中组件通讯的方法有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue3中组件通讯的方法有哪些”吧!Props父组件传值给子组件(简称:父传子)Props 文
2023-07-02

Vue组件间通信的方法有哪些

这篇“Vue组件间通信的方法有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue组件间通信的方法有哪些”文章吧。方法一
2023-07-05

Vue中实现组件间通讯的方式有哪些

这篇文章主要讲解了“Vue中实现组件间通讯的方式有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue中实现组件间通讯的方式有哪些”吧!1.那些场景需要通讯?由于 Vue 所有的组件呈现
2023-06-30

编程热搜

目录