1. 程式人生 > 程式設計 >Vue2 的12種元件通訊

Vue2 的12種元件通訊

目錄
  • 1. props
  • 2. .sync
  • 3. v-model
  • 4. ref
  • 5. $emit / v-on
  • 6. $attrs / $listeners
  • 7. $children / $parent
  • 8. provide / inject
  • 9. EventBus
  • 10. x
  • 11. $root
  • 12. slot

下面把每一種元件通訊方式的寫法一一列出

1. props

父元件向子元件傳送資料,這應該是最常用的方式了
子元件接收到資料之後,不能直接修改父元件的資料。會報錯,所以當父元件重新渲染時,資料會被覆蓋。如果子元件內要修改的話推薦使用 computed

// Parent.vue 傳送
<template>
    <child :msg="msg"></child>
</template>

// Child.vue 接收
export default {
  // 寫法一 用陣列接收
  props:['msg'],// 寫法二 用物件接收,可以限定接收的資料型別、設定預設值、驗證等
  props:{
      msg:{
          type:String,default:'這是預設資料'
      }
  },mounted(){
      console.log(this.msg)
  },}

2. .sync

可以幫我們實現父元件向子元件傳遞的資料 的雙向繫結,所以子元件接收到資料後可以直接修改,並且會同時修改父元件的資料

// Parent.vue
<template>
    <child :page.sync="page"></child>
</template>
<script>
export default {
    data(){
        return {
            page:1
        }
    }
}

// Child.vue
export default {
    props:["page"],computed(){
        // 當我們在子元件裡修改 currentPage 時,父元件的 page 也會隨之改變
        currentPage {
            get(){
                return this.page
            },set(newVal){
                this.$emit("update:page",newVal)
            }
        }
    }
}
</script>

3. v-model

.sync 類似,可以實現將父元件傳給子元件的資料為雙向繫結,子元件通過 $emit 修改父元件的資料

// Parent.vue
<template>
    <child v-model="value"></child>
</template>
<script>
export default {
    data(){
        return {
            value:1
        }
    }
}

// Child.vue
<template>
    <input :value="value" @input="handlerChange">
</template>
export default {
    props:["value"],// 可以修改事件名,預設為 input
    model:{
        event:"updateValue"
    },methods:{
        handlerChange(e){
            this.$emit("input",e.target.value)
            // 如果有上面的重新命名就是這樣
            this.$emit("updateValue",e.target.value)
        }
    }
}
</script>

4. ref

ref 如果在普通的DOM元素上,引用指向的就是該DOM元素;
如果在子元件上,引用的指向就是子元件例項,然後父元件就可以通過 ref 主動獲取子元件的屬性或者呼叫子元件的方法

// Child.vue
export default {
    data(){
        return {
            name:"沐華"
        }
    },methods:{
        someMethod(msg){
            console.log(msg)
        }
    }
}

// Parent.vue
<template>
    <child ref="child"></child>
</template>
<script>
export default {
    mounted(){
        const child = this.$refs.child
        console.log(child.name) // 沐華
        child.someMethod("呼叫了子元件的方法")
    }
}
</script>

5.http://www.cppcns.com $emit / v-on

子元件通過派發事件的方式給父元件資料,或者觸發父元件更新等操作

// Child.vue 派發
export default {
  data(){
      return { msg: "這是發給父元件的資訊" }
  },methods: {
      handleClick(){
          this.$emit("sendMsg",this.msg)
      }
  },}
// Parent.vue 響應
<template>
    <child v-on:sendMsg="getChildMsg"></child>
    // 或 簡寫
    <child @sendMsg="getChildMsg"></child>
</template>

export default {
    methods:{
        getChildMsg(msg){
            console.log(msg) // 這是父元件接收到的訊息
        }
    }
}

6. $attrs / $listeners

多層巢狀元件傳遞資料時,如果只是傳遞資料,而不做中間處理的話就可以用這個,比如父元件向孫子元件傳遞資料時
$attrs:包含父作用域裡除 class style 除外的非 props 屬性集合。通過 this.$attrs 獲取父作用域中所有符合條件的屬性集合,然後還要繼續傳給子元件內部的其他元件,就可以通過 v-bind="$attrs"

$listeners:包含父作用域裡 .native 除外的監聽事件集合。如果還要繼續傳給子元件內部的其他元件,就可以通過 v-on="$linteners"

使用方式是相同的

// Parent.vue
<template>
    <child :name="name" title="1111" ></child>
</template
export default{
    data(){
        return {
            name:"沐華"
        }
    }
}

// Child.vue
<template>
    // 繼續傳給孫子元件
    <sun-child v-bind="$attrs"></sun-child>
</template>
export default{
    props:["name"],// 這裡可以接收,也可以不接收
    mounted(){
        // 如果props接收了name 就是 { title:1111 },否則就是{ name:"沐華",title:1111 }
        console.log(this.$attrs)
    }
}

7. $children / $parent

$children:獲取到一個包含所有子元件(不包含孫子元件)的 VueComponent 物件陣列,可以直接拿到子元件中所有資料和方法等
$parent:獲取到一個父節點的 VueComponent 物件,同樣包含父節點中所有資料和方法等

// Parent.vue
export default{
    mounted(){
        this.$children[0].someMethod() // 呼叫第一個子元件的方法
        this.$children[0].name // 獲取第一個子元件中的屬性
    }
}

// Child.vue
export default{
    mounted(){
        this.$parent.someMethod() // 呼叫父元件的方法
        this.$parent.name // 獲取父元件中的屬性
    }
}

8. provide / inject

provide / inject 為依賴注入,說是不推薦直接用於應用程式程式碼中,但是在一些外掛或元件庫裡卻是被常用,所以我覺得用也沒啥,還挺好用的

provide:可以讓我們指定想要提供給後代元件的資料或方法
inject:在任何後代元件中接收想要新增在這個元件上的資料或方法,不管元件巢狀多深都可以直接拿來用

要注意的是 provide inject 傳遞的資料不是響應式的,也就是說用 inject 接收來資料後,provide 裡的資料改變了,後代元件中的資料不會改變,除非傳入的就是一個可監聽的物件
所以建議還是傳遞一些常量或者方法

// 父元件
export default{
    // 方法一 不能獲取 methods 中的方法
    provide:{
        name:"沐華",age: this.data中的屬性
    },// 方法二 不能獲取 data 中的屬性
    provide(){
        return {
            name:"沐華",someMethod:this.someMethod // methods 中的方法
        }
    },methods:{
        someMethod()客棧{
            console.log("這是注入的方法")
        }
    }
}

// 後代元件
export default{
    inject:["name","someMethod"],mounted(){
        console.log(this.name)
        this.someMethod()
    }
}

9. EventBus

EventBus 是中央事件匯流排,不管是父子元件,兄弟元件,跨層級元件等都可以使用它完成通訊操作
定義方式有三種

/方法一:

// 抽離成一個單獨的  檔案 Bus.js ,然後在需要的地方引入
// Bus.js
import Vue from "vue"
export default new Vue()

方法二 :直接掛載到全域性

// main.js
import Vue from "vue"
Vue.prototype.$bus = new Vue()

方法三 :注入到 Vue 根物件上

// main.js
import Vue from "vue"
new Vue({
    el:"#app",data:{
        Bus: new Vue()
    }
})

使用如下,以方法一按需引入為例

// 在需要向外部發送自定義事件的元件內
<template>
    <button @click="handlerClick">按鈕</button>
</template>
import Bus from "./Bus.js"
export default{
    methods:{
        handlerClick(){
            // 自定義事件名 sendMsg
            Bus.$emit("sendMsg","這是要向外部發送的資料")
        }
    }
}

// 在需要接收外部事件的元件內
import Bus from "./Bus.js"
export default{
    mounted(){
        // 監聽事件的觸發
        Bus.$on("sendMsg",data => {
            console.log("這是接收到的資料:",data)
        })
    },beforeDestroy(){
        // 取消監聽
        Bus.$off("sendMsg")
    }
}

10. Vuex

Vuex 是狀態管理器,集中式儲存管理所有元件的狀態。這一塊內容過長,如果基礎不熟的話可以看這個Vuex,然後大致用法如下

比如建立這樣的檔案結構

Vue2 的12種元件通訊

index.js 裡內容如下:

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import actions from './actions'
import mutations from './mutations'
import state from './state'
import user from './modules/user'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    user
  },getters,actions,mutations,state
})
export default store

然後在 main.js 引入:

import Vue from "vue"
import store from "./store"
new Vue({
    el:"#app",store,render: h => h(App)
})

然後在需要的使用元件裡:

import { mapGetters,mapMutations } from "vuex"
export default{
    computed:{
        // 方式一 然後通過 this.屬性名就可以用了
        ...mapGetters(["引入getters.js裡屬性1","屬性2"])
 程式設計客棧       // 方式二
        ...mapGetters("user",["user模組裡的屬性1","屬性2"])
    },methods:{
        // 方式一 然後通過 this.屬性名就可以用了
        ...mapMutations(["引入mutations.js裡的方法1","方法2"])
        // 方式二
        ...mapMutations("user",["引入user模組裡的方法1","方法2"])
    }
}

// 或者也可以這樣獲取
this.$store.state.xxx
this.$store.state.user.xxx

11. $root

$root 可以拿到 App.vue 裡的資料和方法

12. slot

就是把子元件的資料通過插槽的方式傳給父元件使用,然後再插回來

// Child.vue
<template>
    <div>
        <slot :user="user"></slot>
    </div>
</template>
export default{
    data(){
        return {
            user:{ name:"沐華" }
        }
    }
}

// Parent.vue
<template>
    <div>
        <child v-slot="slotProps">
            {{ slotProps.user.name }}
        </child>
    </div>
</template>

到此這篇關於Vue2.x 的12種元件通訊的文章就介紹到這了,更多相關Vue2.x 元件通訊內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!