组件通信的方法
目录
组件通信共有12个方式 三大种类
1.父子组件通信
2.兄弟组件通信
3.跨层级组件通信
总结
父子:
兄弟
跨组件
组件通信共有12个方式 三大种类
1.props
2.$emit/v-on
3..sync
4.v-model
5.ref
6.children/parent
7.attrs/listeners
8.provide/inject
9.EventBus
10.Vuex
11.$root
12.slot
这十二种可以分为三类
1.父子组件通信
- props
- $emit/v-on
- attrs/listeners
- ref
- .sync
- v-model
- children/parent
父组件 通过属性传值 , 子 props 接收
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>父组件向子组件传值--props</title>
<script src="./js/vue.min.js"></script>
</head>
<body>
<div id="app">
<menu-item title="来自父组件的值"></menu-item>
<!-- 在子组件身上绑定自定义属性来接收父组件data中的数据 -->
<menu-item :tit="title"></menu-item>
</div>
<script>
Vue.component('menu-item',{
props:['tit'], //props用来接收父组件传过来的值
//在props中使用驼峰形式,模版中要改为使用短横线拼接 props里面的值只读,不能修改
//props是单向数据流
data(){
return{
}
},
template:'<div>{{tit}}</div>'
})
var vm=new Vue({
el:'#app',
data:{
title:'我是父组件中的数据'
},
methods:{
}
});
</script>
</body>
</html>
子向父传值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 父组件 -->
<div :style='{fontSize:fontSize+"px"}'>{{pmsg}}</div>
<!-- 子组件 -->
<menu-item :parr="parr" @aas="blune"></menu-item>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
子组件向父组件传值-基本用法
props传递数据原则:单向数据流
*/
Vue.component('menu-item', {
props:['parr'],
data(){
return {
msg1:'这是子组件传递过来的值'
}
},
template: `
<div>
<ul>
<li v-for="(item,index) in parr" :key="index">{{item}}</li>
</ul>
<button @click='dd'>扩大父组件中字体大小</button>
</div>
`,
methods:{
dd(){
this.$emit("aas",this.msg1)
}
}
});
//$emit
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件中内容',
parr: ['apple','orange','banana'],
fontSize: 10
},
methods: {
blune(message){
this.fontSize+=5;
console.log(message);
}
}
});
</script>
</body>
</html>
2.兄弟组件通信
- EventBus
- Vuex
- $parent
兄弟组件传值 事件总线
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./js/vue.min.js"></script>
</head>
<body>
<div id="app">
<brother></brother>
<sister></sister>
</div>
<script>
var enveBus = new Vue();
Vue.component('brother', {
data() {
return {
kk: ''
}
},
methods: {
dd() {
enveBus.$emit("bTs", '这是哥哥给妹妹的爱')
}
},
template: `
<div>
<button @click='dd'>这是一个哥哥组件---{{kk}}</button>
</div>
`,
mounted() {
enveBus.$on('asd', (result) => {
this.kk = result;
})
}
});
Vue.component('sister', {
data() {
return {
sis: ''
}
},
template: `
<div>
<button @click="cc">这是一个妹妹组件---{{sis}}</button>
</div>
`,
mounted() {
enveBus.$on('bTs', (message) => {
this.sis = message
})
},
methods: {
cc() {
enveBus.$emit('asd', '这是妹妹对哥哥的爱');
}
}
});
var vm = new Vue({
el: '#app',
data: {
},
methods: {
}
});
</script>
</body>
</html>
跨层级组件通信
- provide/inject
- EventBus
- Vuex
- attrs/listeners
- $root
跨组件 provide
<script lang="ts" setup>
// provide, inject
import { provide } from 'vue';
// provide(名字,值)
const { separtor = '' } = defineProps<{
separtor?: string
}>()
// 向后代传递值
provide('separtor', separtor)
</script>
<template>
<div class="xtx-bread">
<slot></slot>
</div>
</template>
<style scoped lang="less">
.xtx-bread {
display: flex;
// padding: 25px 10px;
&-item {
a {
color: #666;
transition: all 0.4s;
&:hover {
color: @xtxColor;
}
}
}
i {
font-size: 12px;
margin-left: 5px;
margin-right: 5px;
line-height: 22px;
}
}
</style>
inject
<script lang="ts" setup>
import { inject } from 'vue';
// inject(名字)
// 获取分隔符
const separtor = inject('separtor')
defineProps<{
to?: string // 要跳转的位置
}>()
</script>
<template>
<slot> </slot>
<div class="xtx-bread-item">
<!-- 是否需要跳转 -->
<router-link v-if="to" :to="to"><slot> </slot></router-link>
<slot v-else> </slot>
<!-- 分隔符从祖先来的 -->
<i v-if="separtor">{{ separtor }}</i>
<!-- 默认分隔符 -->
<i v-else class="iconfont icon-angle-right"></i>
</div>
</template>
<style lang="less" scoped>
.xtx-bread-item {
i {
margin: 0 6px;
font-size: 10px;
}
// 最后一个i隐藏
&:nth-last-of-type(1) {
i {
display: none;
}
}
}
</style>
总结
父子:
1.props 通过属性传值,子props接收
2.$emit/v-on 父组件使用子组件声明的自定义事件,传值时触发
3.v-model 原理即props与$emit;父:v-model="值"、子:this.$emit('input',值)
4..sync 原理即:属性名& this.$emit('update:属性名', 值)
5.refs 操作dom,通过this.$refs
6.$children/$parent this.$children获取所有子组件的数组对象,包括子组件的属性和监听事件; this.$parent获取父组件的对象,包括子组件的属性和监听事件;
7.$attrs / $listeners 读取到的只读(不可改): this.$attrs获取所有当前元素的属性(不包括:class、style、props传递给子的) this.$listeners获取所有当前元素的监听事件(不包括:.native声明的)
兄弟
1.vuex state中为动态分享的数据; mutations为方法,修改state中的数据; actions(c,v)异步函数(也可为同步)异步操作后c.commit()调用components中的函数间接修改state的数据; getters类似于computed动态属性 modules:用于模块化时的声明
2.EventBus 通过自定义事件:this.$emit与this.$on配合使用 ...
跨组件
1.provide/inject provide('键','值') const a = inject('键')
2.$root 通过this.$root获取到根,从而逐级查找到具体项(标签元素)的属性与值
3.vuex
4.EventBus
5.$attrs/$listeners