感覺Vue中父子傳參的方式,實在是太多了,於是做一個小總結,只是總結我所知道的。 歡迎吐槽
1.父傳子
基本就用一個方式,props
父親通過在 標籤 中寫入需要傳入的資料。
<!--father.vue-->
<template>
<div>
我是爸爸,下面是兒子
<son title='兒子' :selected='selected'></son>
</div>
</template>
複製程式碼
兒子在 例項中的 props
選項中獲取
//son.vue
export default {
name:'son',
props:{
selected:{
type:Boolean
},
title:{
type:String
}
}
}
複製程式碼
2.子傳父
# update:my-prop-name
模式
Vue 是單項資料流,所以不允許 兒子 直接修改父親的資料,也不允許兒子直接修改自己的props
。
假設一個情況,點選兒子,兒子需要改變 selected
的狀態。
兒子方面
觸發點選事件後, 讓兒子觸發一個 update
事件,把新的 selected
傳出去
<!--son.vue-->
<template>
<div class="son" @click="onClick">
title:{{title}} selected:{{selected}}
</div>
</template>
<script>
export default {
name: "son",
props: {
selected: {
type: Boolean
},
title: {
type: String
}
},
methods: {
onClick() {
this.$emit("update:selected", !this.selected); //關鍵點
}
}
};
</script>
<style>
.son {
border: 1px solid red;
}
</style>
複製程式碼
父親方面
在標籤中監聽 update
事件,並將傳過來的 $event
付給 selected
,這樣就完成了一次傳參。
<!--father.vue-->
<template>
<div>
我是爸爸,下面是兒子
<son title='兒子' :selected='selected' @update:selected='selected=$event'></son>
<!--關鍵點-->
</div>
</template>
<script>
import Son from "./son";
export default {
name: "father",
components: {
Son
},
data() {
return {
selected: true
};
}
};
</script>
複製程式碼
簡單方式
.sync 修飾符
<!--father.vue-->
<template>
<div>
我是爸爸,下面是兒子
<son title='兒子' :selected.sync='selected'></son>
<!--關鍵點-->
</div>
</template>
複製程式碼
# $parents API
兒子方面
從 this.$parent
中可以獲取到 父元件 的 data 資料 ,直接進行修改,是不是很刺激。
methods: {
onClick() {
this.$parent.selected = !this.$parent.selected;
}
}
複製程式碼
雖然刺激,但是,我建議呼叫父元件的函式,來切換狀態。
父親方面
//father.vue
export default {
name: "father",
components: {
Son
},
data() {
return {
selected: true
};
},
methods: {
changeSelected() {
this.selected = !this.selected;
}
}
};
複製程式碼
兒子方面
//son.vue
methods: {
onClick() {
this.$parent.changeSelected();
}
}
複製程式碼
# EventBus
如果只是一個父親,一個兒子上面的方法非常的簡單實用,但是如果是祖孫三代傳參呢?上面的方法就很麻煩了。
具體怎麼麻煩,可以看一下我的這篇文章,用原始的方法造 tabs輪子:zhuanlan.zhihu.com/p/39601572
廢話不多說,開始用 EventBus做一個簡單的 tabs元件。
#app.vue
<template>
<div id="app">
<tab selected='news'>
<tab-item name='news'>新聞</tab-item>
<tab-item name='car'>汽車</tab-item>
<tab-item name=‘code’>程式碼</tab-item>
<tab-pane name='news'>新聞列表</tab-pane>
<tab-pane name='car'>汽車列表</tab-pane>
<tab-pane name=‘code’>程式碼列表</tab-pane>
</tab>
</div>
</template>
<script>
import Tab from "./components/tabs.vue";
import TabItem from "./components/tab-item";
import TabPane from "./components/tab-pane";
export default {
name: "app",
components: {
Tab,
TabItem,
TabPane
}
};
</script>
複製程式碼
# tabs.vue
<template>
<div>
<slot></slot>
</div>
</template>
<script>
import TabItem from "./tab-item.vue";
import Vue from "vue"; //引入VUE
export default {
name: "tab",
props: {
selected: {
type: [Number, String]
}
},
data() {
return {
eventBus: new Vue() // 建立 eventBus
};
},
provide() {
return {
eventBus: this.eventBus // 提供 eventBus
};
},
mounted() {
this.eventBus.$emit("update:selected", this.selected);
//釋出訊息,告訴大家,現在的selected是啥
}
};
</script>
<style>
</style>
複製程式碼
# tabs-item.vue
<template>
<div @click="onClick" :class="{active}">
<slot/>
</div>
</template>
<script>
export default {
name: "tab-item",
props: {
name: {
type: [String, Number]
}
},
inject: ["eventBus"], //注入 eventBus
data() {
return {
active: false
};
},
created() {
this.eventBus.$on("update:selected", newSelected => {
this.active = this.name === newSelected;
}); //接收訊息,如果newselected 和我的 name 相同,那麼我就被選中了
},
methods: {
onClick() {
this.eventBus.$emit("update:selected", this.name);
//釋出訊息,如果點選了我,我就告訴大家,我被選中了
}
}
};
</script>
<style>
.active {
color: red;
}
</style>
複製程式碼
# tab-pane.vue
<template>
<div v-if="active" class="pane">
<slot/>
</div>
</template>
<script>
export default {
name: "tab-pane",
props: {
name: {
type: [String, Number]
}
},
data() {
return {
active: false
};
},
inject: ["eventBus"],//注入 eventBus
created() {
this.eventBus.$on("update:selected", newSelected => {
this.active = this.name === newSelected;
});
//接收訊息,如果newselected 和我的 name 相同,那麼我就被選中了
}
};
</script>
<style>
.pane {
color: red;
}
</style>
複製程式碼
# 靈活運用 provide inject
//father.vue
export default {
name:'father',
data(){
return {
someThing:'father'
}
},
provide(){
return {
father:this
}
}
}
複製程式碼
//son.vue
export default {
name:'son',
inject:['father'],
methods:{
onClick(){
this.father.someThing = 'son'
}
}
}
複製程式碼