方法一:$emit / props
- 父組件經過props的方式向子組件傳遞,子組件經過$emit觸發父組件中v-on綁定的自定義事件
<!--父組件-->
<template>
<div>
<Child :message="message" @customEvent="customEvent"/>
</div>
</template>
<script>
export default {
components:{
Child
},
data(){
return {
message:'來自父組件的問候'
}
},
methods:{
customEvent(value){
//執行子組件觸發的事件
console.log(value)
}
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--子組件-->
<template>
<div>
<p>{{message}}</p>
<button @click="handleClick">點擊向父組件傳值</button>
</div>
</template>
<script>
export default {
props:['message'],//獲得父組件傳遞過來的數據
methods:{
handleClick(){
//觸發父組件中的事件
this.$emit('customEvent','來自子組件的問候');
}
}
}
</script>
方法2、$parent / $children 與 ref
- ref:若是在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;若是用在子組件上,引用就指向組件實例
- $parent / $children:訪問父 / 全部子實例
<!--父組件-->
<template>
<div>
<Child ref='children'/>
<button @click="handleClick">訪問子組件</button>
</div>
</template>
<script>
import Child from './child'
export default {
components:{
Child
},
data(){
return {
message:'我是父組件的數據'
}
},
methods:{
handleClick(){
console.log(this.$refs.children.message)
console.log(this.$children[0].message)
//須要注意的是使用$children返回的是一個數組
}
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--子組件-->
<template>
<div>
<p>{{message}}</p>
<button @click="handleClick">訪問父組件</button>
</div>
</template>
<script>
export default {
data(){
return {
message:'我是子組件的數據'
}
},
methods:{
handleClick(){
console.log(this.$parent.message)
}
}
}
</script>
方法3、中央事件總線bus
- 新建一個Vue事件bus對象,而後經過 bus.$emit 觸發事件, bus.$on 監聽觸發的事件。
//eventBus.js
import Vue from 'vue';
export default new Vue();
- 在須要用到的兩個不一樣組件分別引入便可
- 須要注意的是接受數據的組件要清除事件總線eventBus
<!--A組件-->
<template>
<div>
<p>A組件</p>
<button @click="handleClick">向B組件傳值</button>
</div>
</template>
<script>
import eventBus from 'eventBus.js的路徑'
export default {
data(){
return {
data:'我是A組件的數據'
}
},
methods:{
handleClick(){
eventBus.$emit('change',this.data);
}
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--B組件-->
<template>
<div>
<p>B組件</p>
</div>
</template>
<script>
import eventBus from 'eventBus.js的路徑';
export default {
//觸發事件通常用mounted 或 created 鉤子來監聽
mounted(){
//觸發和監聽的事件名稱要一致
eventBus.$on('change',(value)=>{
console.log(value)
})
},
destroyed(){
eventBus.$off('change');
}
}
</script>
方法4、依賴注入 provide和inject
- 適用場景:高階插件/組件庫
- 類型:
- provide:Object | () => Object
- inject:Array<string> | { [key: string]: string | Symbol | Object }
- 父組件中經過provider來提供變量,而後在子組件中經過inject來注入變量。
- 不論子組件有多深,只要調用了inject那麼就能夠注入provider中的數據。
<!--父組件-->
<template>
<div>
<h1>父組件</h1>
<Son/>
</div>
</template>
<script>
import Son from './son'
export default {
components:{
Son
},
data(){
return {
message:'我是父組件的數據'
}
},
provide(){
return {
message:this.message
}
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--子組件-->
<template>
<div>
<h1>子組件</h1>
<GrandSon />
</div>
</template>
<script>
import GrandSon from './grandSon';
export default {
components:{
GrandSon
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--孫子組件-->
<template>
<div>
<h1>孫子組件</h1>
<p>{{message}}</p>
</div>
</template>
<script>
export default {
inject:['message']
}
</script>
方法5、$attrs 和 $listeners
- 適用場景:多層、遞歸組件
- $attrs 是包含了因此父組件在子組件上設置的屬性(除了prop傳遞的屬性、class 和 style )
- $listeners 是組件的內置屬性,它的值是父組件(不含.native修飾器的) v-on事件監聽器
- 若是子組件已經綁定$listener中同名的監聽器,則兩個監聽器函數會以冒泡的方式前後執行
<!--父組件-->
<template>
<div>
<h1>父組件</h1>
<Son :message1="message1" :message2="message2" name='attr' v-on="{onChange1,onChange2}"/>
</div>
</template>
<script>
import Son from './son'
export default {
components:{
Son
},
data(){
return {
message1:'我是父組件的數據1',
message2:'我是父組件的數據2'
}
},
methods:{
onChange1(val){
console.log("父組件:" + val)
},
onChange2(val){
console.log(val)
}
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--子組件-->
<template>
<div>
<h1>子組件</h1>
<!--關鍵點-->
<GrandSon v-bind="$attrs" v-on="$listeners" @onChange1="onChange1"/>
</div>
</template>
<script>
import GrandSon from './grandSon';
export default {
inheritAttrs:false,
/**
* 一、當設置inheritAttrs爲true(默認)時,子組件的頂層標籤元素中會渲染出父組件傳遞過來(前提:子組件的props中未註冊父組件傳遞過來的屬性)的屬性。
* 二、當設置inheritAttrs爲false時,子組件的頂層標籤元素中不會渲染出父組件傳遞過來(前提:子組件的props中未註冊父組件傳遞過來的屬性)的屬性。
* 三、無論inheritAttrs爲true或者false,子組件中都能經過$attrs屬性獲取到父組件中傳遞過來的屬性。
*/
components:{
GrandSon
},
methods:{
//與父組件監聽的事件同名了
onChange1(val){
console.log('子組件:'+val)
}
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--孫子組件-->
<template>
<div>
<h1>孫子組件</h1>
<p>{{message2}}</p>
<button @click="handleClick">點擊觸發父組件的方法</button>
</div>
</template>
<script>
export default {
props:['message2'], //message2被聲明
created(){
console.log(this.$attrs) //{message1: "我是父組件的數據1", name: "attr"}
console.log(this.$listeners) //{onChange1: ƒ, onChange2: ƒ}
},
methods:{
handleClick(){
this.$emit('onChange1','來自孫子的問候')
}
}
}
</script>
方法6、v-model
- 父組件經過v-model傳遞值給子組件時,會自動傳遞一個value的prop屬性,在子組件中經過this.$emit('input',val)自動修改v-model綁定的值
- prop屬性和觸發事件能夠經過model修改
<!--父組件-->
<template>
<div>
<h1>父組件</h1>
<p>{{inputValue}}</p>
<Son v-model="inputValue"/>
</div>
</template>
<script>
import Son from './son'
export default {
components:{
Son
},
data(){
return {
inputValue:'父組件的默認消息'
}
}
}
</script>
<!-------------------------------------------------------------------------------------------->
<!--子組件-->
<template>
<div>
<h1>子組件</h1>
<p>父組件傳過來的值:{{value}}</p>
<input @input="handleChange" />
</div>
</template>
<script>
export default {
model:{
prop:'value', //默認(value)能夠修改任意值
event:'input' //默認(input)事件名也能夠修改
},
props:{
value:String
},
methods:{
handleChange(e){
this.$emit('input',e.target.value)
}
}
}
</script>
方法7、VueX