最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue 中的受控與非受控組件的實現

 更新時間:2018年12月17日 09:43:15   作者:aryu  
這篇文章主要介紹了Vue 中的受控與非受控組件的實現,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

受控組件

什么是受控組件?

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

受控組件有兩個特點:1. 設置value值,value由state控制,2. value值一般在onChange事件中通過setState進行修改

什么時候使用受控組件?

需要對組件的value值進行修改時,使用受控組件。比如:頁面中有一個按鈕,每點擊一次按鈕受控組件的值加1.

非受控組件

什么是非受控組件?

表單數據由 DOM 處理的組件非受控組件。

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

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

取值方法:this.usernameElem.value

什么時候使用非受控組件?

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

Vue 中的受控與非受控組件

熟悉 React 的開發(fā)者應該對“受控組件”的概念并不陌生,實際上對于任何組件化開發(fā)框架而言,都可以實現所謂的受控與非受控,Vue 當然也不例外。并且理解受控與非受控對應的需求場景,可以讓我們在設計一些基礎組件時思路更加清晰,暴露出來的組件 API 也更加合理、統(tǒng)一。

需求

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

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

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

但有的時候我們又希望對 Tabs 的狀態(tài)有很強的控制能力,例如多個關聯的 Tabs,子級 Tabs 的內容需要根據父級 Tabs 的 active Tab 動態(tài)切換,這時候就會希望 Tabs 組件可以暴露足夠充分的 API,來實現業(yè)務的需求。

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

簡化示例

我們用一個簡單的 Tabs 實現來演示這種通用的組件 API 設計模式,簡化的部分包括:

  • 用 index 來作為 Tab 的唯一標識
  • Tab content 只支持字符串

可以打開 online DEMO 配合閱讀

API 設計

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

非受控模式

如上文所說,非受控模式指的是使用者不需要關心控制組件的狀體,完全交由組件內部維護。

因此我們的 API 會包括:

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

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

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

同樣的,我們也可以通過 {{ tabs[localActiveIdx].content }} 展示 active Tab 的內容。

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

受控模式

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

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

props: {
 activeIdx: Number
}

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

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

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

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

為了保證以上邏輯不會讓我們的組件內部實現變得復雜、易錯,我們引入一個 computed 屬性:

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

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

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

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

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

總結

最終我們?yōu)?active index 設計的完整 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);
  }
 }
}

通過這種 API 設計方式,可以讓我們設計的基礎組件使用方式更一致,拓展性更強,不論是開發(fā)還是使用時思路也會更加簡潔清晰。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • vue-cli webpack配置文件分析

    vue-cli webpack配置文件分析

    這篇文章主要介紹了vue-cli webpack配置文件分析,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • vue計算屬性computed、事件、監(jiān)聽器watch的使用講解

    vue計算屬性computed、事件、監(jiān)聽器watch的使用講解

    今天小編就為大家分享一篇關于vue計算屬性computed、事件、監(jiān)聽器watch的使用講解,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • vue實現微信瀏覽器左上角返回按鈕攔截功能

    vue實現微信瀏覽器左上角返回按鈕攔截功能

    這篇文章主要介紹了vue實現微信瀏覽器左上角返回按鈕攔截功能,本文通過實例代碼相結合的形式給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • Vue中使用Echarts儀表盤展示實時數據的實現

    Vue中使用Echarts儀表盤展示實時數據的實現

    這篇文章主要介紹了Vue中使用Echarts儀表盤展示實時數據的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • vue實現左右伸縮方式(el-drawer自定義位置展開收縮)

    vue實現左右伸縮方式(el-drawer自定義位置展開收縮)

    這篇文章主要介紹了vue實現左右伸縮方式(el-drawer自定義位置展開收縮),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Vue3.5中新增的baseWatch函數用法詳解

    Vue3.5中新增的baseWatch函數用法詳解

    在Vue 3.5.0-beta.3版本中新增了一個base watch函數,這個函數用法和我們熟知的watch API一模一樣,下面就跟隨小編一起來了解一下它的具體使用吧
    2024-11-11
  • Element Badge標記的使用方法

    Element Badge標記的使用方法

    這篇文章主要介紹了Element Badge標記的使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • Vue+Openlayers自定義軌跡動畫

    Vue+Openlayers自定義軌跡動畫

    這篇文章主要為大家詳細介紹了Vue+Openlayers自定義軌跡動畫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • vuex新手進階篇之取值

    vuex新手進階篇之取值

    Vuex 是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式,下面這篇文章主要給大家介紹了關于vuex新手進階篇之取值的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • vue?cli?局部混入mixin和全局混入mixin的過程

    vue?cli?局部混入mixin和全局混入mixin的過程

    這篇文章主要介紹了vue?cli?局部混入mixin和全局混入mixin的過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05

最新評論

普洱| 丹东市| 凯里市| 饶河县| 抚远县| 鄂伦春自治旗| 南宫市| 岐山县| 安龙县| 德昌县| 获嘉县| 宜宾县| 肥城市| 汤阴县| 汉沽区| 威远县| 陆河县| 合山市| 潮州市| 六安市| 青河县| 广丰县| 八宿县| 白山市| 岳池县| 安平县| 清丰县| 双流县| 教育| 南康市| 康乐县| 阜新市| 安阳县| 亚东县| 临洮县| 定兴县| 新巴尔虎左旗| 嘉鱼县| 武乡县| 北宁市| 鄂尔多斯市|