vue中不同情況下怎麼進行通訊?方式分享

2022-04-20 22:00:43
vue中不同情況下怎麼進行通訊?下面本篇文章給大家分析一下中不同情況下的通訊方式,希望對大家有所幫助!

其實對於vue中元件通訊這件事大家也都不陌生。甚至張口就來,畢竟這也是面試中的經常會問到的。由於之前沒有進行過細緻的考慮,在寫小專案的時候遇到了元件中通訊的需求,然後上來就寫,結果發現沒有用,查了好久才知道那種方式不適用這樣情況。所以經過這次事情決定寫篇文章,對於通訊方式進行更清楚更細緻的分類,畢竟不是每種通訊方式都適用於所有場景。(學習視訊分享:)

同視窗(也就是同瀏覽器同一個頁籤內)

同瀏覽器同頁籤內主要涉及的就是父子元件的傳值。

vuex:狀態管理器:適用一個專案裡的任何元件,包容性極強

對於狀態管理器的概念大家應該也不會陌生。

  • 多個元件可以共用一個或者多個狀態值。不管元件的層級有多深都可以正常存取。所以這是一種官方直接支援的通訊方式。
  • 注意:對於小型單頁應用而言,該選擇並不是很建議,對於小型專案而言使用vuex反而會變得更加繁瑣,就像是一個75斤150cm的人,穿了一件170cm110斤人的衣服一樣,看著就很鬆鬆垮垮撐不起來。

provide / inject (寫法基於v2.2.1及以上版本):適用N級元件,但是必須是單線傳承的那種

這對選項需要一起使用,以允許一個祖先元件向其所有子孫後代注入一個依賴,不論元件層次有多深,並在其上下游關係成立的時間裡始終生效。

  • 就是相當於有一個N層樓的樓房,最頂層的是父級元件,每層樓之間會公用一個管子,這個管子就是provide。而管子在每層樓都有一個出口叫:inject
  • 注意:provideinject 繫結並不是可響應的。不過如果你傳入了一個可監聽的物件,那麼其物件的 property 還是可響應的。
  • 讓咱們來看看程式碼
// parent.vue
// 此處忽略template模板的東西
<script>
export default {
    name: 'parent',
    // provide有兩種寫法
    // 第一種
    provide: {
        a: 1,
        b: 2
    }
    // 第二種
    provide() {
        return {
            a: 1,
            b: 2
        }
    }
}
</script>
// child.vue
// 此處忽略template模板的東西
<script>
export default {
    name: 'child',
    // inject
    // 第一種
    inject: [ 'a', 'b' ]
    // 第二種
    inject: {
        abc: { // 可以指定任意不與data,props衝突的變數名,然後指定是指向provide中的哪個變數
            from: 'a',
            default: 'sfd' // 如果預設值不是基本資料型別,那就得改用:default: () => {a:1,b:2}
        },
        b: {
            default: '33'
        }
    }
}
</script>

props:適用相鄰兩元件的傳值(父->子);$emit: 子 -> 父

正經的props/$emit可太常見了,都是用爛了的,就不用寫範例程式碼了吧。

  • 只適用於相鄰級別的父子元件之間傳值
  • 對於多級元件的傳值雖然也能用props傳,但是吧,這樣的話會讓程式碼很難維護,極其不推薦。

eventBus: 地位與vuex差不多,適用任意元件,包容性極強

問題:

  • 不方便維護:如果在專案裡用的多了,可能出現方法名衝突導致異常的問題,而且比較不方便排查。
  • 範例:
// utils/eventBus.js
import Vue from 'vue'
const EventBus = new Vue()
export default EventBus
// main.js
// 進行全域性掛載
import eventBus from '@/utils/eventBus'
Vue.prototype.$eventBos = eventBus
// views/parent.vue
<template>
    <div>
        <button @click="test">測試</button>
    </div>
</template>
<script>
export default {
    data() {
        return {}
    },
    methods: {
        test() {
            this.$eventBus.$emit('testBus', 'test')
        }
    }
}
// views/child.vue
<template>
    <div>
        {{ testContent }} <!-- test -->
    </div>
</template>
<script>
export default {
    data() {
        return {
            testContent: ''
        }
    },
    mounted() {
        this.$eventBus.$on('test', e => this.testContent = e)
    }
}

$attrs / $listeners

  • $attrs
    • 官方解釋
      • 從父元件傳給自定義子元件的屬性,如果沒有 prop 接收會自動設定到子元件內部的最外層標籤上,如果是 classstyle 的話,會合並最外層標籤的 classstyle
      • 如果子元件中不想繼承父元件傳入的非 prop 屬性,可以使用 inheritAttrs 禁用繼承,然後通過 v-bind="$attrs" 把外部傳入的 非 prop 屬性設定給希望的標籤上,但是這不會改變 classstyle
    • 當父元件向子元件傳值,但是子元件並沒有全部將傳過來的值在props中宣告時,在子元件裡就可以通過$attrs來代理獲取所有父元件傳過來的值。
    • 範例:這是父元件

1.png

    • 這是子元件: 沒有宣告props

    2.png

    • 這是dom展示:

    3.png

    • 此時,通過dom可以發現,所有沒有宣告的資訊,全部出現在了子元件的根元素上。
    • 如果要讓沒有宣告的資訊不出現在子元件的根元素上,那就在子元件與data同級的位置加個屬性:inheritAttrs: false;這樣就不會未通過props接收的變數就不會出現在子元件的根元素上了
    • 至於怎麼傳遞給子元件的子元件的子元件的子元件....等,那就需要給子元件的子元件依次都繫結:v-bind="$attrs"即可。
    • 注意這樣只適用於傳遞資料。
  • $listeners
    • 官方解釋:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器。它可以通過 v-on="$listeners" 傳入內部元件——在建立更高層次的元件時非常有用
    • 當父元件向子元件傳遞迴撥時,子元件可以通過$listeners代理所有回撥。
    • 範例:這是父元件

4.png

    • 這是子元件

5.png

    • 這是執行展示:

      6.png

    • 同時可以發現子元件加上inheritAttrs:false之後根元件裡的未宣告props接受的變數消失了

      7.png

  • 最後:建議最好不要用這個玩意,雖然他們都可以相對便捷的將第一級元件的屬性,方法回撥傳遞給N級子元件中的任一級,但是之後進行bug定位,或者分析需求將會是一個比較大的挑戰。

不同視窗(同瀏覽器不同頁籤內)

同瀏覽器的不同頁籤之間的通訊,大多數的場景是:專案裡的增刪改查都是開啟的新頁面,然後新增結束後就觸發列表頁重新獲取列表。這種場景下有什麼方法呢?

監聽stroage事件

// 需要監聽的頁面
mounted() {
    window.addEventListener('storage', this.storageEvent);
},
beforeDestroy() {
    window.removeEventListener()
}
methods: {
    storageEvent(e) {
        console.log("storage值發生變化後觸發:", e)
    }
}
  • 切記:第一條:要記得將監聽的事件在元件銷燬之前解除監聽。否則會給你驚」喜「
  • 切記:第二條:其中監聽方法回撥一定要在methods中定義,然後通過this進行參照,否則你在解除事件監聽的時候將無效。

不同瀏覽器

不同瀏覽器的同一網站的有通訊的必要嗎?
如果有那就:websocket(比如聊天室)
哈哈哈哈

(學習視訊分享:、)

以上就是vue中不同情況下怎麼進行通訊?方式分享的詳細內容,更多請關注TW511.COM其它相關文章!