vue必須掌握之組件通訊(7種方法)

方法一:$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

相關文章
相關標籤/搜索