成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Vue組件通信

philadelphia / 3365人閱讀

摘要:使,最主要的的是跨組件通信全局?jǐn)?shù)據(jù)維護(hù)。這兩種法旦發(fā)出事件后,任何組件都是可以接收到的,就近原則,且會(huì)在第次接收到后停冒泡,除返回。并且和也沒(méi)有解決兄弟組件間的通信問(wèn)題。

Vue的組件是其非常重要的系統(tǒng),組件之間的通信也是開(kāi)發(fā)中不可避免的需求

一般來(lái)說(shuō)Vue組件是以下幾種關(guān)系

A組件和B組件、B組件和C組件、B組件和D組件是父子關(guān)系,C組件和D組件是兄弟關(guān)系,A組件和C/D組件是隔代關(guān)系。

本文闡述了幾種常用的通信方式和使用場(chǎng)景

props&&emit

父組件通過(guò) props 傳遞數(shù)據(jù)給子組件,子組件通過(guò) emit 發(fā)送事件傳遞數(shù)據(jù)給父組件

這種父子通信方式也就是典型的單向數(shù)據(jù)流,父組件通過(guò) props 傳遞數(shù)據(jù),子組件不能直接修改 props , 而是必須通過(guò)發(fā)送事件的方式告知父組件修改數(shù)據(jù)。

// component-a




// component-b


優(yōu)點(diǎn):易于使用,結(jié)構(gòu)清晰

缺點(diǎn):只能用于父子組件通信

ref&&$parent / $children

這兩種都是直接得到組件實(shí)例,使?后可以直接調(diào)?組件的?法或訪(fǎng)問(wèn)數(shù)據(jù)

ref:給元素或組件注冊(cè)引?信息

$parent/$children:訪(fǎng)問(wèn)父/子組件

ref
// component-a


$parent / $children

$parent$children都是基于當(dāng)前上下文訪(fǎng)問(wèn)父組件和子組件

// component-a




// component-b


ref$parent/$children的優(yōu)缺點(diǎn)和props&&emit相同,弊端都是無(wú)法在跨級(jí)和兄弟間通信

provide/inject

ref$parent/$children在跨級(jí)通信中有一定的弊端。
Vue.js 2.2.0 版本后新增 provide / inject API
vue文檔
這對(duì)選項(xiàng)需要?起使?,以允許?個(gè)祖先組件向其所有?孫后代注??個(gè)依賴(lài),不論組件層次有多深,并在起上下游關(guān)系成?的時(shí)間?始終?效

provide 選項(xiàng)應(yīng)該是一個(gè)對(duì)象或返回一個(gè)對(duì)象的函數(shù)。該對(duì)象包含可注入其子孫的屬性。

inject 選項(xiàng)應(yīng)該是:

一個(gè)字符串?dāng)?shù)組

一個(gè)對(duì)象,對(duì)象的 key 是本地的綁定名,value 是:

在可用的注入內(nèi)容中搜索用的 key (字符串或 Symbol),或

一個(gè)對(duì)象,該對(duì)象的:

from 屬性是在可用的注入內(nèi)容中搜索用的 key (字符串或 Symbol)

default 屬性是降級(jí)情況下使用的 value

provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個(gè)可監(jiān)聽(tīng)的對(duì)象,那么其對(duì)象的屬性還是可響應(yīng)的。

// 父級(jí)組件提供 "foo"
var Provider = {
  provide: {
    foo: "bar"
  },
  // ...
}

// 子組件注入 "foo"
var Child = {
  inject: ["foo"],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}
模擬Vuex

在做 Vue ?型項(xiàng)?時(shí),可以使? Vuex 做狀態(tài)管理。使用 provide / inject,可以模擬 達(dá)到 Vuex 的效果 。
使? Vuex,最主要的?的是跨組件通信、全局?jǐn)?shù)據(jù)維護(hù)。?如?戶(hù)的登錄信息維護(hù)、通知信息維護(hù)等全局的狀態(tài)和數(shù)據(jù)

通常vue應(yīng)用都有一個(gè)根根組件app.vue,可以?來(lái)存儲(chǔ)所有需要的全局?jǐn)?shù)據(jù)和狀態(tài),methods 等。項(xiàng)目中所有的組件其父組件都是app,通過(guò)provideapp實(shí)例暴露對(duì)外提供


接下來(lái)任何組件只要通過(guò) inject 注? app.vueapp 的話(huà),都可以直接通過(guò)this.app.xxx 來(lái)訪(fǎng)問(wèn) app.vuedata、computed、methods 等內(nèi)容

例如通過(guò)這個(gè)特性保存登錄信息

export default {
  provide() {
    return {
      app: this
    };
  },
  data() {
    return {
      userInfo: null
    };
  },
  methods: {
    getUserInfo() {
      // 這?通過(guò) ajax 獲取?戶(hù)信息后,賦值給this.userInfo;
      $.ajax("/user", data => {
        this.userInfo = data;
      });
    }
  },
  mounted() {
    this.getUserInfo();
  }
};

之后在任何??或組件,只要通過(guò) inject 注? app 后,就可以直接訪(fǎng)問(wèn) userInfo 的數(shù)據(jù)了


優(yōu)點(diǎn):

跨級(jí)注入

所有子組件都可獲取到注入的信息

缺點(diǎn):

注入的數(shù)據(jù)非響應(yīng)式

Vuex

Vuex 是一個(gè)專(zhuān)為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。當(dāng)需要開(kāi)發(fā)開(kāi)發(fā)大型單頁(yè)應(yīng)用(SPA),就應(yīng)該考慮使用Vuex了,它能把組件的共享狀態(tài)抽取出來(lái),當(dāng)做一個(gè)全局單例模式進(jìn)行管理。這樣不管你在何處改變狀態(tài),都會(huì)通知使用該狀態(tài)的組件做出相應(yīng)修改。
Vuex官方文檔已經(jīng)給出了詳細(xì)的使用方式

優(yōu)點(diǎn):

官方集成管理庫(kù),可以處理各種場(chǎng)景的通信和狀態(tài)管理

缺點(diǎn):

需要額外引入管理庫(kù)

Bus

如果不是大型項(xiàng)目,狀態(tài)管理不復(fù)雜,數(shù)據(jù)量不是很大,沒(méi)有必要使用Vuex

可以使用一個(gè)空的vue實(shí)例作為事件總線(xiàn)中間件Bus處理組件間的通信

首先在全局定義bus

let bus = new Vue();

var eventBus = {
  install(Vue, options) {
    Vue.prototype.$bus = bus;
  }
};
Vue.use(eventBus);

然后就可以在組件中使用$on,$emit,off來(lái)監(jiān)聽(tīng),分發(fā)和銷(xiāo)毀組件

分發(fā)組件

// component-c


監(jiān)聽(tīng)組件

// component-d


最好在組件銷(xiāo)毀之前清除監(jiān)聽(tīng)事件

優(yōu)點(diǎn):

使用簡(jiǎn)單,不需要額外支持

可以實(shí)現(xiàn)跨級(jí)和兄弟間通信

缺點(diǎn):

需要在組件銷(xiāo)毀時(shí),手動(dòng)清除事件監(jiān)聽(tīng)

事件過(guò)多時(shí)比較混亂

dispatch/broadcast

$dispatch$broadcast 是Vue1.x中提供的API,前者?于向上級(jí)派發(fā)事件,只要是它的?級(jí)(?級(jí)或多級(jí)以上),都可以在組件內(nèi)通過(guò) $on 監(jiān)聽(tīng)到,后者相反,是由上級(jí)向下級(jí)?播事件

// 子組件
vm.$dispatch(eventName,params)
// 父組件
vm.$on(eventName
, (params) => {
console.log(params); 
});

$broadcast 類(lèi)似,只不過(guò)?向相反。這兩種?法?旦發(fā)出事件后,任何組件都是可以接收到的,就近原則,?且會(huì)在第?次接收到后停?冒泡,除?返回 true 。

這2個(gè)方法在已經(jīng)被棄用,Vue官方給出的解釋是:

因?yàn)榛诮M件樹(shù)結(jié)構(gòu)的事件流方式實(shí)在是讓人難以理解,并且在組件結(jié)構(gòu)擴(kuò)展的過(guò)程中會(huì)變得越來(lái)越脆弱。這種事件方式確實(shí)不太好,我們也不希望在以后讓開(kāi)發(fā)者們太痛苦。并且$dispatch 和 $broadcast 也沒(méi)有解決兄弟組件間的通信問(wèn)題。

雖然在開(kāi)發(fā)中,沒(méi)有Vuex這樣的專(zhuān)業(yè)狀態(tài)管理工具方便好用,但是在獨(dú)立組件庫(kù)和一些特殊場(chǎng)景中,也是非常好用的一種傳遞方式。

模擬dispatch/broadcast

自行模擬dispatch/broadcast無(wú)法達(dá)到與原方法一模一樣的效果,但是基本功能都是可以實(shí)現(xiàn)的,解決組件之間的通信問(wèn)題

方法有功能有向上/下找到對(duì)應(yīng)的組件,觸發(fā)指定事件并傳遞數(shù)據(jù),其下/上級(jí)組件已經(jīng)通過(guò)$on監(jiān)聽(tīng)了該事件。

首先需要正確地向上或向下找到對(duì)應(yīng)的組件實(shí)例,并在它上?觸發(fā)?法。

function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
    const name = child.$options.name;
    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat([params]));
    }
  });
}
export default {
  methods: {
    dispatch(componentName, eventName, params) {
      let parent = this.$parent || this.$root;
      let name = parent.$options.name;

      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;
        if (parent) {
          name = parent.$options.name;
        }
      }

      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

這兩個(gè)?法都接收了三個(gè)參數(shù),第?個(gè)是組件的 name 值,?于向上或向下遞歸遍歷來(lái)尋找對(duì)應(yīng)的組件,第?個(gè)和第三個(gè)就是上?分析的?定義事件名稱(chēng)和要傳遞的數(shù)據(jù)。

dispatch ?,通過(guò) while 語(yǔ)句,不斷向上遍歷更新當(dāng)前組件(即上下?為當(dāng)前調(diào)?該?法的組件)的?組件實(shí)例(變量 parent 即為?組件實(shí)例),直到匹配到定義的 componentName 與某個(gè)上級(jí)組件的 name 選項(xiàng)?致時(shí),結(jié)束循環(huán),并在找到的組件實(shí)例上,調(diào)? $emit ?法來(lái)觸發(fā)?定義事件 eventName 。 broadcast ?法與之類(lèi)似,只不過(guò)是向下遍歷尋找

優(yōu)點(diǎn):

使用簡(jiǎn)單

可以實(shí)現(xiàn)跨級(jí)通信

缺點(diǎn):

原生支持已經(jīng)廢除,需要自行實(shí)現(xiàn)

findComponents系列

上述介紹的各種通信方法都有各自的局限性,我們可以實(shí)現(xiàn)一個(gè) findComponents 系列的方法,可以實(shí)現(xiàn)

向上找到最近的指定組件

向上找到所有的指定組件

向下找到最近的指定組件

向下找到所有指定的組件

找到指定組件的兄弟組件

5個(gè)方法都是通過(guò)遞歸和遍歷,通過(guò)組件name選項(xiàng)匹配到指定組件返回

向上找到最近的指定組件
function findComponentUpward(context, componentName) {
    let parent = context.$parent; // 獲取父級(jí)組件
    let name = parent.$options.name; // 獲取父級(jí)組件名稱(chēng)
    // 如果父級(jí)存在 且 父級(jí)組件 沒(méi)有name 或 name與要尋找的組件名不一致,重置parent和name,再逐級(jí)尋找
    while (parent && (!name || [componentName].indexOf(name) < 0)) {
        parent = parent.$parent;
        if (parent) name = parent.$options.name;
    }
    // 逐級(jí)查找父級(jí)組件名和傳參名是否一致,返回找到的parent
    return parent;
}

findComponentUpward 接收兩個(gè)參數(shù),第?個(gè)是當(dāng)前上下?,即你要基于哪個(gè)組件來(lái)向上尋找,?般都是基于當(dāng)前的組件,也就是傳? this;第?個(gè)參數(shù)是要找的組件的 name 。
dispatch是通過(guò)觸發(fā)和監(jiān)聽(tīng)事件來(lái)完成事件交互,findComponentUpward 會(huì)直接拿到組件的實(shí)例

向上找到所有的指定組件
function findComponentsUpward(context,
    componentName) {
    let parents = []; // 收集指定組件
    const parent = context.$parent;
    if (parent) {
        if (parent.$options.name === componentName)
            parents.push(parent);
        return parents.concat(findComponentsUpward(parent, // 遞歸逐級(jí)向上尋找
            componentName));
    } else {
        return [];
    }
}

findComponentsUpward會(huì)返回的是?個(gè)數(shù)組,包含了所有找到的組件實(shí)例
findComponentsUpward 的使?場(chǎng)景較少

向下找到最近的指定組件
function findComponentDownward(context,
    componentName) {
    const childrens = context.$children;
    let children = null;
    if (childrens.length) {
        for (const child of childrens) {
            const name = child.$options.name;
            if (name === componentName) {
                children = child;
                break;
            } else {
                children = findComponentDownward(child,
                    componentName);
                if (children) break;
            }
        }
    }
    return children;
}

context.$children 得到的是當(dāng)前組件的全部?組件,所以需要遍歷?遍,找到有沒(méi)有匹配到的組件 name,如果沒(méi)找到,繼續(xù)遞歸找每個(gè) $children$children,直到找到最近的?個(gè)為?

向下找到所有指定的組件
function findComponentsDownward(context,
    componentName) {
    return context.$children.reduce((components, child) => {
        if (child.$options.name === componentName)
            components.push(child);
        const foundChilds = findComponentsDownward(child, componentName);
        return components.concat(foundChilds);
    }, []);
}

使? reduce 做累加器,并?遞歸將找到的組件合并為?個(gè)數(shù)組并返回

找到指定組件的兄弟組件
function findBrothersComponents(context,
    componentName, exceptMe = true) {
    let res = context.$parent.$children.filter(item
        => {
        return item.$options.name === componentName;
    });
    let index = res.findIndex(item => item._uid ===
        context._uid);
    if (exceptMe) res.splice(index, 1);
    return res;
}

findBrothersComponents 多了?個(gè)參數(shù) exceptMe ,是否把本身除外,默認(rèn)是 true 。尋找兄弟組件的?法,是先獲取 context.$parent.$children,也就是?組件的全部?組件,這??當(dāng)前包含了本身,所有也會(huì)有第三個(gè)參數(shù)exceptMe。Vue.js 在渲染組件時(shí),都會(huì)給每個(gè)組件加?個(gè)內(nèi)置的屬性 _uid,這個(gè) _uid 是不會(huì)重復(fù)的,借此我們可以從?系列兄弟組件中把??排除掉。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/103608.html

相關(guān)文章

  • Vue 組件通信方式

    摘要:本身提供哪幾種通信方式首先靈感源于,支持雙向綁定,本質(zhì)還是單向數(shù)據(jù)流。跟一樣,組件間最基本的數(shù)據(jù)流是通過(guò)向子組件傳遞數(shù)據(jù)。但是在卻很少使用,因?yàn)榻M件可以自定義事件,即后面的組件間通信方式其實(shí)就是訂閱發(fā)布模式。 例子是在 jsrun.net 平臺(tái)編寫(xiě),不支持移動(dòng)端平臺(tái),所以本文建議在 PC 端進(jìn)行閱讀。 Vue 是數(shù)據(jù)驅(qū)動(dòng)的視圖框架,那么組件間的數(shù)據(jù)通信是必然的事情,那么組件間如何進(jìn)行數(shù)...

    hss01248 評(píng)論0 收藏0
  • vue中8種組件通信方式, 值得收藏!

    摘要:一父組件通過(guò)的方式向子組件傳遞數(shù)據(jù),而通過(guò)子組件可以向父組件通信。而且只讀,不可被修改,所有修改都會(huì)失效并警告。 之前寫(xiě)了一篇關(guān)于vue面試總結(jié)的文章, 有不少網(wǎng)友提出組件之間通信方式還有很多, 這篇文章便是專(zhuān)門(mén)總結(jié)組件之間通信的 vue是數(shù)據(jù)驅(qū)動(dòng)視圖更新的框架, 所以對(duì)于vue來(lái)說(shuō)組件間的數(shù)據(jù)通信非常重要,那么組件之間如何進(jìn)行數(shù)據(jù)通信的呢?首先我們需要知道在vue中組件之間存在什么樣...

    BicycleWarrior 評(píng)論0 收藏0
  • Vue組件基礎(chǔ)與通信

    摘要:組件基礎(chǔ)與通信一腳手架簡(jiǎn)介與安裝之前安裝的是模塊,之后安裝的是模塊。如果是三級(jí)組件通信,該如何處理比如父組件與孫子組件通信。和,提供和注入實(shí)現(xiàn)祖先組件和后代組件之間通信。 Vue組件基礎(chǔ)與通信 一、vue cli腳手架 ① vue cli 簡(jiǎn)介與安裝 vue cli 3.0之前安裝的是vue-cli模塊,vue cli 3.0之后安裝的是@vue/cli模塊。如果已經(jīng)全局安裝了舊版本的...

    I_Am 評(píng)論0 收藏0
  • vue組件通信的幾種方式

    摘要:雖然和都可以獲取組件實(shí)例,但是它們無(wú)法在跨級(jí)或兄弟間通信,這是它們的缺點(diǎn)。也就是在父組件中提供一個(gè)值,并且在需要使用的子孫組件中注入改值,即不僅僅是,只要是的子組件,無(wú)論隔多少代,都可以通過(guò)這個(gè)的方式注入。通過(guò)混入組件,實(shí)現(xiàn)組件間的通信。 寫(xiě)在前面 vue 的組件化應(yīng)該是其最核心的思想了,無(wú)論是一個(gè)大的頁(yè)面還是一個(gè)小的按鈕,都可以被稱(chēng)之為組件?;?Vue 的開(kāi)發(fā),就是在寫(xiě)一個(gè)個(gè)組件,...

    vspiders 評(píng)論0 收藏0
  • 整理4種Vue組件通信方式

    摘要:整理種組件通信方式重點(diǎn)是梳理了前兩個(gè)父子組件通信和通信我覺(jué)得文檔里的說(shuō)明還是有一些簡(jiǎn)易我自己第一遍是沒(méi)看明白。第四種通信方式利用比較復(fù)雜可以單獨(dú)寫(xiě)一篇 整理4種Vue組件通信方式 重點(diǎn)是梳理了前兩個(gè),父子組件通信和eventBus通信,我覺(jué)得Vue文檔里的說(shuō)明還是有一些簡(jiǎn)易,我自己第一遍是沒(méi)看明白。 父子組件的通信 非父子組件的eventBus通信 利用本地緩存實(shí)現(xiàn)組件通信 Vuex...

    MingjunYang 評(píng)論0 收藏0
  • vue組件通信、數(shù)據(jù)傳遞(父子組件,同級(jí)組件

    總結(jié)一下對(duì)vue組件通信的理解和使用。 一、組件目錄結(jié)構(gòu) 父組件:app.vue 子組件:page1.vue 子組件:page2.vue 父組件 app.vue 請(qǐng)輸入單價(jià): import Page1 from ./components/page1; import Page2 from ./components/page2; export de...

    Harpsichord1207 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<