目录
组件之前的通信方法
1. props/$emit
2.parent/children
3.ref
4.v-model
5.sync
6.attrs,attrs,attrs,listeners
7.provide/inject
7.eventBus
组件之前的通信方法
1. props/$emit
父传子 props 这个只能够接收父组件传来的数据 不能进行修改 可以静态传递 也可以动态传递(一个表达式,一个对象或者布尔值等)父组件属性绑定 子组件用props接收
子改父 emit子组件的内部通过emit 子组件的内部通过emit子组件的内部通过emit去触发这个事件 同时也可以传参过去 v-on去传递事件是写在子组件的标签身边的,然后回调函数是写在父组件的methods身上的
//父组件
<template>
<div>
<child :msg="msg" @changeMsg="changeMsg"></child>
<p>{{msg}}</p>
</div>
</template>
<script>
import child from "../components/Child";
export default {
data() {
return {
msg: "hello"
};
},
components: { child },
methods:{
changeMsg(value){
this.msg=value
}
}
};
</script>
// 这是子组件
<template>
<div>
<div @click="change">改变父组件的{{msg}}</div>
</div>
</template>
<script>
export default {
props: ["msg"],
methods:{
change(){
this.$emit("changeMsg",123)
}
}
};
</script>
2.parent/children
$parent 子组件可以获取到父组件身上的属性以及方法,但是一定要注意,如果说这个组件的父组件不止一个的话 那么容易发生报错
children父组件拿到自己身上的子组件的属性已经方法,如果身上的子组件不止一个的话打印this.children 父组件拿到自己身上的子组件的属性已经方法,如果身上的子组件不止一个的话 打印this.children父组件拿到自己身上的子组件的属性已经方法,如果身上的子组件不止一个的话打印this.children的时候会以数组的形式展示出来
3.ref
父组件想要拿到子组件身上的数据 还可以给子组件写上ref="名字" 然后在父组件身上 this.$ref.名字就可以拿到子组件 身上的方法已经数据都可以获取到
4.v-model
v-model:将数据传递下去的同时 子组件可以修改父组件提供过来的数据(emit方法)
// 这是父组件
<template>
<div>
<child v-model="msg"></child>
<p>{{msg}}</p>
</div>
</template>
<script>
import child from "../components/Child";
export default {
data() {
return {
msg: "hello"
};
},
components: { child }
};
</script>
// 这是子组件
<template>
<div>
<input :value="value" @input="$emit('input',$event.target.value)">
</div>
</template>
<script>
export default {
props: ["value"]
};
</script>
5.sync
sync:将数据传递下去的同时 允许子组件可以修改数据
// 父组件
<template>
<div>
{{num}}
<child-a :count.sync="num" />
</div>
</template>
<script>
import childA from "../components/ChildA";
export default {
data() {
return {
num: 0
};
},
components: { childA }
};
</script>
// 子组件
<template>
<div>
<div @click="handleAdd">ADD</div>
</div>
</template>
<script>
export default {
data() {
return {
counter: this.count
};
},
props: ["count"],
methods: {
handleAdd() {
this.$emit("update:count", ++this.counter);
}
}
};
</script>
6.attrs,attrs,attrs,listeners
attrs包含的是父组件不被prop所识别的特性(📢:inheritAttrs为true属性才会渲染false时属性不会被渲染)可以通过v−bind="attrs 包含的是父组件不被prop所识别的特性 (📢:inheritAttrs为true 属性才会渲染 false时 属性不会被渲染) 可以通过v-bind="attrs包含的是父组件不被prop所识别的特性(📢:inheritAttrs为true属性才会渲染false时属性不会被渲染)可以通过v−bind="attrs"传给内部的组件 listeners包含父组件啊种v−on事件监听器通过v−on="listeners 包含父组件啊种v-on事件监听器 通过v-on="listeners包含父组件啊种v−on事件监听器通过v−on="listeners" 传给内部的足迹爱
<template>
<div>
<!-- 父组件 -->
<h1>{{ count }}</h1>
<son
:msg="msg"
:foo="foo"
:boo="boo"
:coo="coo"
:doo="doo"
title="前端工匠"
@click.native="handleClick"
v-on:focus="handleFocus"
/>
</div>
</template>
<script>
import son from "./son.vue";
export default {
name: "FatherVue",
components: { son },
data() {
return {
msg: "父组件的msg",
foo: "Javascript",
boo: "Html",
coo: "CSS",
doo: "Vue",
};
},
computed: {
count() {
return this.$children[0] && this.$children[0].count;
},
},
mounted() {
console.log(this.$children); // [子组件1, 子组件2,......]
},
methods: {
handleClick() {
console.log("handleClick");
},
handleFocus() {
console.log("handleFocus");
},
},
};
</script>
<!-- 子组件 son.vue -->
<template>
<div>
{{ msg }}
<p>father 父组件的$attrs: {{ $attrs }}</p>
<button @click="handleClick">click</button>
<smallson v-bind="$attrs"></smallson>
</div>
</template>
<script>
import smallson from "./smallson.vue";
export default {
name: "FuSon",
components: { smallson },
inheritAttrs: true, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
computed: {
msg() {
return this.$parent.msg;
},
},
data() {
return {
count: "我是子组件的count",
};
},
methods: {
handleClick() {
console.log(this.$listeners);
},
},
};
</script>
<!-- smallson 组件 -->
<template>
<div>
<h1>smallson</h1>
{{ $attrs }}
</div>
</template>
<script>
export default {
name: "SmallSon",
inheritAttrs: false,
};
</script>
7.provide/inject
provide 提供变量 inject 注入变量
📢:
- 不论层级多深 只要调用了inject那么久可以注入provide的变量
- provide提供的数据在父组件中假设发生了变化 默认后辈的组件是不会响应式变化的 但是如果给的数据是this的数据的话 那么就是响应式的书
<template>
<div id="app">
<myInject></myInject>
</div>
</template>
<script>
import myInject from "./components/zujiantongxin/inject.vue";
export default {
name: "App",
provide: {
for: "provide",
},
// provide() {
// return {
// baba: this,
// msg: this.msg,
// };
// }, 这个时候的数据就可以做到响应式的了 给的就是this的数据 给的就是响应式的数据 就可以做到响应式
components: {
myInject,
},
};
</script>
<template>
<div>
<h2>inject 组件</h2>
<h1>{{ for1 }}</h1>
</div>
</template>
<script>
export default {
name: "myInject",
data() {
return {
for1: this.for,//这一步可以省略的
};
},
inject: ["for"],
mounted() {
console.log(this.for);
},
};
</script>
7.eventBus
EventBus 本质上就是一个vue实例对象,它可以实现兄弟组件之前的通信,首先在A组件中设置EventBus.on自定义事件名称以及回调函数,然后B组件就是通过eventbus.on自定义事件名称以及回调函数,然后B组件就是通过eventbus.on自定义事件名称以及回调函数,然后B组件就是通过eventbus.emit去触发那个自定义事件,将数据传递给A组件
Eventbus的原理实际上就是发布订阅的模式
发布订阅模式 :其实就是一种对象间一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象都将得到状态改变的通知
vue中常见的发布订阅就是emitemit emiton
redux中常见的就是subscribe
// eventBus.js
import Vue from "vue";
export default new Vue();
<template>
<!-- comA子组件 -->
<div>
<h1>{{ msg }}</h1>
</div>
</template>
<script>
import eventBus from "./eventBus";
export default {
name: "面试ComA",
data() {
return {
msg: "",
};
},
mounted() {
eventBus.$on("message", (val) => {
this.msg = val;
});
},
};
</script>
<template>
<div>
<button @click="sendMsg">click 点击 想 COMA 发消息</button>
</div>
</template>
<script>
import eventBus from "./eventBus";
export default {
name: "面试ComB",
data() {
return {};
},
methods: {
sendMsg() {
eventBus.$emit("message", "我是来自comB的数据");
},
},
};
</script>
<template>
<div id="app">
<comA></comA>
<comB></comB>
</div>
</template>
<script>
import comA from "@/components/zujiantongxin/comA.vue";
import comB from "@/components/zujiantongxin/comB.vue";
export default {
name: "App",
components: {
comA,
comB,
},
};
</script>