中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React項目中hook怎么實現展示對話框功能

發布時間:2022-05-13 14:06:25 來源:億速云 閱讀:215 作者:iii 欄目:開發技術

這篇文章主要介紹“React項目中hook怎么實現展示對話框功能”,在日常操作中,相信很多人在React項目中hook怎么實現展示對話框功能問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”React項目中hook怎么實現展示對話框功能”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

React中使用對話框并不容易,主要因為:

  1. 對話框需要在父組件中聲明,才能在子組件中控制其是否顯示

  2. 給對話框傳遞參數只能由props傳入,這意味著所有狀態管理都必須在更高階的組件中。而實際上這個對話框的參數只在子組件中才會維護。這時就需要我們使用自定義事件將參數傳回

這些問題的本質就是:如何用一個統一的方式去管理對話框,從而讓對話框相關的業務邏輯更加模塊化,以及和其他業務邏輯進行解耦。

下面的方式只是經驗總結,并不是唯一或者最佳實現:

思路:使用全局狀態管理所有對話框

對話框本質上是獨立于其他界面的一個窗口,用于完成一個獨立的功能。

所以,定義一個對話框,定位等價于定義一個具有唯一URL路徑的頁面。只是前者由彈出層實現,后者是頁面的切換。

對話框UI彈出過程和頁面URL的切換非常類似,那么我們就可以給每一個對話框定義一個全局唯一的ID,然后通過這個ID去顯示或者隱藏一個對話框,并且給它傳遞參數。

嘗試設計一個API去做對話框的全局管理

假設我們實現的對話框為NiceModal,那么我們的目標是如下去使用:

const UserInfoModal = NiceModal.create(
    'user-info-modal',
    RealUserInfoModal
)
 
// 創建一個useNiceModal 這樣的hook去獲取某個id的對話框的操作對象
const modal = useNiceModal('user-info-modal')
 
// 通過 modal.show 顯示一個對話框,并能夠給它傳遞參數
modal.show(args)
modal.hide()

可以看到,如果有這樣的API,那么無論在哪個層級的組件,只要知道某個Modal的ID,那么就都可以統一使用這些對話框,而不再需要考慮該在哪個層級的組件去定義了。

實現:創建NiceModal組件和相關API

創建一個處理所有對話框的action creator 和 reducer

function showModal(modalId, args) {
    return {
        type: "nice-modal/show",
        payload: {
            modalId,
            args
        }
    }
}
 
function hideModal(modalId, force) {
    return {
        type: "nice-modal/hide",
        payload: {
            modalId,
            force
        }
    }
}
const modalReducer = (state = { hiding: {} }, action) {
    switch (action.type) {
        case "nice-modal/show":
            const {modalId, args} = action.payload
            return {
                ...state,
                // 如果存在 modalId 對應的狀態(即args),就顯示這個對話框
                // 只要有參數就認為對話框應該顯示,如果沒有傳遞args,在reducer中使用默認值true
                [modalId]: args || true,
                // 定義一個hiding 狀態, 用于處理對話框關閉動畫
                hiding: {
                    ...state.hiding,
                    [modalId]: false,
                }
            }
        case "nice-modal/hide":
            const { modalId, force: boolean } = action.payload
            // 只有force時才真正移除對話框,否則就是隱藏中hiding
            return action.payload.force 
                ? {
                    ...state,
                    [modalId]: false,
                    hiding: { [modalId]: false }
                  }
                : { ...state, hiding: { [modalId]: true } }
            default:
                return state
    }
}

這段代碼的主要思路就是通過Redux的store去存儲每個對話框狀態和參數。在這里設計了兩個action,分別顯示和隱藏對話框。

特別注意的是,這里加入了hiding這樣的一個狀態,用來處理對話框關閉過程動畫。

根據使用順序,首先實現 createNiceModal,

使用容器模式,在對話框不可見時直接返回null,從而不渲染任何內容,

確保即使頁面上定義了100個對話框,也不會影響性能。

createNiceModal = (modalId, Comp) => {
    return (props) => {
        const { visible, args } = useNiceModal(modalId)
        if (!visible) return null
        return <Comp {...args} {...props} />
    }
}
 
// 使用
const MyModal = createNiceModal('my-modal', () => {
    return (
        <NiceModal id="my-modal" title="Nice modal">
            Hello NiceModal
        </NiceModal>
    )
})

實現useNiceModal,根據id,封裝一些邏輯。

讓Redux的action使用起來更方便,在其內部封裝對store的操作,從而實現對話框狀態管理的邏輯重用。

const modalCallbacks = {}
 
const useNiceModal = (modalId) => {
    const dispatch = useDispatch()
 
    // 封裝Redux action 用于顯示對話框
    const show = useCallback(
        (args) => {
            dispatch(showModal(modalId, args))
        },
        [dispatch, modalId]
    )
    
    // 封裝Redux action 用于隱藏對話框 (force: boolean)
    const hide = useCallback(
        (force) => {
            dispatch(hideModal(modalId, force))
        },
        [dispatch, modalId]
    )
 
    const args = useSelector((s) => s[modalId])
    const hiding = useSelector((s) => s.hiding[modalId])
 
    // 只要有參數就認為對話框應該顯示,如果沒有傳遞args,在reducer中使用默認值true
    return { args, hiding, visible: !!args, show, hide }
}

這樣,我們就實現了一個NiceModal這樣的全局對話管理框架。

這樣使用:

import { Button } from 'antd'
import NiceModal, {
    createNiceModal,
    useNiceModal
} from "./NiceModal"
 
const MyModal = createNiceModal("my-modal", () => {
    return (
        <NiceModal id="my-modal" title="Nice Modal">
            Hello World
        </NiceModal>
    )
})
 
function MyModalExample() {
    const modal = useNiceModal("my-modal")
    return (
        <>
            <Button type="primary" onClick={() => modal.show()}>
                Show my modal
            </Button>
            <MyModal />
        </>
    )
}

處理對話框的返回值

如果說對話框和頁面這兩種UI模式基本上是一致的,都是獨立窗口完成獨立邏輯。但是在用戶交互上,有一定的差別:

  • 對話框可能需要返回值給調用者

  • 而頁面切換一般不會關心頁面執行的結果是什么

基于上面的NiceModal實現邏輯,現在考慮如何讓調用者獲得返回值。

我們可以把用戶在對話框中的操作看成一個異步操作邏輯,那么用戶在完成對話框中內容的操作后,就認為異步操作邏輯完成了。因此我們可以利用Promise來完成這樣的邏輯。

那么,我們要實現的API如下:

const modal = useNiceModal('my-modal')
// 實現一個 promise API 來處理返回值
modal.show(args).then(res => {})

事實上,要實現這樣一個機制并不困難,就是在 useNiceModal 這個 Hook 的實現中提供一個 modal.resolve 這樣的方法,能夠去 resolve modal.show 返回的 Promise。

代碼的核心思路就是將show 和 resolve 兩個函數通過 Promise 聯系起來。因此兩個函數調用位置不一樣,所以我們使用一個局部的臨時變量,來存放resolve回調函數。

// 使用一個 object 緩存 promise 的 resolve 回調函數
const modalCallbacks = {};
export const useNiceModal = (modalId) => {
  const dispatch = useDispatch();
  const show = useCallback(
    (args) => {
      return new Promise((resolve) => {
        // 顯示對話框時,返回 promise 并且將 resolve 方法臨時存起來
        modalCallbacks[modalId] = resolve;
        dispatch(showModal(modalId, args));
      });
    },
    [dispatch, modalId],
  );
  const resolve = useCallback(
    (args) => {
      if (modalCallbacks[modalId]) {
        // 如果存在 resolve 回調函數,那么就調用
        modalCallbacks[modalId](args);
        // 確保只能 resolve 一次
        delete modalCallbacks[modalId];
      }
    },
    [modalId],
  );
  
  // 其它邏輯...
 
  // 將 resolve 也作為返回值的一部分
  return { show, hide, resolve, visible, hiding };
};

到此,關于“React項目中hook怎么實現展示對話框功能”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

乌兰浩特市| 汝城县| 纳雍县| 惠东县| 漳平市| 分宜县| 松溪县| 满洲里市| 定襄县| 马边| 迭部县| 公安县| 永泰县| 故城县| 西峡县| 昆明市| 丹东市| 罗定市| 吉隆县| 多伦县| 钦州市| 汉中市| 平遥县| 光山县| 安陆市| 龙川县| 西充县| 泸水县| 西盟| 香河县| 阿克| 页游| 林西县| 恭城| 新营市| 勐海县| 河北省| 工布江达县| 聂拉木县| 天峨县| 平远县|