欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React為 Vue 引入容器組件和展示組件的教程詳解

 更新時(shí)間:2018年05月03日 11:34:59   作者:迅雷前端  
這篇文章主要介紹了React為 Vue 引入容器組件和展示組件的教程詳解,文中很詳細(xì)的給大家介紹了使用容器組件的原因,需要的朋友可以參考下

如果你使用過(guò) Redux 開(kāi)發(fā) React,你一定聽(tīng)過(guò) 容器組件(Smart/Container Components) 或 展示組件(Dumb/Presentational Components),這樣劃分有什么樣的好處,我們能否能借鑒這種劃分方式來(lái)編寫 Vue 代碼呢?這篇文章會(huì)演示為什么我們應(yīng)該采取這種模式,以及如何在 Vue 中編寫這兩種組件。

為什么要使用容器組件?

假如我們要寫一個(gè)組件來(lái)展示評(píng)論,在沒(méi)聽(tīng)過(guò)容器組件之前,我們的代碼一般都是這樣寫的:

components/CommentList.vue

<template>
 <ul>
 <li v-for="comment in comments"
  :key="comment.id"
 >
  {{comment.body}}—{{comment.author}}
 </li>
 </ul>
</template>
<script>
export default {
 name: 'CommentList',
 computed: {
 comments () {
  return this.$store.state.comments
 }
 },
 mounted () {
 this.$store.dispatch('fetchComments')
 }
}
</script>

store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
 state: {
 comments: [],
 },

 mutations: {
 setComments(state, comments) {
  state.comments = comments;
 },
 },

 actions: {
 fetchComments({commit}) {
  setTimeout(() => {
  commit('setComments', [
   {
   body: '霸氣側(cè)漏',
   author: '雷叔',
   id: 1123,
   },
   {
   body: '機(jī)智如我',
   author: '蕾妹',
   id: 1124,
   },
  ]);
  });
 },
 },
});

export default store;

這樣寫看起來(lái)理所當(dāng)然,有沒(méi)有什么問(wèn)題,或者可以優(yōu)化的地方呢?

有一個(gè)很顯而易見(jiàn)的問(wèn)題,由于 CommentList.vue 與 項(xiàng)目的 Vuex store 產(chǎn)生了耦合,導(dǎo)致脫離當(dāng)前的項(xiàng)目很難復(fù)用。

有沒(méi)有更好的組件的組織方式,可以解決這個(gè)問(wèn)題呢?是時(shí)候了解下 React 社區(qū)的容器組件的概念了。

什么是容器組件

在 React.js Conf 2015 ,有一個(gè) Making your app fast with high-performance components 的主題介紹了容器組件。

 

容器組件專門負(fù)責(zé)和 store 通信,把數(shù)據(jù)通過(guò) props 傳遞給普通的展示組件,展示組件如果想發(fā)起數(shù)據(jù)的更新,也是通過(guò)容器組件通過(guò) props 傳遞的回調(diào)函數(shù)來(lái)告訴 store。

由于展示組件不再直接和 store 耦合,而是通過(guò) props 接口來(lái)定義自己所需的數(shù)據(jù)和方法,使得展示組件的可復(fù)用性會(huì)更高。

容器組件 和 展示組件 的區(qū)別


展示組件
容器組件
作用 描述如何展現(xiàn)(骨架、樣式) 描述如何運(yùn)行(數(shù)據(jù)獲取、狀態(tài)更新)
直接使用 store
數(shù)據(jù)來(lái)源 props 監(jiān)聽(tīng) store state
數(shù)據(jù)修改 從 props 調(diào)用回調(diào)函數(shù) 向 store 派發(fā) actions

來(lái)自 Redux 文檔 https://user-gold-cdn.xitu.io/2018/5/2/1631f590aa5512b7

用 容器組件/展示組件 模式改造上面的例子

針對(duì)最初的例子,如何快速按照這種模式來(lái)劃分組件呢?我們主要針對(duì) CommentList.vue 進(jìn)行拆分,首先是基本的概要設(shè)計(jì):

概要設(shè)計(jì)

展示組件

components/CommentListNew.vue 這是一個(gè)新的評(píng)論展示組件,用于展示評(píng)論
comments: Array prop 接收以 { id, author, body } 形式顯示的 comment 項(xiàng)數(shù)組。
fetch() 接收更新評(píng)論數(shù)據(jù)的方法
展示組件只定義外觀并不關(guān)心數(shù)據(jù)來(lái)源和如何改變。傳入什么就渲染什么。

comments、fetch 等這些 props 并不關(guān)心背后是否是由 Vuex 提供的,你可以使用 Vuex,或者其他狀態(tài)管理庫(kù),甚至是一個(gè) EventBus,都可以復(fù)用這些展示組件。

同時(shí),可以利用 props 的類型和驗(yàn)證來(lái)約束傳入的內(nèi)容,比如驗(yàn)證傳入的 comments 是否是一個(gè)含有指定字段的對(duì)象,這在之前混合組件的情況是下是沒(méi)有的,提高了代碼的健壯性。

容器組件

containers/CommentListContainer.vue 將 CommentListNew 組件連接到 store
容器組件可以將 store 對(duì)應(yīng)的 state 或者 action 等封裝傳入展示組件。

編碼實(shí)現(xiàn)

Talk is cheap, show me the code!
components/CommentListNew.vue

這個(gè)文件不再依賴 store,改為從 props 傳遞。

值得注意到是 comments 和 fetch 分別定義了 type 、default 和 validator,用以定義和驗(yàn)證 props。

<template>
 <ul>
 <li v-for="comment in comments"
  :key="comment.id"
 >
  {{comment.body}}—{{comment.author}}
 </li>
 </ul>
</template>

<script>
export default {
 name: 'CommentListNew',

 props: {
 comments: {
  type: Array,
  default () {
  return []
  },
  validator (comments) {
  return comments.every(comment =>
   'body' in comment &&
   'author' in comment &&
   'id' in comment
  )
  }
 },
 fetch: {
  type: Function,
  default: () => {}
 }
 },

 mounted () {
 this.fetch()
 }
}
</script>

containers/CommentListContainer.vue

容器組件的職責(zé)

通過(guò) computed 來(lái)獲取到狀態(tài)更新,傳遞給展示組件

通過(guò) methods 定義回調(diào)函數(shù),回調(diào)函數(shù)內(nèi)部調(diào)用 store 的 dispatch 方法,傳遞給展示組件

<template>
 <CommentList
 :comments="comments"
 :fetch="fetchComments"
 ></CommentList>
</template>

<script>
import CommentList from '@/components/CommentListNew'

export default {
 name: 'CommentListContainer',

 components: {
 CommentList
 },

 computed: {
 comments () {
  return this.$store.state.comments
 }
 },

 methods: {
 fetchComments () {
  return this.$store.dispatch('fetchComments')
 }
 }
}
</script>

使用 @xunlei/vuex-connector 實(shí)現(xiàn)容器組件

上面演示的容器組件的代碼非常簡(jiǎn)單,實(shí)際上如果直接投入生產(chǎn)環(huán)境,會(huì)產(chǎn)生一些問(wèn)題。

手動(dòng)實(shí)現(xiàn)容器組件存在的不足

代碼比較繁瑣

在上面的例子中,每次傳遞一個(gè) state 都要定義一個(gè) computed,每傳遞一個(gè) mutation 或者 action 都需要定一個(gè)方法,而且還要注意這個(gè)方法的參數(shù)要透?jìng)鬟^(guò)去,同時(shí)還要處理返回值,比如異步的 action 需要返回 promise 的時(shí)候,定義的這個(gè) method 也得把 action 的返回值返回出去。

無(wú)法透?jìng)髌渌?props 給展示組件

比如展示組件新增了一個(gè) prop 叫做 type,可以傳遞一個(gè)評(píng)論的類型,用來(lái)區(qū)分是熱門還是最新,如果用上面的容器實(shí)現(xiàn)方式,首先需要在容器組件這層新增一個(gè) prop 叫做 type 接受外部傳來(lái)的參數(shù),然后在展示組件內(nèi)部同樣定義一個(gè) 叫做 type 的 prop,然后才能傳遞下去。

需要透?jìng)鞯?prop 必須定義兩遍,增加了維護(hù)的成本。

<CommentListContainer type="熱門"></CommentListContainer>
<CommentList
 :fetch="fetchComments"
 :comments="comments"
 :type="type"
 ></CommentList>

容器組件無(wú)法統(tǒng)一進(jìn)行優(yōu)化

每一個(gè)手動(dòng)實(shí)現(xiàn)的容器組件實(shí)質(zhì)上代碼邏輯非常近似,但是沒(méi)有經(jīng)過(guò)同一層封裝,如果目前實(shí)現(xiàn)的容器組件存在一些性能優(yōu)化的地方,需要每個(gè)容器組件都進(jìn)行統(tǒng)一的修改。

無(wú)法控制展示組件不去獲取 store

因?yàn)槿萜鹘M件是通過(guò) this.$store 獲取 store 的,展示組件內(nèi)部實(shí)質(zhì)上也可以直接跟 store 通信,如果沒(méi)有約束,很難統(tǒng)一要求展示組件不得直接和 store 通信。

使用 @xunlei/vuex-connector

@xunlei/vuex-connector 借鑒了 react redux 的 connect 方法,在 vuex 基礎(chǔ)上進(jìn)行的開(kāi)發(fā)。

有以下幾個(gè)特點(diǎn):

代碼非常簡(jiǎn)潔

下面是上面例子中手動(dòng)實(shí)現(xiàn)的容器組件的改造版本:

comonents/ConnectCommentListContainer.vue

<script>
import CommentListNew from '@/components/CommentListNew'
import { connector } from '@/store'

export default connector.connect({
 mapStateToProps: {
  comments: (state) => state.comments
 },
 mapActionToProps: {
  fetch: 'fetchComments'
 }
})(CommentListNew)
</script>


通過(guò) connector 的 connnect 方法,傳入要映射的配置,支持 mapStateToProps, mapGettersToProps, mapDispatchToProps, mapCommitToProps 這四種,每一種都是只要配置一個(gè)簡(jiǎn)單的 map 函數(shù),或者字符串即可。

然后在返回的函數(shù)中傳入要連接的展示組件,是不是非常的簡(jiǎn)潔,同時(shí)借鑒了 redux 優(yōu)雅的函數(shù)式風(fēng)格。

問(wèn)題來(lái)了,connector 是什么?

connector 實(shí)際上是一個(gè)能獲取到 store 實(shí)例的連接器,可以在初始化 vuex store 的時(shí)候進(jìn)行初始化。

import Vue from 'vue';
import Vuex from 'vuex';
import VuexConnector from '@xunlei/vuex-connector';
Vue.use(Vuex);
const store = new Vuex.Store({
 // your store
});
export const connector = new VuexConnector(store);
export default store;

一個(gè) Vue 程序?qū)嶋H上只需要初始化一次即可。

支持透?jìng)髌渌?props 給展示組件

VuexConnector 實(shí)現(xiàn)的時(shí)候采用了函數(shù)式組件( functional: true )

函數(shù)式組件是無(wú)狀態(tài) (沒(méi)有響應(yīng)式數(shù)據(jù)),無(wú)實(shí)例 (沒(méi)有 this 上下文)。

在作為包裝組件時(shí)函數(shù)式組件非常有用,比如,當(dāng)你需要做這些時(shí):

程序化地在多個(gè)組件中選擇一個(gè)

在將 children, props, data 傳遞給子組件之前操作它們。

另外,函數(shù)式組件只是一個(gè)函數(shù),所以渲染開(kāi)銷也低很多。然而,對(duì)持久化實(shí)例的缺乏也意味著函數(shù)式組件不會(huì)出現(xiàn)在 Vue devtools 的組件樹(shù)里。

因此需要透?jìng)鞯?props 可以直接透?jìng)?,需要通過(guò) map 方式從 store 里進(jìn)行獲取的 props 直接會(huì)根據(jù)配置生成。

統(tǒng)一封裝方便后續(xù)統(tǒng)一優(yōu)化

VuexConnector.connect 方法將本來(lái)需要重復(fù)做的事情進(jìn)行了抽象,也帶來(lái)了后期進(jìn)行統(tǒng)一優(yōu)化和升級(jí)的便利。

可以控制展示組件無(wú)法直接與 store 通信

VuexConnector 不依賴 this.$store,而是依賴初始化傳入的 store 實(shí)例,容器組件可以用 connect 將展示組件與 store 進(jìn)行連接。

由于不依賴 this.$store,我們?cè)诔绦蛉肟?new Vue 的時(shí)候,就不需要傳入 store 實(shí)例了。

比如,之前我們是通過(guò)下面的方式進(jìn)行初始化:

import Vue from 'vue';
import App from './App';
import store from './store';
new Vue({
 el: '#app',
 components: {App},
 template: '<App/>',
 store,
});

使用了 VuexConnector 之后,在最初 new Vue 的時(shí)候就不需要也最好不要傳遞 store 了,這樣就避免了 this.$store 泛濫導(dǎo)致代碼耦合的問(wèn)題。

引入容器組件/展示組件模式帶來(lái)的好處

可復(fù)用性

容器組件/展示組件的劃分,采用了單一職責(zé)原則的設(shè)計(jì)模式,容器組件專門負(fù)責(zé)和 store 通信,展示組件只負(fù)責(zé)展示,解除了組件的耦合,可以帶來(lái)更好的可復(fù)用性。

健壯性

由于展示組件和容器組件是通過(guò) prop 這種接口來(lái)連接,可以利用 props 的校驗(yàn)來(lái)增強(qiáng)代碼的可靠性,混合的組件就沒(méi)有這種好處。

另外對(duì) props 的校驗(yàn)可以采取一下幾種方式:

Vue 組件 props 驗(yàn)證

可以驗(yàn)證 props 的類型,默認(rèn)可以校驗(yàn)是否是以下類型:

  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array
  • Symbol

如果你的 props 是類的一個(gè)實(shí)例,type 也可以是一個(gè)自定義構(gòu)造器函數(shù),使用 instanceof 檢測(cè)。

如果還是不滿足需求,可以自定義驗(yàn)證函數(shù):

// 自定義驗(yàn)證函數(shù)
propF: {
 validator: function (value) {
  return value > 10
 }
}

TypeScript 類型系統(tǒng)

Vue 組件 props 驗(yàn)證對(duì)于對(duì)象或者其他復(fù)雜的類型校驗(yàn)還是不太友好,所以很多人也推薦大家的 props 盡量采取簡(jiǎn)單類型,不過(guò)如果你有在用 TypeScript 開(kāi)發(fā) Vue 應(yīng)用,可以利用 TypeScript 靜態(tài)類型檢查來(lái)聲明你的 props 。

@Component
export default class Hello extends Vue {
 @Prop
 info: IHelloInfo; // 這里可以用你自定義的 interface
}

可測(cè)試性

由于組件做的事情更少了,使得測(cè)試也會(huì)變得容易。

容器組件不用關(guān)心 UI 的展示,只關(guān)心數(shù)據(jù)和更新。

展示組件只是呈現(xiàn)傳入的 props ,寫單元測(cè)試的時(shí)候也非常容易 mock 數(shù)據(jù)層。

引入容器組件/展示組件模式帶來(lái)的限制

學(xué)習(xí)和開(kāi)發(fā)成本

因?yàn)槿萜鹘M件/展示組件的拆分,初期會(huì)增加一些學(xué)習(xí)成本,不過(guò)當(dāng)你看完這篇文章,基本上也就入門了。

在開(kāi)發(fā)的時(shí)候,由于需要封裝一個(gè)容器,包裝一些數(shù)據(jù)和接口給展示組件,會(huì)增加一些工作量, @xunlei/vuex-connector 通過(guò)配置的方式可以減輕不少你的工作量。

另外,在展示組件內(nèi)對(duì) props 的聲明也會(huì)帶來(lái)少量的工作。

總體來(lái)說(shuō),引入容器組件/展示組件模式投入產(chǎn)出比還是比較值得的。

總結(jié)

以上所述是小編給大家介紹的React為 Vue 引入容器組件和展示組件的教程詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • React?Streaming?SSR原理示例深入解析

    React?Streaming?SSR原理示例深入解析

    這篇文章主要為大家介紹了React?Streaming?SSR原理示例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 模塊化react-router配置方法詳解

    模塊化react-router配置方法詳解

    這篇文章主要介紹了模塊化react-router配置方法詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-06-06
  • React?實(shí)現(xiàn)爺孫組件間相互通信

    React?實(shí)現(xiàn)爺孫組件間相互通信

    這篇文章主要介紹了React實(shí)現(xiàn)爺孫組件間相互通信,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-08-08
  • React全家桶環(huán)境搭建過(guò)程詳解

    React全家桶環(huán)境搭建過(guò)程詳解

    本篇文章主要介紹了React全家桶環(huán)境搭建過(guò)程詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • 一文帶你搞懂React中的useReducer

    一文帶你搞懂React中的useReducer

    useReducer 是除useState之外另一個(gè)與狀態(tài)管理相關(guān)的 hook,這篇文章主要為大家介紹了useReducer應(yīng)用的相關(guān)知識(shí),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • React Native時(shí)間轉(zhuǎn)換格式工具類分享

    React Native時(shí)間轉(zhuǎn)換格式工具類分享

    這篇文章主要為大家分享了React Native時(shí)間轉(zhuǎn)換格式工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • React三大屬性之props的使用詳解

    React三大屬性之props的使用詳解

    這篇文章主要介紹了React三大屬性之props的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-04-04
  • 解決React報(bào)錯(cuò)Functions are not valid as a React child

    解決React報(bào)錯(cuò)Functions are not valid as 

    這篇文章主要為大家介紹了React報(bào)錯(cuò)Functions are not valid as a React child解決詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • React學(xué)習(xí)之JSX與react事件實(shí)例分析

    React學(xué)習(xí)之JSX與react事件實(shí)例分析

    這篇文章主要介紹了React學(xué)習(xí)之JSX與react事件,結(jié)合實(shí)例形式分析了React中JSX表達(dá)式、屬性、嵌套與react事件相關(guān)使用技巧,需要的朋友可以參考下
    2020-01-01
  • React Hook 監(jiān)聽(tīng)localStorage更新問(wèn)題

    React Hook 監(jiān)聽(tīng)localStorage更新問(wèn)題

    這篇文章主要介紹了React Hook 監(jiān)聽(tīng)localStorage更新問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評(píng)論