vue组件之间的通信(超详细的vue组件间通信总结)
vue组件之间的通信
超详细的vue组件间通信总结目录
- 前言
- 一、props、$emit单向数据流
- 二、$parent、$children
- 三、$attrs、$listeners
- 四、provide、inject
- 五、eventBus(事件总线)
- 六、vuex
- 七、localstorage
- 总结
组件通信在我们平时开发过程中,特别是在vue和在react中,有着举足轻重的地位。本篇将总结在vue中,组件之间通信的几种方式:
- props、$emit
- $parent、$children
- $attrs、$listeners
- provide、inject
- eventBus
- vuex
- 本地存储
father.vue:
<template> <li> <li>我是父亲:<input type="button" value="父亲" /> 数字为: {{num}}</li> <son :num="num" @change="change"></son> </li> </template> <script> import son from "./son.vue"; export default { name: "Father", components: { son, }, data() { return { num: 1, }; }, methods:{ change(val){ this.num = val } } }; </script>
son.vue:
<template> <li>我是儿子:<input type="button" value="儿子" @click="change"/>数字为:{{num}}</li> </template> <script> export default { name: "App", components: {}, props: { num: { default: 0, }, }, created() {}, methods: { change(){ // this.num = 2 props通信是单向数据流,在这直接修改父组件传过来的num将会报错 // 可以用$emit触发change事件,father组件绑定change事件 this.$emit('change', 2) } }, }; </script>
对于上面的场景:子组件的change事件只是为了修改父组件中某一个值,还可以有以下几种写法:
1.父组件绑定给子组件的事件使用箭头函数
father: <son :num="num" @change="val => num = val"></son> son: this.$emit('change', 2)
2.update:num和.sync
father: <son :num.sync="num"></son> son: this.$emit('update:num', 2)//update是规定的写法,不可更换
3.v-model
先修改props和绑定的事件:
father:<son :value="num" @input="val => num = val"></son>son:this.$emit('input', 2) 可用v-model简写:<son v-model="num"></son>
$parent、$children可直接在父子组件中调用各自的方法以及修改数据
子组件中直接:this.$parent.num = 2
父组件中$children是个数组,因此具体是哪个子组件不太直观,可以用$refs来操作子组件
vue官方并不推荐使用这种通信方式:节制地使用$parent
和$children
- 它们的主要目的是作为访问组件的应急方法,更推荐用 props 和 events 实现父子组件通信。
$attrs可以拿到父组件传过来的属性:
<li>我是儿子:<input type="button" value="儿子" @click="change"/>数字为:{{$attrs}}</li>
dom节点:
$attrs会直接将传过来的属性放到对应的标签上,反观props就不会。如果想去掉标签中的这些属性,可以用inheritAttrs:
值得注意的是:props的优先级大于$attrs,即当props存在的时候,$attrs为空对象:
$attrs常用于跨多级组件传递属性,比如祖孙组件,用父组件做中转:
father:
<son v-bind="$attrs"></son>
$attrs用于属性跨级传递,方法跨级传递则用$listeners。
grandFather.vue:
<template> <li> <li>我是祖父: 数字为:{{nums}}</li> <father :nums="nums" @up="up" @down="down"></father> </li> </template> <script> import father from "./father.vue"; export default { name: "App", components: { father, }, data(){ return { nums:0 } }, methods: { up() { alert('up') }, down() { alert('down') }, }, }; </script>
father.vue:
<son v-bind="$attrs" v-on="$listeners"></son>
son.vue:
<li>我是儿子:<input type="button" value="儿子" @click="$listeners.up"/></li>
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效
provide选项应该是一个对象或返回一个对象的函数。
inject选项应该是一个字符串数组或一个对象。
App:
... export default { provide(){ return {vm: this} }, ...
son:
... export default { inject: ['vm'], data(){}, mounted(){ console.log(this.vm) } ...
注意:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
inject注入中的值会沿着组件向上查找,遵从"就近原则"。
provide 和 inject中的数据流是双向的。
五、eventBus(事件总线)eventBus通过发布订阅全局事件,供其他组件使用。
在main.js中:
Vue.prototype.$bus = new Vue();
parent.vue:
<template> <li> <son1></son1> <son2></son2> </li> </template> <script> import son1 from './son1.vue' import son2 from './son2.vue' export default { name: 'parent', components: { son1, son2 }, created(){ this.$bus.$on('busEvent',(v)=>{ console.log(v); }) }, beforeDestroy(){ this.$bus.off('busEvent') } } </script>
son1和son2中的mounted:
son1:mounted(){ this.$bus.$emit('busEvent','son1哈哈') }son2:mounted(){ this.$bus.$emit('busEvent', 'son2嘻嘻')}
打印结果:
使用eventBus有三点需要注意,1.$bus.on应该在created钩子内使用,如果在mounted使用,它可能接收不到其他组件来自created钩子内发出的事件;
2.$bus.emit应该在mounted中使用,等待created中的$bus.on事件绑定完成;
3.发布订阅的事件在beforeDestory钩子里需要使用$bus.off解除,组件销毁后没必要一直监听。
六、vuex借助vuex的状态管理来实现组件通信,vuex适用于较为复杂的项目,频繁的数据共享且数据量比较大。
store/index.js:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { isLogin: false }, mutations: { loginState (state, isLogin) { state.isLogin = isLogin } } }) export default store
App.vue:
created(){ this.$store.commit('loginState',true)// 设置登录状态为true },
son.vue:
<template> <li>我是儿子:<input type="button" value="儿子" />登录状态:{{isLogin}}</li> </template> <script> import {mapState} from 'vuex'; export default { name: "son", computed:{ ...mapState(['isLogin']) } }; </script>
七、localstorage
localstorage是浏览器的本地存储,将会长期存储在浏览器中,非常庞大的数据不建议用此方式。
App.vue
created(){ localStorage.setItem('isLogin', true) },
son.vue:
computed:{ isLogin(){ return localStorage.getItem('isLogin') } }
常见的组件通信方式基本就是这些啦,有什么遗漏或不足的,欢迎评论区留言!
总结到此这篇关于vue组件间通信的文章就介绍到这了,更多相关vue组件间通信内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
- 面试问vue掌握程度如何回答(面试最常问的13种Vue修饰符)
- vue函数中的默认参数(Vue3中SetUp函数的参数props、context详解)
- vue-cli请求数据的方式(vue-cli配置使用Vuex的全过程记录)
- vue原样表格导出excel(Vue导出Excel功能的全过程记录)
- 详解从vue的组件传值着手观察者模式(详解从vue的组件传值着手观察者模式)
- vue浏览pdf文件(如何在vue中使用pdfjs预览pdf文件)
- vue设置属性没响应(Vue.$set 失效的坑 问题发现及解决方案)
- vue-cli安装教程学习(Vue新手指南之创建第一个vue-cli脚手架程序)
- vue组件方法里如何修改data(vue项目中使用rem替换px的实现示例)
- vue.js入门教学第15讲(Vue.js 使用AntV X6的示例步骤)
- vue 实现吸顶效果(vue实现水波涟漪效果的点击反馈指令)
- vue常用的指令和修饰符(Vue中 Vue.prototype使用详解)
- vue插槽实例(Vue中插槽slot的使用方法与应用场景详析)
- vue 优雅写法(使用vue实现手写签名功能)
- vue2.0自定义指令(vue2实现provide inject传递响应式)
- vue控制div滚动条(vue3实现CSS无限无缝滚动效果)
- 吴启华与曾舜晞两代张无忌同框,戏里经典的他却没活出原著的潇洒(吴启华与曾舜晞两代张无忌同框)
- 经常发这三种 朋友圈 的人,要迅速屏蔽(经常发这三种朋友圈)
- 有种尴尬叫朋友圈忘屏蔽,大学生上演社死现场,父母亲自下场吐槽(有种尴尬叫朋友圈忘屏蔽)
- 朋友圈屏蔽你的人,可以直接看淡了(朋友圈屏蔽你的人)
- 金球奖只青睐那些会戴珠宝的女人(金球奖只青睐那些会戴珠宝的女人)
- 浙江省一个县,人口超40万,建县历史超1100年(浙江省一个县人口超40万)
热门推荐
- sqlserver2016的安装(Sql Server2016 正式版安装程序图解教程)
- php分页函数有什么用(php实现分页功能的详细实例方法)
- 怎样查看mysql的ddl窗口(详解MySQL8.0原子DDL语法)
- mysql数据库触发器(MySQL中使用游标触发器的方法)
- dedecms调用点击数(织梦DEDECMS中显示复制地址,推荐给QQ/MSN上的好友的代码)
- 怎么用docker中的mysql连接数据库(连接docker里面的mysql失败解决方法)
- zabbix监控页面(Zabbix WEB监测实现过程图解)
- docker管理脚本(Docker可视化ui管理工具Portainer安装及使用解析)
- mysql中的null是什么(浅谈为什么Mysql数据库尽量避免NULL)
- 登录宝塔面板无法显示网站(宝塔bt面板如何设置自定义404错误页面)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9