Vue数据传递
关系:父亲、孩子
1.$emit / props / v-model
父传子 props
Father.vue
<template>
<div>
<h1>家庭资产:{{ fatherM }}</h1>
<Child :fatherM="fatherM" />
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
name: "Father",
components: { Child },
data() {
return {
fatherM: 3000,
};
},
};
</script>
Child.vue
<template>
<div>
<h2>子女资产:{{ fatherM }}</h2>
</div>
</template>
<script>
export default {
name: "child",
//详细props写法请看另一篇文章 https://blog.youkuaiyun.com/Jenny_ljj/article/details/117282848
props: {
fatherM: Number,
},
};
</script>
子传父 $emit
Father.vue
<template>
<div>
<h1>家庭资产:{{ fatherM }}</h1>
<!-- 有几种写法 -->
<Child @setMoney="getMoneyUU" />
<Child @update:value="(value) => (this.fatherM = value)" />
<Child :value.sync="fatherM" /> <!-- 语法糖 -->
<Child @setMoney="(fatherM) => (this.fatherM = fatherM)" />
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
name: "Father",
components: { Child },
data() {
return {
fatherM: 0,
};
},
methods: {
getMoneyUU(num) {
this.fatherM = num
},
},
};
</script>
Child.vue
<template>
<div>
<button @click="getMoney">给爸爸的零花钱</button>
</div>
</template>
<script>
export default {
name: "child",
methods: {
getMoney() {
this.$emit("setMoney", 10000);
// this.$emit("update:value", 10000);
},
},
};
</script>
子传父 v-model
Father.vue
<Child
:fatherM="fatherM"
@update:fatherM="(fatherM) => (this.fatherM = fatherM)"
/>
等于
<Child v-model="fatherM" />
Child.vue
this.$emit("update:fatherM", 1000);
关系:爷爷,爸爸
2. $refs / ref
子传父 !!!
Grandpa.vue
<template>
<div>
<!-- ref : dom节点 => 返回的是dom对象
ref : 组件 => 返回的是组件实例 -->
<Father ref="father" />
</div>
</template>
<script>
import Father from "./Father.vue";
export default {
name: "Grandpa",
components: { Father },
mounted() {
console.log(this.$refs.father.name);
this.$refs.father.getCall();
}
};
</script>
Father.vue
<script>
export default {
name: "Father",
data() {
return {
name: "李四",
age: 12,
sex: "男",
};
},
methods: {
getCall() {
console.log("好吧好吧");
},
},
};
</script>
关系:爷爷, 爸爸 , 孩子
3.provide / inject
父传子(爷爷 -> 爸爸 -> 孩子)
grandpa.vue
<template>
<div>
<Father />
</div>
</template>
<script>
import Father from "./Father.vue";
export default {
// 提供者
provide() {
return {
grandpa: this,
};
},
name: "Grandpa",
components: { Father },
data() {
return {
name: "张三",
age: 12,
sex: "男",
};
},
methods: {
notice() {
console.log(1256546);
},
},
};
</script>
Father.vue
<template>
<div>
<Child />
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
name: "Father",
// 注入
inject: ["grandpa"],
components: { Child },
mounted() {
// this 是页面自身的实例对象,然后爷爷把自己页面的内容通过inject注入到了父亲自身的实例对象中 如下图
console.log(this);
},
};
</script>
Child.vue
<script>
export default {
// 注入
inject: ["grandpa"],
name: "Child",
mounted() {
// this 是页面自身的实例对象,然后爷爷把自己页面的内容通过inject注入到了孩子自身的实例对象中 如下图
console.log(this);
},
};
</script>
关系:爷爷, 爸爸 , 孩子
4.$attrs / $listeners
父传子(爷爷 -> 爸爸 -> 孩子)
对比图
关系: 爸爸,两兄弟
5.eventBus
兄弟组件传值
Father.vue
<template>
<div>
<Child />
<Child2 />
</div>
</template>
<script>
import Child from "./Child.vue";
import Child2 from "./Child2.vue";
export default {
name: "Father",
components: { Child, Child2 },
mounted() {
this.$eventBus.$on("fatherTouch", (param) => {
console.log(param);
});
},
};
</script>
Child.vue
<script>
export default {
name: "Child",
mounted() {
this.$eventBus.$on("childTouch", (param) => {
console.log(param);
});
// 子传父 ---- 因为响应问题 有时候这边还没请求 父亲那边就访问了,所以加个$nextTick 避免没有打印的问题
this.$nextTick(() => {
this.$eventBus.$emit("fatherTouch", "好了好了");
});
},
};
</script>
Child2.vue
<script>
export default {
name: "Child2",
mounted() {
this.$eventBus.$emit("childTouch", "来了来了");
},
};
</script>
- 然后我们来创建中间事件 $eventBus
- 先在src目录下新建一个文件夹 -> 接着创建两个文件
- 然后在main.js里引入一下
event.js
export default function (Vue) {
Vue.prototype.$eventBus = new Vue();
}
index.js
import eventExtend from './event';
export { eventExtend };
main.js
// extends是文件夹的名字
import { eventExtend } from './extends';
eventExtend(Vue);
关系:爷爷,爸爸,孩子
6.$dispatch / $broadcast == $parent / $children
简单介绍一下$dispatch / $broadcast == $parent / $children的关系
$dispatch:派发 === $parent 子传父的时候用
$broadcast :广播 === $children 父传子的时候用
可以通过扩展函数再原型上绑定派发、广播事件,原理就是通过 $parent / $children 循环 $emit
Grandpa.vue
<template>
<div>
<h1>爷爷的资产:{{ money }}</h1>
<Father :money="money" @useMoneyAA="useMoneyUU" />
</div>
</template>
<script>
import Father from "./Father.vue";
export default {
name: "Grandpa",
components: { Father },
data() {
return {
money: 10000,
};
},
methods: {
useMoneyUU(num) {
this.money -= num;
// 父传子: 当孩子点击用钱按钮时 就会触发notice事件,爷爷会告诉孩子爸爸 孩子用钱了
this.$eventBroadcast("notice");
},
},
};
</script>
Father.vue
<template>
<div>
<h1>爸爸继承爷爷的资产:{{ money }}</h1>
<Child :money="money" @notice="notice" />
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
name: "Father",
components: { Child },
props: {
money: Number,
},
methods: {
notice() {
console.log("孩子用钱了");
},
},
};
</script>
Child.vue
<template>
<div>
<h2>孩子继承爸爸的资产:{{ money }}</h2>
<button @click="useMoney">用钱</button>
</div>
</template>
<script>
export default {
name: "Child",
// 这个方法最前面有 是用来接收父级的money参数 也可称 父传子
props: {
money: Number,
},
methods: {
useMoney() {
// this.$parent.$emit("useMoney", 100); 这个方法也可用 但只适用于子级数量少的时候!!!!
// 子传父 : 每次用100块钱,金钱总数减少
this.$eventDispatch("useMoneyAA", 100); //进行封装过的组件
},
},
};
</script>
event.js (前面有写怎么创建需要引入什么,自行看第5个 eventBus)
export default function (Vue) {
Vue.prototype.$eventDispatch = function (name, value) {
let parent = this.$parent;
while (parent) {
parent.$emit(name, value);
parent = parent.$parent;
}
};
Vue.prototype.$eventBroadcast = function (name, value) {
const bc = (children) => {
children.map((c) => {
c.$emit(name, value);
if (c.$children) {
bc(c.$children);
}
});
};
bc(this.$children);
};
}
最后 : 不建议用 $ parent / $ children 以及组件派发/广播,$dispatch1.0是有得,2.0就没有了,因为这样结构不清晰