[譯]為什麼 VueX 是前端與 API 之間的完美介面

趙小生發表於2018-06-04

前端 Web 開發複雜性的增加促進了前後端專業化和前後端分離。

這種專業化和複雜性的增加有許多好處 —— 網路使用者體驗的質量呈指數級增長,同時,更多的人將通過多種裝置連線彼此,這是史無前例的。

但是,它也帶來了一些挑戰。

挑戰:前端和 API 之間的整合

前端和 API 之間介面的摩擦、挑戰和複雜性是一個常見的問題。

理想狀態下,後端和前端將通過緊密的通訊和諧共處,後端提供的資料將完全匹配前端所需的資料。

實際上,應用程式的這兩個部分通常由完全不同的團隊甚至不同的公司開發。在設計部門和前端部門之外建立一個專門的團隊並不罕見,而你自己的團隊正在進行後端開發。

典型解決方案

結果是一個通常看起來如下所示的流程:

  1. 使用偽造的 'stubbed' (“存根”)資料構建 UI,也可以直接嵌入模板和程式碼中,或者通過一個工具包載入。
  2. 當 API 準備就緒時,迅速使用真實的 API 呼叫和資料替換每一處整合點。

這種方法存在的問題是雙重的:

  1. 資料整合通常分散在整個應用程式中,需要跟蹤並重新編寫大量程式碼。
  2. 即使資料是相對獨立的,前端期望與API最終提供的內容之間往往存在不匹配。前端期望的資料與 API 最終返回的資料往往存在不匹配。

更好的解決方案:VueX

如果您使用 Vue.js 開發您的前端,那麼一個更好的解決此問題的方法信手拈來。

深度整合到 Vue 中的 VueX 庫提供了一種完美的解決方案,可以為您的資料建立一個乾淨的隔離的介面,從而使存根資料(stubbed data)和實際 API 之間的轉換變得輕而易舉。

什麼是 VueX

VueX 是受 Flux,Redux 和 Elm 架構的啟發下開發的狀態管理庫,並且專門設計並調整為與 Vue.js 良好整合並利用 Vue 的響應式特性。

所有這些庫都旨在解決一個簡單問題:當許多元件共享狀態時,尤其是兄弟元件或在不同檢視下的元件時,管理該狀態的分發和更新具有挑戰性。

像 VueX 這樣的庫可以通過結構化和可維護的方式管理元件間的共享狀態,方法是建立一個全域性狀態樹,可以按結構化方式訪問和更新每個元件。

VueX 是如何工作的

VueX 將狀態管理分為 3 個關鍵部分:statemutationsactions。當你例項化一個 VueX store時,你可以定義這三個物件:

const store = new Vuex.Store({
    state: {
    ...
    },
    mutations: {
    ...
    },
    actions: {
    ...
    }
})
複製程式碼

State

State 代表實際資料本身。 這只是一個包含資料樹的 JavaScript 物件。在 VueX 中,您可以擁有單個全域性狀態樹或按模組組織(例如使用者狀態樹,產品狀態樹等)

例如,我們可以使用這個狀態樹來跟蹤我們當前的使用者,如果使用者沒有登入,則從 null 開始:

state: {
    currentUser: null
}
複製程式碼

Mutations

Mutations 是我們改變狀態樹的機制。狀態的所有變化必須通過 mutations 來實現,這使得 VueX 能夠以可預測的方式管理狀態。

一個關於 mutation 的例子也許是這樣:

mutations: {
    setCurrentUser(currentState, user) {
    currentState.currentUser = user;
    }
}
複製程式碼

Mutations 是同步的,並直接修改狀態物件(比如,與 Redux 相比,有一個同等的概念稱為 reducer 並返回一個 new 物件)。

這種狀態物件的同步、直接變化與 Vue 的響應式概念完美匹配。VueX 狀態物件是響應式的,所以這些變化向外延伸到所有的依賴。

你可以通過 commit 函式來呼叫一個 mutation:

store.commit('setCurrentUser', user);
複製程式碼

Actions

Actions 是 VueX 的最後一塊,是意圖修改之間的中介。

Actions是非同步的,並且間接地通過commititting mutations 來修改 store。但是,由於它們是非同步的,因此它們可以做的遠不止這些。

非同步允許 actions 處理諸如 API 呼叫,使用者互動和整個 action 流程等事情。

一個簡單的例子,一個 action 可能會進行一次 API 呼叫並記錄結果:

actions: {
    login(context, credentials) {
    return myLoginApi.post(credentials).then((user) => {
        context.commit('setCurrentUser', user)
    })
    }
}
複製程式碼

Actions 可以返回 promises,允許檢視或其他程式碼分派 actions,等待它們完成並根據其結果做出響應。你應該使用 dispatch 來分派一個 action 。而不是使用 commit。例如,我們的呼叫程式碼可能如下所示:

store.dispatch('login', credentials).then(() => {
    // 重定向到登入區域
}).catch((error) => {
    // 顯示有關錯誤密碼的訊息
});
複製程式碼

為什麼說 VueX 操作是 API 的完美介面

如果您正在開發一個後端和前端同時進行的專案,或者您是一個 UI/前端團隊,您甚至可能在後端存在之前就構建使用者介面,那麼您可能會在開發前端時經常面臨這樣的問題,即需要將後端的部分資料擷取出來。

這種場景的常見做法是如同純靜態模板或內容一樣,在前端模板中使用合適的佔位符和文字。

從這一步驟開始,就是某種形式的固定寫法,由前端靜態載入資料並把它們放置到正確的位置。

這些都經常遇到同樣的挑戰:當後端終於可以使用的時候,需要進行大量的重構工作來獲取真實的資料。

即使(奇蹟般地)來自後端的資料結構與您的固定寫法相匹配,您仍然需要全方位排查以找到每個整合點。如果結構不同(讓我們面對它,通常情況下都會這樣),您不僅必須這樣做,而且必須弄清楚如何更改前端或建立轉換資料的抽象層。

進入 VueX Actions

VueX 的優點在於,actions 提供了一種完美的方式來對前端和後端進行隔離和抽象,並且以這種方式進行操作,以便從存根資料(stubbed data)更新到真正的後端是無縫而簡單的。

讓我們展開來說。以我們的登入功能作為例子。如果我們的登入 API 尚不存在,但我們仍然準備構建前端,我們可以像這樣實施我們的操作:

actions: {
    login(context, credentials) {
    const user = MY_STUBBED_USER;
    if(credentials.login === '[email protected]') {
        context.commit('setCurrentUser', user)
        return Promise.resolve();
    } else {
        return Promise.reject(new Error('invalid login'));
    }
    }
}
複製程式碼

現在,我們的前端可以通過測試資料實現一種登入方式,這種登入方式在將來也是以同樣的方式執行的,可以同時實現成功和失敗的登入請求。這種行為將立即發生,而不是通過 API 非同步實現,但通過返回 promises ,現在任何呼叫者都可以像對待真正的 API 呼叫一樣對待它。

當我們的 API 可用時,我們可以簡單地修改這個 action 以使用它,並且我們的程式碼庫中的其他所有內容都保持不變。

處理資料不匹配的問題

將我們的 API 呼叫與 VueX 隔離也為我們提供了一種簡潔優雅的方式來處理後端和前端之間的資料格式不匹配的問題。

繼續使用我們的登入示例,或許我們假設 API 將返回我們在登入時需要的所有使用者資訊,但是我們需要在通過身份驗證後從單獨的端點獲取首選項,即使此格式與我們預期的格式不同

我們可以將這種差異完全隔離在我們的 VueX 的 action 中,防止我們需要改變我們前端的其他任何地方。由於 promises 可以鏈式呼叫和巢狀,我們可以在我們的行為被視為完成之前,通過一系列需要完成的 API 呼叫。

actions: {
    login(context, credentials) {
    return myLoginApi.post(credentials).then((userData) => {
        const user = { ...userData };
        return myPreferencesApi.get(userData.id).then((preferencesData) => {
        user.preferences = transformPreferencesData(preferencesData);
        context.commit('setCurrentUser', user)
        });
    })
    }
}
複製程式碼

從我們的狀態修改和 dispatch 給我們的 login action 的程式碼的角度來看,最終的結果是完全相同的。

藉助 VueX,將新的或變化的後端 API 整合到我們的前端的挑戰已經大大簡化。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章