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

如何在React項(xiàng)目中優(yōu)雅的使用對話框

 更新時(shí)間:2022年05月12日 11:34:55   作者:拜小白  
在項(xiàng)目中,對話框和確認(rèn)框是使用頻率很高的組件,下面這篇文章主要給大家介紹了關(guān)于如何在React項(xiàng)目中優(yōu)雅的使用對話框的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

背景

對話框在前端開發(fā)應(yīng)用中,是一種非常常用的界面模式。對話框作為一個(gè)獨(dú)立的窗口,常常被用于信息的展示,輸入信息,亦或者更多其他功能。但是項(xiàng)目的使用過程中,在某些場景下對話框用起來會有一些麻煩。例如:

場景一

如果想要在多個(gè)子組件(A、B)中控制一個(gè)對話框(C)的顯示影藏,這個(gè)對話框必須在共有的父組件(MySalesOrders)中進(jìn)行聲明。

場景二

如果需要給對話框(C)傳遞參數(shù),一般情況我們會使用 props 傳入,意味著狀態(tài)的管理必須也是子組件(A、B)的父組件或者更高一級進(jìn)行管理和維護(hù),但是其實(shí)這些狀態(tài)可能只需要在子組件 A 或者 B 中維護(hù)。這種情況下,我們就需要自定義事件,將狀態(tài)進(jìn)行回傳,比較麻煩。

const MySalesOrders: React.FC = () => {
  const [visible, setVisible] = React.useState(false);
  ...
  return (
  	<>
    	<A modalVisible={setVisible}/>      
			<B modalVisible={setVisible}/>
    	{
        visible ? (
          <C
            ...
          />
        ) : null
      }
    </>
  );
}

const A: React.FC = (props) => {
  ...
  return (
  	<>
    	<Button 
        onClick={() => {
            props.modalVisible(...)
        }} 
      />
    </>
  );
}

const B: React.FC = (props) => {
  ...
  return (
  	<>
    	<Button 
        onClick={() => {
            props.modalVisible(...)
        }} 
      />
    </>
  );
}

場景三

一個(gè)展示的對話框,對話框在不同的模塊可能只是提示文案不一樣,需要在不同的地方多次導(dǎo)入定義。例如系統(tǒng)中常用的提示成功、提示失敗的對話框。

我們通常會定義一個(gè)通用的組件,在父組件中定義,然后使用時(shí)喚起,但是如果我們需要在不同的頁面使用,我們就需要在不同的頁面組件中使用引入定義。

這些場景都是在我在實(shí)際開發(fā)中都會用到的,并且我們開發(fā)中也是基本都是這樣做的,雖然可以正常的使用。但是隱藏了幾個(gè)小的問題。

問題一:難以擴(kuò)展

如果和 MySalesOrders 同級的組件也要訪問這個(gè)對話框(C)?又或者, MySalesOrders 下面的某個(gè)深層級的孫子組件也要能對話框(C)?前者意味著代碼需要重構(gòu),繼續(xù)提升狀態(tài)到 MySalesOrders 組件的父組件;后者意味著業(yè)務(wù)邏輯處理更復(fù)雜,需要通過層層的自定義事件回調(diào)來完成。

問題二:維護(hù)問題

同一個(gè)組件,需要在不同的地方多次的導(dǎo)入定義。在系統(tǒng)中增加了大量重復(fù)的代碼。代碼很快就會變得臃腫,且難以理解和維護(hù)。

問題的本質(zhì)

對上訴問題來說,本質(zhì)在于:在我們?nèi)粘5捻?xiàng)目中應(yīng)該哪里定義去對話框?又該如何和對話框進(jìn)行數(shù)據(jù)交互?

對話框的本質(zhì)

換一個(gè)角度再來看對話框,其實(shí)對話框本身是一個(gè)一對一或者一對多的 UI 模式。站在對話框的角度上,對話框本質(zhì)上是一個(gè)「獨(dú)立于其他界面的一個(gè)窗口,用于完成一個(gè)獨(dú)立的功能」。

如果從視覺角度出發(fā),你會發(fā)現(xiàn)在使用對話框的時(shí)候,你完全不會關(guān)心它是從哪個(gè)具體的組件中彈出來的,而只會關(guān)心對框本身的內(nèi)容。比如說,成功和失敗的對話框,它可能在 A 組件點(diǎn)出來的,也可能是 B 組件點(diǎn)出來的,亦或者其他組件點(diǎn)出來的。對話框的本質(zhì)就決定了它是獨(dú)立于各個(gè)組件之外的,

雖然很可能在一開始這個(gè)對話框的實(shí)現(xiàn)和某個(gè)組件非常高的相關(guān)度,但是在整個(gè)應(yīng)用的不斷開發(fā)和演進(jìn)過程中,是很可能不斷變化的。所以,在定義一個(gè)對話框的時(shí)候,其定位基本會等價(jià)于定義一個(gè)具有唯一 URL 路徑的頁面。只是前者由彈出層實(shí)現(xiàn),后者是頁面的切換。對于頁面級別的 UI 切換,我們很容易理解,就是定義全局的路由嘛。那么同樣的,如果我們以同樣的方式去思考對話框,其實(shí)就是將對話框全局化,然后通過一個(gè)全局的機(jī)制來管理這些對話框。這個(gè)過程和頁面 URL 的切換非常類似,那么我們就可以給每一個(gè)對話框定義一個(gè)全局唯一的 ID,然后通過這個(gè) ID 去顯示或者隱藏一個(gè)對話框,并且給它傳遞參數(shù)。

基于這樣的設(shè)想,我們可以嘗試使用全局的狀態(tài)管理來設(shè)置我們的對話框。

全局的狀態(tài)管理的對話框

整體的架構(gòu)

具體實(shí)現(xiàn)

代碼實(shí)現(xiàn)以 React 項(xiàng)目為主。

Redux - reducer 存儲

利用 Redux 的 store 去存儲每個(gè)對話框狀態(tài)和參數(shù)。

export default (state = {
  hiding: {}
}, action: AnyAction) => {
  switch (action.type) {
    case CONSTANTS.modalShow:
      return {
        ...state,
        [action.payload.modalId]: action.payload.args || true,
        hiding: {
          ...state.hiding,
          [action.payload.modalId]: false,
        },
      };
    case CONSTANTS.modalHide:
      return action.payload.force
        ? {
          ...state,
          [action.payload.modalId]: false,
          hiding: { [action.payload.modalId]: false },
        }
        : { ...state, hiding: { [action.payload.modalId]: true } };
    default:
      return state;
  }
};

Redux - action 處理對話框的顯示隱藏

兩個(gè) action ,分別用來顯示和隱藏對話框。

export function showModal(modalId: string, args: any) {
  return {
    type: CONSTANTS.modalShow,
    payload: {
      modalId,
      args,
    },
  };
}

export function hideModal(modalId: string, force: any) {
  return {
    type: CONSTANTS.modalHide,
    payload: {
      modalId,
      force,
    },
  };
}

Hook - useCommonModal

定義一個(gè) Hook,在其內(nèi)部封裝對 Store 的操作,從而實(shí)現(xiàn)對話框狀態(tài)管理的邏輯重用。

export const useCommonModal = (modalId: string) => {
  const dispatch = useDispatch();

  const show = React.useCallback(
    (args?: any) => new Promise((resolve) => {
      commonmModalCallbacks[modalId] = resolve;
      dispatch(showModal(modalId, { ...args }));
    }),
    [dispatch, modalId],
  );

  const resolve = React.useCallback(
    (args?: any) => {
      if (commonmModalCallbacks[modalId]) {
        commonmModalCallbacks[modalId]({ ...args });
        delete commonmModalCallbacks[modalId];
      }
    },
    [modalId],
  );

  const hide = React.useCallback(
    (force?: any) => {
      dispatch(hideModal(modalId, force));
      delete commonmModalCallbacks[modalId];
    },
    [dispatch, modalId],
  );

  const args = useSelector((s: any) => s?.modalReducer?.[modalId]);
  const hiding = useSelector((s: any) => s?.modalReducer?.hiding?.[modalId]);

  return React.useMemo(
    () => ({ args, hiding, visible: !!args, show, hide, resolve }),
    [args, hide, show, resolve, hiding],
  );
};

創(chuàng)建對話框-容器模塊

創(chuàng)建對話框時(shí),使用容器模式,它會在對話框不可見時(shí)直接返回 null,從而不渲染任何內(nèi)容;并且確保即使頁面上定義了 100 個(gè)對話框,也不會影響頁面性能。

export const createCommonModal = (modalId: string, Comp: any) => (props: any) => {
  const { visible, args } = useCommonModal(modalId);
  if (!visible) return null;
  return (
    <Comp
      {...args}
      {...props}
    />
  );
};

對話框返回值處理

往往在實(shí)際的使用中,可能在打開對話框進(jìn)行操作之后需要將返回值返給調(diào)用者,有兩種方式可以供參考:

  • callback:在傳入?yún)?shù)時(shí),傳入一個(gè)回調(diào)函數(shù),在進(jìn)行操作完成之后,進(jìn)行回調(diào)函數(shù)的調(diào)用。
const show = React.useCallback(
    (args?: any) => new Promise((resolve) => {
      commonmModalCallbacks[modalId] = resolve;
      //  args 中攜帶上 callback
      dispatch(showModal(modalId, { ...args }));
    }),
    [dispatch, modalId],
  );

// 調(diào)用
const modal = useCommonModal('modal-id');
modal.show({
  callback() {}
});

// 對話框解析參數(shù)
const modalReducer = useSelector((state: any) => state.modalReducer);
const { callback } = modalReducer?.['modal-id'];

//對話框觸發(fā)
callback();
  • 將 show 和 resolve 兩個(gè)函數(shù)通過 Promise 聯(lián)系起來。通過臨時(shí)變量,來存放 resolve 回調(diào)函數(shù),在對話框中去調(diào)用 modal.resolve 來進(jìn)行值的返回。
  const resolve = React.useCallback(
    (args?: any) => {
      if (commonmModalCallbacks[modalId]) {
        commonmModalCallbacks[modalId]({ ...args });
        delete commonmModalCallbacks[modalId];
      }
    },
    [modalId],
  );

// 調(diào)用
const modal = useCommonModal('modal-id');
modal.show(args).then(result => {});

// 對話框觸發(fā)
const modal = useCommonModal('modal-id');
modal.resolve({ ... });

運(yùn)行實(shí)例

global-modal

總結(jié)

分享了一種使用對話框的實(shí)踐方式:利用全局狀態(tài)來管理對話框。解決上文提到的在使用對話框遇到的問題。其核心思路在于從 UI 模式的角度出發(fā),把對話框也可當(dāng)做一個(gè)單獨(dú)的頁面,對話框的展示可用全局狀態(tài)來管理,因此,用全局的方式去管理對話框就是一種非常合理的方式。從而讓組件的語義更加清楚,代碼更容易理解和維護(hù)。

并且對于對話框定義位置,其實(shí)可以分場景來甄別。系統(tǒng)某一個(gè)模塊下的業(yè)務(wù)對話框,就只需要定義在這個(gè)業(yè)務(wù)模塊的根組件下就可以了。對于全局都可能使用的公共對話框,那就可以定義在整個(gè)系統(tǒng)的根組件,系統(tǒng)任何地方都可以使用。定義的位置決定了對話框組件輻射的廣度。

當(dāng)然這種全局的狀態(tài)管理對話框的方式,只是對原有的對話框操作做了一個(gè)增強(qiáng),解決了一些場景下的問題,但是對于一些簡單的對話框我們還是可以用常用的方式去管理和控制。兩者是可以并存的,大家可以根據(jù)場景來定義使用哪一種方式。

參考

到此這篇關(guān)于如何在React項(xiàng)目中優(yōu)雅的使用對話框的文章就介紹到這了,更多相關(guān)React使用對話框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • react native實(shí)現(xiàn)監(jiān)控手勢上下拉動(dòng)效果

    react native實(shí)現(xiàn)監(jiān)控手勢上下拉動(dòng)效果

    這篇文章主要為大家詳細(xì)介紹了react native實(shí)現(xiàn)監(jiān)控手勢上下拉動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • React反向代理及樣式獨(dú)立詳解

    React反向代理及樣式獨(dú)立詳解

    這篇文章主要介紹了React反向代理及樣式獨(dú)立詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-08-08
  • ReactNative 之FlatList使用及踩坑封裝總結(jié)

    ReactNative 之FlatList使用及踩坑封裝總結(jié)

    本篇文章主要介紹了ReactNative 之FlatList使用及踩坑封裝總結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • 詳解Stack?Navigator中使用自定義的Render?Callback

    詳解Stack?Navigator中使用自定義的Render?Callback

    這篇文章主要為大家介紹了Stack?Navigator中使用自定義的Render?Callback使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • React Native基礎(chǔ)入門之調(diào)試React Native應(yīng)用的一小步

    React Native基礎(chǔ)入門之調(diào)試React Native應(yīng)用的一小步

    這篇文章主要給大家介紹了關(guān)于React Native基礎(chǔ)入門之調(diào)試React Native應(yīng)用的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • React狀態(tài)管理Redux的使用介紹詳解

    React狀態(tài)管理Redux的使用介紹詳解

    redux是redux官方react綁定庫,能夠使react組件從redux store中讀取數(shù)據(jù),并且向store分發(fā)actions以此來更新數(shù)據(jù),這篇文章主要介紹了react-redux的設(shè)置,需要的朋友可以參考下
    2022-09-09
  • 淺談React雙向數(shù)據(jù)綁定原理

    淺談React雙向數(shù)據(jù)綁定原理

    在 React中是不存在雙向數(shù)據(jù)綁定的機(jī)制的,需要我們自己對其進(jìn)行實(shí)現(xiàn)。本文主要介紹一下React雙向數(shù)據(jù)綁定,感興趣的可以了解一下
    2021-11-11
  • React通過hook實(shí)現(xiàn)封裝表格常用功能

    React通過hook實(shí)現(xiàn)封裝表格常用功能

    這篇文章主要為大家詳細(xì)介紹了React通過hook封裝表格常用功能的使用,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下
    2023-12-12
  • 詳解React之key的使用和實(shí)踐

    詳解React之key的使用和實(shí)踐

    這篇文章主要介紹了詳解React之key的使用和實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • react.js 父子組件數(shù)據(jù)綁定實(shí)時(shí)通訊的示例代碼

    react.js 父子組件數(shù)據(jù)綁定實(shí)時(shí)通訊的示例代碼

    本篇文章主要介紹了react.js 父子組件數(shù)據(jù)綁定實(shí)時(shí)通訊的示例代碼,
    2017-09-09

最新評論

渝北区| 宜城市| 蓬溪县| 宁南县| 镇巴县| 潼关县| 德庆县| 大理市| 象山县| 无极县| 云阳县| 恭城| 双城市| 韩城市| 阜南县| 绥阳县| 邹城市| 滁州市| 通城县| 黔南| 卓资县| 泗水县| 齐齐哈尔市| 河北区| 湾仔区| 乐亭县| 大洼县| 屏东市| 会宁县| 尼勒克县| 海伦市| 孝感市| 襄城县| 雅安市| 抚州市| 霞浦县| 西藏| 博乐市| 越西县| 阜新市| 蕉岭县|