亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Vue組件通信

philadelphia / 3434人閱讀

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

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

一般來說Vue組件是以下幾種關(guān)系

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

本文闡述了幾種常用的通信方式和使用場景

props&&emit

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

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

// component-a




// component-b


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

缺點:只能用于父子組件通信

ref&&$parent / $children

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

ref:給元素或組件注冊引?信息

$parent/$children:訪問父/子組件

ref
// component-a


$parent / $children

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

// component-a




// component-b


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

provide/inject

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

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

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

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

一個對象,對象的 key 是本地的綁定名,value 是:

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

一個對象,該對象的:

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

default 屬性是降級情況下使用的 value

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

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

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

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

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


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

例如通過這個特性保存登錄信息

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

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


優(yōu)點:

跨級注入

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

缺點:

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

Vuex

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

優(yōu)點:

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

缺點:

需要額外引入管理庫

Bus

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

可以使用一個空的vue實例作為事件總線中間件Bus處理組件間的通信

首先在全局定義bus

let bus = new Vue();

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

然后就可以在組件中使用$on,$emit,off來監(jiān)聽,分發(fā)和銷毀組件

分發(fā)組件

// component-c


監(jiān)聽組件

// component-d


最好在組件銷毀之前清除監(jiān)聽事件

優(yōu)點:

使用簡單,不需要額外支持

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

缺點:

需要在組件銷毀時,手動清除事件監(jiān)聽

事件過多時比較混亂

dispatch/broadcast

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

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

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

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

因為基于組件樹結(jié)構(gòu)的事件流方式實在是讓人難以理解,并且在組件結(jié)構(gòu)擴(kuò)展的過程中會變得越來越脆弱。這種事件方式確實不太好,我們也不希望在以后讓開發(fā)者們太痛苦。并且$dispatch 和 $broadcast 也沒有解決兄弟組件間的通信問題。

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

模擬dispatch/broadcast

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

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

首先需要正確地向上或向下找到對應(yīng)的組件實例,并在它上?觸發(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);
    }
  }
};

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

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

優(yōu)點:

使用簡單

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

缺點:

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

findComponents系列

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

向上找到最近的指定組件

向上找到所有的指定組件

向下找到最近的指定組件

向下找到所有指定的組件

找到指定組件的兄弟組件

5個方法都是通過遞歸和遍歷,通過組件name選項匹配到指定組件返回

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

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

向上找到所有的指定組件
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, // 遞歸逐級向上尋找
            componentName));
    } else {
        return [];
    }
}

findComponentsUpward會返回的是?個數(shù)組,包含了所有找到的組件實例
findComponentsUpward 的使?場景較少

向下找到最近的指定組件
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)前組件的全部?組件,所以需要遍歷?遍,找到有沒有匹配到的組件 name,如果沒找到,繼續(xù)遞歸找每個 $children$children,直到找到最近的?個為?

向下找到所有指定的組件
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 做累加器,并?遞歸將找到的組件合并為?個數(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 多了?個參數(shù) exceptMe ,是否把本身除外,默認(rèn)是 true 。尋找兄弟組件的?法,是先獲取 context.$parent.$children,也就是?組件的全部?組件,這??當(dāng)前包含了本身,所有也會有第三個參數(shù)exceptMeVue.js 在渲染組件時,都會給每個組件加?個內(nèi)置的屬性 _uid,這個 _uid 是不會重復(fù)的,借此我們可以從?系列兄弟組件中把??排除掉。

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/103608.html

相關(guān)文章

  • Vue 組件通信方式

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

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

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

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

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

    I_Am 評論0 收藏0
  • vue組件通信的幾種方式

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

    vspiders 評論0 收藏0
  • 整理4種Vue組件通信方式

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

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

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

    Harpsichord1207 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<