组件通信的几种方式...
1. 父传子
- 值得注意的是,这种数据从父组件传值给子组件 是单向的, 也就是说 子组件无法直接修改父组件传递过来的数据,
如果强行修改
props
里面的值,会报一个警告. - 如果真的需要修改这个值,推荐使用
computed
, 当然在data
里定义一个变量接收props
的值,也是可以的.
父组件---parent.vue
<template>
<div>
<Child :message="msg"></Child>
</div>
</template>
<script>
import Child from "./child";
export default {
components: {
Child,
},
data() {
return {
msg: "hello vue!",
};
},
};
</script>
<style scoped></style>
子组件---child.vue
<template>
<div>
<p>{{ message }}</p>
<p>{{ myMsg }}</p>
</div>
</template>
<script>
export default {
// props:["message"],
props: {
message: {
type: String,
// default: ""
default() {
return "";
},
},
},
data() {
return {};
},
computed: {
myMsg() {
return this.message;
},
},
methods: {},
};
</script>
<style scoped></style>
2. 子传父
- 这里需要使用自定义事件,在子组件中使用
this.$emit(‘myEvent’, value)
触发,然后在父组件中使用@myEvent
监听.
子组件---child.vue
<template>
<div>
<button @click="toParent">传值给父组件</button>
</div>
</template>
<script>
export default {
data() {
return {
message: "hello vue!",
};
},
methods: {
toParent() {
this.$emit("pushValue", this.message);
},
},
};
</script>
<style scoped></style>
父组件---parent.vue
<template>
<div>
<Child @pushValue="getChildValue"></Child>
</div>
</template>
<script>
import Child from "./child";
export default {
components: {
Child,
},
data() {
return {
msg: "hello vue!",
};
},
methods: {
getChildValue(value) {
console.log(value); // hello vue!
},
},
};
</script>
<style scoped></style>
3. 兄弟组件之间的传值
- 运用自定义事件
$emit
的触发和监听能力,定义一个公共的事件总线 eventBus
,通过它作为中间桥梁,我们就可以传值给任意组件了。
事件总线---eventBus.js
import Vue from "vue";
export default new Vue();
子组件---child1.vue
<template>
<div>
<button @click="toBrother">传值给兄弟组件child2</button>
</div>
</template>
<script>
import eventBus from "./eventBus";
export default {
data() {
return {
num: 0,
};
},
methods: {
toBrother() {
eventBus.$emit("pushValue", ++this.num);
},
},
};
</script>
<style scoped></style>
子组件---child2.vue
<template>
<div>
<p>兄弟组件child1传过来的值: {{ myNum }}</p>
</div>
</template>
<script>
import eventBus from "./eventBus";
export default {
data() {
return {
myNum: 0,
};
},
mounted() {
eventBus.$on("pushValue", (value) => {
this.myNum = value;
});
},
};
</script>
<style scoped></style>
父组件---parent.vue
<template>
<div>
<brotherChild></brotherChild>
<child></child>
</div>
</template>
<script>
import brotherChild from "./brotherChild";
import child from "./child";
export default {
components: {
brotherChild,
child,
},
};
</script>
<style scoped></style>
4. 路由传值
- 如果
A组件
跳转至B组件
// A组件
this.$router.push({
name: "B",
query: {
id: 1,
name: "Tom",
},
// params: {
// id: 1,
// name: "Tom",
// },
});
// B组件
this.$route.query.id;
this.$route.query.name;
// this.$route.params.id;
// this.$route.params.name;
5. 使用 $ref
- 通过
$ref
的能力,给子组件定义一个 ID,父组件通过这个 ID 可以直接访问子组件里面的方法和属性
父组件---parent.vue
<template>
<div>
<child ref="child1"></child>
<button @click="useRefs">调用子组件的属性和方法</button>
</div>
</template>
<script>
import child from "./child";
export default {
components: { child },
data() {
return {
number: 0,
};
},
methods: {
useRefs() {
this.$refs.child1.updateNum();
},
},
};
</script>
<style scoped></style>
子组件---child2.vue
<template>
<div>
<p>父组件调用子组件属性或方法: {{num}}</p>
</div>
</template>
<script>
export default {
data() {
return {
num: 0,
};
},
methods: {
updateNum() {
++this.num;
},
},
};
</script>
<style scoped></style>
6. 使用 provide 和 inject
provide
允许我们指定我们想要提供给后代组件的数据/方法
然后在任何后代组件
里,我们都可以使用inject
来给当前实例 注入父组件的数据/方法:
父组件---parent.vue
<template>
<div>
<child></child>
<input v-model="message" />
<input v-model.number="obj.age" />
</div>
</template>
<script>
import child from "./child";
export default {
components: { child },
data() {
return {
message: "hello vue!",
obj: {
age: 18,
name: "李四",
},
};
},
provide() {
return {
that: this,
getObj: this.obj,
putMethod: this.outPutLog,
};
},
methods: {
outPutLog(value) {
console.log(value); // hello vue inject
},
},
};
</script>
<style scoped></style>
任何后代组件---child.vue
<template>
<div>
<p>子组件注入依赖: {{that.message}}</p>
<p>{{getObj.name + "今年" + getObj.age + "岁了"}}</p>
</div>
</template>
<script>
export default {
data() {
return {};
},
inject: ["that", "getObj", "putMethod"],
mounted() {
this.putMethod("hello vue inject");
},
};
</script>
<style scoped></style>
7. $parent
// 获父组件的数据
this.$parent.message;
// 写入父组件的数据
this.$parent.message = 2;
// 访问父组件的计算属性
this.$parent.bar;
// 调用父组件的方法
this.$parent.func1();
8. Vue.observable(object)
- 随着组件的细化,多组件间的数据共享越来越普遍,
vuex
是可以解决组件数据共享的问题, 但是当开发一个不大的应用时, 为了避免代码的冗余繁杂,可以使用vue 2.6.0
提供的一个API
--observable API
, 他可以简单的处理一些多组件数据共享的问题. - 如果项目
vue
版本低于2.6.0
, 又要使用Vue.observable(object)
, 此时就需要升级vue
和vue-template-compiler
版本, 两者的版本需要同步更新, 否则会报错.
// 升级版本
npm update vue -S "或者" yarn add vue -S
npm update vue-template-compiler -S "或者" yarn add vue-template-compiler -D
献上官方文档地址: Vue.observable(object)
下面献上代码实例
首先在src
目录下创建一个store.js
, 里面提供一个store
和mutations
对象 提供一些方法.
Component1
可以跳转至Component2
store.js
import Vue from "vue";
export let store = Vue.observable({ name: "李四", age: 18 });
export let mutations = {
setAge(age) {
store.age = age;
},
setName(name) {
store.name = name;
},
};
Component1
<template>
<div>
<p>{{ this.name + "今年" + this.age + "岁了" }}</p>
<input
type="text"
v-model="myName"
@change="changeName(myName)"
placeholder="名字"
/>
<input
type="text"
v-model="myAge"
@change="changeAge(myAge)"
placeholder="年龄"
/>
<div>
<button @click="routerPush">跳转至Component2</button>
</div>
</div>
</template>
<script>
import { store, mutations } from "@/store";
export default {
name: "Component1",
data() {
return {
message: "hello vue!",
myName: "",
myAge: "",
};
},
computed: {
name() {
return store.name;
},
age() {
return store.age;
},
},
methods: {
changeName: mutations.setName,
changeAge: mutations.setAge,
routerPush() {
this.$router.push({
name: "Component2",
});
},
},
};
</script>
<style scoped></style>
Component2
<template>
<div>
<p>{{ age }}</p>
</div>
</template>
<script>
import { store, mutations } from "./store";
export default {
name: "Component2",
data() {
return {};
},
computed: {
age() {
return store.age;
},
},
};
</script>
<style scoped></style>
9. vuex
- 不详细介绍,篇幅太长~~~~
请移步: Vuex