亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue 中的受控與非受控組件的實(shí)現(xiàn)

 更新時(shí)間:2018年12月17日 09:43:15   作者:aryu  
這篇文章主要介紹了Vue 中的受控與非受控組件的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

受控組件

什么是受控組件?

其值由React控制的輸入表單元素稱為“受控組件”。

受控組件有兩個(gè)特點(diǎn):1. 設(shè)置value值,value由state控制,2. value值一般在onChange事件中通過(guò)setState進(jìn)行修改

什么時(shí)候使用受控組件?

需要對(duì)組件的value值進(jìn)行修改時(shí),使用受控組件。比如:頁(yè)面中有一個(gè)按鈕,每點(diǎn)擊一次按鈕受控組件的值加1.

非受控組件

什么是非受控組件?

表單數(shù)據(jù)由 DOM 處理的組件非受控組件。

非受控組件有兩個(gè)特點(diǎn):1. 不設(shè)置value值,2. 通過(guò)ref獲取dom節(jié)點(diǎn)然后再取value值

<input type="text" placeholder="請(qǐng)輸入姓名" name='username' ref={(input) => this.usernameElem = input}/>

取值方法:this.usernameElem.value

什么時(shí)候使用非受控組件?

任何時(shí)候都不需要改變組件的value值,這時(shí)候可以使用非受控組件。

Vue 中的受控與非受控組件

熟悉 React 的開(kāi)發(fā)者應(yīng)該對(duì)“受控組件”的概念并不陌生,實(shí)際上對(duì)于任何組件化開(kāi)發(fā)框架而言,都可以實(shí)現(xiàn)所謂的受控與非受控,Vue 當(dāng)然也不例外。并且理解受控與非受控對(duì)應(yīng)的需求場(chǎng)景,可以讓我們?cè)谠O(shè)計(jì)一些基礎(chǔ)組件時(shí)思路更加清晰,暴露出來(lái)的組件 API 也更加合理、統(tǒng)一。

需求

許多 UI 組件都是有狀態(tài)(stateful)的,而這個(gè)狀態(tài)是由組件外部控制還是組件內(nèi)部維護(hù),也就對(duì)應(yīng)了受控與非受控兩種模式。

例如 Tabs 組件是很常見(jiàn)的一種 UI 組件,它的核心狀態(tài)就是記錄當(dāng)前 active 的 Tab,并且允許用戶切換。

很多時(shí)候我們只希望 Tabs 可以正確的展示 active 的內(nèi)容、并在用戶操作時(shí)正常切換,不需要進(jìn)行任何干預(yù),那么就希望 只需要傳入所有的 Tab 內(nèi)容,不需要再做額外的配置。

但有的時(shí)候我們又希望對(duì) Tabs 的狀態(tài)有很強(qiáng)的控制能力,例如多個(gè)關(guān)聯(lián)的 Tabs,子級(jí) Tabs 的內(nèi)容需要根據(jù)父級(jí) Tabs 的 active Tab 動(dòng)態(tài)切換,這時(shí)候就會(huì)希望 Tabs 組件可以暴露足夠充分的 API,來(lái)實(shí)現(xiàn)業(yè)務(wù)的需求。

因此我們可以用一種通用的模式,來(lái)讓任意組件的任意狀態(tài)同時(shí)兼容受控與非受控兩種模式,讓不同需求場(chǎng)景下都可以使用最合理的 API。

簡(jiǎn)化示例

我們用一個(gè)簡(jiǎn)單的 Tabs 實(shí)現(xiàn)來(lái)演示這種通用的組件 API 設(shè)計(jì)模式,簡(jiǎn)化的部分包括:

  • 用 index 來(lái)作為 Tab 的唯一標(biāo)識(shí)
  • Tab content 只支持字符串

可以打開(kāi) online DEMO 配合閱讀

API 設(shè)計(jì)

對(duì)于 Vue 組件而言,API 設(shè)計(jì)主要指的是內(nèi)部的 data, computed, methods 以及對(duì)外的 props, events。在這個(gè)示例中,我們會(huì)用 activeIdx 作為核心狀態(tài),所有的 API 也都會(huì)圍繞這個(gè)狀態(tài)命名。

非受控模式

如上文所說(shuō),非受控模式指的是使用者不需要關(guān)心控制組件的狀體,完全交由組件內(nèi)部維護(hù)。

因此我們的 API 會(huì)包括:

{
 props: {
  defaultActiveIdx: {
   type: Number,
   default: 0
  }
 },
 data() {
  return {
   localActiveIdx: this.defaultActiveIdx
  }
 },
 methods: {
  handleActiveIdxChange(idx) {
   this.localActiveIdx = idx;
   this.$emit("active-idx-change", idx);
  }
 }
}

localActiveIdx 是我們用來(lái)存放 active index 的組件內(nèi) data,對(duì)于非受控模式而言,雖然不希望在外部維護(hù)狀態(tài),但是仍有可能希望在外部決定初始狀態(tài),所以我們用 defaultActiveIdx 這個(gè) props 決定 localActiveIdx 的初始值。

之后當(dāng)我們用 v-for="(tab, idx) in tabs" 指令生成所有的 Tab 時(shí),就可以通過(guò) idx === localActiveIdx 的方式判斷當(dāng)前 Tab 是否 active,再通過(guò) @click="handleActiveIdxChange(idx)" 就可以實(shí)現(xiàn)對(duì) localActiveIdx 的更新。

同樣的,我們也可以通過(guò) {{ tabs[localActiveIdx].content }} 展示 active Tab 的內(nèi)容。

需要注意的是在 handleActiveIdxChange 的事件處理中,我們也 emit 了 active-idx-change 這一事件,這樣可以方便外部在不需要管理組件狀態(tài)的同時(shí)也可以與組件狀態(tài)保持同步。例如我們希望將 active Tab 反映在 URL 中,就可以在外部監(jiān)聽(tīng) active-idx-change 這一事件,并將當(dāng)前 index 同步到路由中,在將路由中獲取到的 index 作為 defaultActiveIdx 傳入,就可以實(shí)現(xiàn) URL 和 Tabs 的同步。

受控模式

對(duì)于受控模式來(lái)說(shuō),我們可以理解為 active index 是外部傳入的 props,由外部自行維護(hù)其狀態(tài)。

因此我們只需要添加如下 props:

props: {
 activeIdx: Number
}

由于我們已經(jīng)有對(duì)外 emit 的事件 active-idx-change,所以外部用以下方式就可以用一個(gè) data 屬性 externalActiveIdx 維護(hù)對(duì)應(yīng)狀態(tài):

<tabs
 :tabs="tabs"
 :activeIdx="externalActiveIdx"
 @active-idx-change="this.externalActiveIdx = $event"
/>

當(dāng)然由于在這種模式下外部對(duì)狀態(tài)有完全的控制權(quán),所以在 active-idx-change 的事件處理中也可以做更為復(fù)雜的判斷,例如是否允許激活目標(biāo) Tab 之類的校驗(yàn)。

而在 Tabs 組件內(nèi)部,我們還需要做一些小的修改。在受控模式中,我們所有狀態(tài)相關(guān)的處理都是直接使用 localActiveIdx,而現(xiàn)在我們的邏輯應(yīng)該變?yōu)椤叭绻嬖?activeIdx props,則使用,否則使用 localActiveIdx”。

為了保證以上邏輯不會(huì)讓我們的組件內(nèi)部實(shí)現(xiàn)變得復(fù)雜、易錯(cuò),我們引入一個(gè) computed 屬性:

computed: {
 _activeIdx() {
  return this.activeIdx || this.localActiveIdx;
 }
}

這樣我們就可以把狀態(tài)相關(guān)的判斷改為通過(guò) idx === _activeIdx 判斷一個(gè) Tab 是否為激活狀態(tài),也通過(guò) {{ tabs[_activeIdx].content }} 展示 active Tab 的內(nèi)容。

同樣,我們?cè)?handleActiveIdxChange 的方法內(nèi)部也可以增加一個(gè)判斷,如果存在 props aciveIdx 則不更新 localActiveIdx:

handleActiveIdxChange(idx) {
 if (this.activeIdx === undefined) {
  this.localActiveIdx = idx;
 }
 this.$emit("active-idx-change", idx);
}

在一些更復(fù)雜的組件中,可能會(huì)頻繁判斷是否為受控模式并做不同的處理,這時(shí)候通過(guò) this.activeIdx 這樣的核心狀態(tài) props 是否傳入來(lái)判斷是否為受控模式是一個(gè)不錯(cuò)的實(shí)踐。

總結(jié)

最終我們?yōu)?active index 設(shè)計(jì)的完整 API 如下:

{
 props: {
  activeIdx: Number,
  defaultActiveIdx: {
   type: Number,
   default: 0
  }
 },
 data() {
  return {
   localActiveIdx: this.defaultActiveIdx
  };
 },
 computed: {
  _activeIdx() {
   return this.activeIdx || this.localActiveIdx;
  }
 },
 methods: {
  handleActiveIdxChange(idx) {
   if (this.activeIdx === undefined) {
    this.localActiveIdx = idx;
   }
   this.$emit("active-idx-change", idx);
  }
 }
}

通過(guò)這種 API 設(shè)計(jì)方式,可以讓我們?cè)O(shè)計(jì)的基礎(chǔ)組件使用方式更一致,拓展性更強(qiáng),不論是開(kāi)發(fā)還是使用時(shí)思路也會(huì)更加簡(jiǎn)潔清晰。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • element前端實(shí)現(xiàn)壓縮圖片的功能

    element前端實(shí)現(xiàn)壓縮圖片的功能

    本文主要介紹了element前端實(shí)現(xiàn)壓縮圖片的功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Vue中如何動(dòng)態(tài)顯示表格內(nèi)容

    Vue中如何動(dòng)態(tài)顯示表格內(nèi)容

    這篇文章主要介紹了Vue中如何動(dòng)態(tài)顯示表格內(nèi)容問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Vue使用NProgress實(shí)現(xiàn)頁(yè)面頂部的進(jìn)度條顯示效果

    Vue使用NProgress實(shí)現(xiàn)頁(yè)面頂部的進(jìn)度條顯示效果

    這篇文章主要介紹了vue Nprogress頁(yè)面頂部進(jìn)度條功能實(shí)現(xiàn),NProgress是頁(yè)面跳轉(zhuǎn)是出現(xiàn)在瀏覽器頂部的進(jìn)度條,本文通過(guò)實(shí)例代碼給大家講解,需要的朋友可以參考下
    2022-12-12
  • 在Vue中是如何封裝axios

    在Vue中是如何封裝axios

    這篇文章主要介紹在Vue中是如何封裝axios的相關(guān)資料,axios的封裝主要是幫助我們簡(jiǎn)化代碼和利于后期的更新維護(hù),感興趣的小伙伴可以和小編一起來(lái)閱讀下面文章的具體內(nèi)容
    2021-10-10
  • vue中利用Promise封裝jsonp并調(diào)取數(shù)據(jù)

    vue中利用Promise封裝jsonp并調(diào)取數(shù)據(jù)

    Promise就是一個(gè)給一步操作提供的容器,在這個(gè)容器里,有兩個(gè)階段無(wú)法改變的階段,這兩個(gè)階段在文中給大家提到。對(duì)vue中利用Promise封裝jsonp并調(diào)取數(shù)據(jù) 的相關(guān)知識(shí)感興趣的朋友,跟隨小編一起看看吧
    2019-06-06
  • Vue3中內(nèi)置組件Teleport的基本使用與典型案例

    Vue3中內(nèi)置組件Teleport的基本使用與典型案例

    Teleport是一種能夠?qū)⑽覀兊哪0逡苿?dòng)到DOM中Vue app之外的其他位置的技術(shù),下面這篇文章主要給大家介紹了關(guān)于Vue3中內(nèi)置組件Teleport的基本使用與典型案例的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • vue.nextTick()與setTimeout的區(qū)別及說(shuō)明

    vue.nextTick()與setTimeout的區(qū)別及說(shuō)明

    這篇文章主要介紹了vue.nextTick()與setTimeout的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 基于vue3+TypeScript實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Calendar組件

    基于vue3+TypeScript實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Calendar組件

    最近在學(xué)習(xí) react,在學(xué)習(xí)到使用 react 開(kāi)發(fā) Calendar 組件的時(shí)候,突然聯(lián)想到使用 vue 進(jìn)行 Calendar 功能的實(shí)現(xiàn),因?yàn)槟壳笆褂玫募夹g(shù)棧是 vue,剛好可以加深下對(duì) vue3 和 ts 的使用印象,所以本文給大家介紹了基于vue3+TypeScript實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Calendar組件
    2024-05-05
  • vue無(wú)限輪播插件代碼實(shí)例

    vue無(wú)限輪播插件代碼實(shí)例

    這篇文章主要介紹了vue無(wú)限輪播插件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Vue跨端渲染實(shí)現(xiàn)多端無(wú)縫銜接

    Vue跨端渲染實(shí)現(xiàn)多端無(wú)縫銜接

    這篇文章主要介紹了Vue跨端渲染實(shí)現(xiàn)多端無(wú)縫銜接,Vue跨端渲染是一種基于Vue框架的跨平臺(tái)開(kāi)發(fā)技術(shù),能夠?qū)崿F(xiàn)Web、iOS和Android三端的無(wú)縫銜接,提高開(kāi)發(fā)效率和用戶體驗(yàn)
    2023-05-05

最新評(píng)論