'Javascript 前端設計模式'

"

工具匆匆過,模式永流傳

雖然在我們的項目中使用新的框架/庫可能很酷,但我們經常忽略了為什麼使用它們,而是“為了使用它而使用它”。

在人們製作桌面/企業應用程序的日子裡,出現了許多設計模式/軟件架構設計。它們由明智的工程師設計,以解決其應用程序中信息流的複雜性。今天,當我們忙於製作Web應用程序時,這種複雜性並不會消失,只有這一次階段才會從桌面/企業私有服務器變為瀏覽器。因此,我們應該能夠從這些看似不那麼性感的架構模式中學習,以管理我們的前端應用程序。

由於有豐富的代碼示例和資源來學習前端社區中工具“使用方法”,因此本文不應該是另一個。相反,我們的重點將放在“前端應用程序的體系結構”上,或更明確地說,“在應用程序中管理大量不斷變化的部分的方法”,這在當今豐富的UI交互中。如果這篇文章可以促進這一主題的思考和討論,那麼它的目的就大大提高了。

在React,Angular 之前。。。

"

工具匆匆過,模式永流傳

雖然在我們的項目中使用新的框架/庫可能很酷,但我們經常忽略了為什麼使用它們,而是“為了使用它而使用它”。

在人們製作桌面/企業應用程序的日子裡,出現了許多設計模式/軟件架構設計。它們由明智的工程師設計,以解決其應用程序中信息流的複雜性。今天,當我們忙於製作Web應用程序時,這種複雜性並不會消失,只有這一次階段才會從桌面/企業私有服務器變為瀏覽器。因此,我們應該能夠從這些看似不那麼性感的架構模式中學習,以管理我們的前端應用程序。

由於有豐富的代碼示例和資源來學習前端社區中工具“使用方法”,因此本文不應該是另一個。相反,我們的重點將放在“前端應用程序的體系結構”上,或更明確地說,“在應用程序中管理大量不斷變化的部分的方法”,這在當今豐富的UI交互中。如果這篇文章可以促進這一主題的思考和討論,那麼它的目的就大大提高了。

在React,Angular 之前。。。

Javascript 前端設計模式

這是作者開始Web開發之旅的地方(甚至在學習vanilla javascript之前)。jQuery提供了一種選擇和操作DOM的便捷方法。假設我們正在構建像Netflix這樣的網絡應用。我們將向用戶顯示電影列表。我們以下列格式保存這些數據:

[{id:123,title:'Ironman',savedForLater:true},
{id:456,title:'X-Men',savedForLater:false},
{id:789,title:'Aquaman',savedForLater:false} ,
...
]

我們可以遍歷數組並使用“appendChild”到document 來記錄包含的相關信息。然後,對於每部電影,我們提供一個按鈕供用戶點擊,以便切換savedForLater布爾字段。我們可以綁定onClick事件並更新列表。要更新UI,我們可以刪除所有子節點並重新渲染它們,或者我們可以通過id選擇DOM子節點,創建容器div,使用新節點添加appendChild,刪除舊節點和容器。

接下來,我們要添加一個顯示savedForLater計數的功能,導航欄中出現的書籤圖標按鈕上的數字徽章。(像購物車一樣!?)為了使這個計數保持最新,我們可以將它綁定到每個savedForLater按鈕的onClick事件 - 更新列表變量,更新卡片UI,更新計數顯示。

(可能有另一種不創建數組變量的方法。它是在每個影片DOM元素的數據屬性中保存每個影片的所有信息。為了得到計數,我們可以遍歷元素並總結值像data-savedForLater這樣的屬性)

但是,我們可以看到,當有越來越多的功能/ UI交互時,我們必須自己處理越來越多的DOM操作,如有必要,我們要同時管理任何全局變量(movie array,isLoading,isLoggedIn,themeColor。。。)。

"

工具匆匆過,模式永流傳

雖然在我們的項目中使用新的框架/庫可能很酷,但我們經常忽略了為什麼使用它們,而是“為了使用它而使用它”。

在人們製作桌面/企業應用程序的日子裡,出現了許多設計模式/軟件架構設計。它們由明智的工程師設計,以解決其應用程序中信息流的複雜性。今天,當我們忙於製作Web應用程序時,這種複雜性並不會消失,只有這一次階段才會從桌面/企業私有服務器變為瀏覽器。因此,我們應該能夠從這些看似不那麼性感的架構模式中學習,以管理我們的前端應用程序。

由於有豐富的代碼示例和資源來學習前端社區中工具“使用方法”,因此本文不應該是另一個。相反,我們的重點將放在“前端應用程序的體系結構”上,或更明確地說,“在應用程序中管理大量不斷變化的部分的方法”,這在當今豐富的UI交互中。如果這篇文章可以促進這一主題的思考和討論,那麼它的目的就大大提高了。

在React,Angular 之前。。。

Javascript 前端設計模式

這是作者開始Web開發之旅的地方(甚至在學習vanilla javascript之前)。jQuery提供了一種選擇和操作DOM的便捷方法。假設我們正在構建像Netflix這樣的網絡應用。我們將向用戶顯示電影列表。我們以下列格式保存這些數據:

[{id:123,title:'Ironman',savedForLater:true},
{id:456,title:'X-Men',savedForLater:false},
{id:789,title:'Aquaman',savedForLater:false} ,
...
]

我們可以遍歷數組並使用“appendChild”到document 來記錄包含的相關信息。然後,對於每部電影,我們提供一個按鈕供用戶點擊,以便切換savedForLater布爾字段。我們可以綁定onClick事件並更新列表。要更新UI,我們可以刪除所有子節點並重新渲染它們,或者我們可以通過id選擇DOM子節點,創建容器div,使用新節點添加appendChild,刪除舊節點和容器。

接下來,我們要添加一個顯示savedForLater計數的功能,導航欄中出現的書籤圖標按鈕上的數字徽章。(像購物車一樣!?)為了使這個計數保持最新,我們可以將它綁定到每個savedForLater按鈕的onClick事件 - 更新列表變量,更新卡片UI,更新計數顯示。

(可能有另一種不創建數組變量的方法。它是在每個影片DOM元素的數據屬性中保存每個影片的所有信息。為了得到計數,我們可以遍歷元素並總結值像data-savedForLater這樣的屬性)

但是,我們可以看到,當有越來越多的功能/ UI交互時,我們必須自己處理越來越多的DOM操作,如有必要,我們要同時管理任何全局變量(movie array,isLoading,isLoggedIn,themeColor。。。)。

Javascript 前端設計模式

UI狀態交互的示意圖

這就是Angular,React,Vue等前端框架的用武之地。一旦我們更新了應用程序的狀態(Model),所有這些框架/庫都將為我們處理DOM操作(View)。更新模型,更改視圖,聽起來很熟悉?是的,讓我們說下架構模式。

架構模式

MVVM模式,雙向綁定

在構造應用程序時,我們都聽說過MVC(模型視圖控制器)模式。在SPA的上下文中,我們可以說Model = App State,V = Html模板。對於Angular和Vue.js,它們的模式更接近於MVC的變體 - MVVM(模型視圖 - 模型)。在這種情況下,每個DOM元素(或一組元素)僅對模型的某個部分感興趣(即僅是app狀態的一部分)。通過將每個元素綁定到模型的負責部分(View-Model層),它可以直接監聽(讀取)/更新(寫入)模型的一部分。這也稱為雙向綁定。

"

工具匆匆過,模式永流傳

雖然在我們的項目中使用新的框架/庫可能很酷,但我們經常忽略了為什麼使用它們,而是“為了使用它而使用它”。

在人們製作桌面/企業應用程序的日子裡,出現了許多設計模式/軟件架構設計。它們由明智的工程師設計,以解決其應用程序中信息流的複雜性。今天,當我們忙於製作Web應用程序時,這種複雜性並不會消失,只有這一次階段才會從桌面/企業私有服務器變為瀏覽器。因此,我們應該能夠從這些看似不那麼性感的架構模式中學習,以管理我們的前端應用程序。

由於有豐富的代碼示例和資源來學習前端社區中工具“使用方法”,因此本文不應該是另一個。相反,我們的重點將放在“前端應用程序的體系結構”上,或更明確地說,“在應用程序中管理大量不斷變化的部分的方法”,這在當今豐富的UI交互中。如果這篇文章可以促進這一主題的思考和討論,那麼它的目的就大大提高了。

在React,Angular 之前。。。

Javascript 前端設計模式

這是作者開始Web開發之旅的地方(甚至在學習vanilla javascript之前)。jQuery提供了一種選擇和操作DOM的便捷方法。假設我們正在構建像Netflix這樣的網絡應用。我們將向用戶顯示電影列表。我們以下列格式保存這些數據:

[{id:123,title:'Ironman',savedForLater:true},
{id:456,title:'X-Men',savedForLater:false},
{id:789,title:'Aquaman',savedForLater:false} ,
...
]

我們可以遍歷數組並使用“appendChild”到document 來記錄包含的相關信息。然後,對於每部電影,我們提供一個按鈕供用戶點擊,以便切換savedForLater布爾字段。我們可以綁定onClick事件並更新列表。要更新UI,我們可以刪除所有子節點並重新渲染它們,或者我們可以通過id選擇DOM子節點,創建容器div,使用新節點添加appendChild,刪除舊節點和容器。

接下來,我們要添加一個顯示savedForLater計數的功能,導航欄中出現的書籤圖標按鈕上的數字徽章。(像購物車一樣!?)為了使這個計數保持最新,我們可以將它綁定到每個savedForLater按鈕的onClick事件 - 更新列表變量,更新卡片UI,更新計數顯示。

(可能有另一種不創建數組變量的方法。它是在每個影片DOM元素的數據屬性中保存每個影片的所有信息。為了得到計數,我們可以遍歷元素並總結值像data-savedForLater這樣的屬性)

但是,我們可以看到,當有越來越多的功能/ UI交互時,我們必須自己處理越來越多的DOM操作,如有必要,我們要同時管理任何全局變量(movie array,isLoading,isLoggedIn,themeColor。。。)。

Javascript 前端設計模式

UI狀態交互的示意圖

這就是Angular,React,Vue等前端框架的用武之地。一旦我們更新了應用程序的狀態(Model),所有這些框架/庫都將為我們處理DOM操作(View)。更新模型,更改視圖,聽起來很熟悉?是的,讓我們說下架構模式。

架構模式

MVVM模式,雙向綁定

在構造應用程序時,我們都聽說過MVC(模型視圖控制器)模式。在SPA的上下文中,我們可以說Model = App State,V = Html模板。對於Angular和Vue.js,它們的模式更接近於MVC的變體 - MVVM(模型視圖 - 模型)。在這種情況下,每個DOM元素(或一組元素)僅對模型的某個部分感興趣(即僅是app狀態的一部分)。通過將每個元素綁定到模型的負責部分(View-Model層),它可以直接監聽(讀取)/更新(寫入)模型的一部分。這也稱為雙向綁定。

Javascript 前端設計模式

具有MVVM模式的Angular和Vue.js的代碼片段

使用這種模式,我們實現了關注點的分離 - 將業務邏輯(模型)與表示層(View)分離。此模式允許快速和直接操作數據模型,這是基於CRUD(創建 - 讀取 - 更新 - 刪除)的應用程序的理想選擇。

CRUD應用和基於任務的應用

CRUD應用程序例如是Todo List,Employee List等。為您顯示數據項的行,對於每個數據項,您可以單擊“編輯”以更新該項目的某些屬性,然後“保存”它。您還可以使用“添加”按鈕插入新行,使用“刪除”按鈕刪除某行。這就像擁有一個用於數據庫操作的圖形用戶界面。

我們也想構建的另一種應用是基於任務的應用。示例應用程序是酒店/航班預訂應用程序,電子商務應用程序或MacBook上的“系統偏好設置”應用程序。您需要完成一系列步驟才能完成工作。就數據模型/應用程序狀態而言,CRUD應用程序和基於任務的應用程序之間的根本區別在於後面的應用程序的狀態將不僅僅具有“書籍列表”的數據,例如“currentStep”,“currentUser”, “isDarkMode”。

"

工具匆匆過,模式永流傳

雖然在我們的項目中使用新的框架/庫可能很酷,但我們經常忽略了為什麼使用它們,而是“為了使用它而使用它”。

在人們製作桌面/企業應用程序的日子裡,出現了許多設計模式/軟件架構設計。它們由明智的工程師設計,以解決其應用程序中信息流的複雜性。今天,當我們忙於製作Web應用程序時,這種複雜性並不會消失,只有這一次階段才會從桌面/企業私有服務器變為瀏覽器。因此,我們應該能夠從這些看似不那麼性感的架構模式中學習,以管理我們的前端應用程序。

由於有豐富的代碼示例和資源來學習前端社區中工具“使用方法”,因此本文不應該是另一個。相反,我們的重點將放在“前端應用程序的體系結構”上,或更明確地說,“在應用程序中管理大量不斷變化的部分的方法”,這在當今豐富的UI交互中。如果這篇文章可以促進這一主題的思考和討論,那麼它的目的就大大提高了。

在React,Angular 之前。。。

Javascript 前端設計模式

這是作者開始Web開發之旅的地方(甚至在學習vanilla javascript之前)。jQuery提供了一種選擇和操作DOM的便捷方法。假設我們正在構建像Netflix這樣的網絡應用。我們將向用戶顯示電影列表。我們以下列格式保存這些數據:

[{id:123,title:'Ironman',savedForLater:true},
{id:456,title:'X-Men',savedForLater:false},
{id:789,title:'Aquaman',savedForLater:false} ,
...
]

我們可以遍歷數組並使用“appendChild”到document 來記錄包含的相關信息。然後,對於每部電影,我們提供一個按鈕供用戶點擊,以便切換savedForLater布爾字段。我們可以綁定onClick事件並更新列表。要更新UI,我們可以刪除所有子節點並重新渲染它們,或者我們可以通過id選擇DOM子節點,創建容器div,使用新節點添加appendChild,刪除舊節點和容器。

接下來,我們要添加一個顯示savedForLater計數的功能,導航欄中出現的書籤圖標按鈕上的數字徽章。(像購物車一樣!?)為了使這個計數保持最新,我們可以將它綁定到每個savedForLater按鈕的onClick事件 - 更新列表變量,更新卡片UI,更新計數顯示。

(可能有另一種不創建數組變量的方法。它是在每個影片DOM元素的數據屬性中保存每個影片的所有信息。為了得到計數,我們可以遍歷元素並總結值像data-savedForLater這樣的屬性)

但是,我們可以看到,當有越來越多的功能/ UI交互時,我們必須自己處理越來越多的DOM操作,如有必要,我們要同時管理任何全局變量(movie array,isLoading,isLoggedIn,themeColor。。。)。

Javascript 前端設計模式

UI狀態交互的示意圖

這就是Angular,React,Vue等前端框架的用武之地。一旦我們更新了應用程序的狀態(Model),所有這些框架/庫都將為我們處理DOM操作(View)。更新模型,更改視圖,聽起來很熟悉?是的,讓我們說下架構模式。

架構模式

MVVM模式,雙向綁定

在構造應用程序時,我們都聽說過MVC(模型視圖控制器)模式。在SPA的上下文中,我們可以說Model = App State,V = Html模板。對於Angular和Vue.js,它們的模式更接近於MVC的變體 - MVVM(模型視圖 - 模型)。在這種情況下,每個DOM元素(或一組元素)僅對模型的某個部分感興趣(即僅是app狀態的一部分)。通過將每個元素綁定到模型的負責部分(View-Model層),它可以直接監聽(讀取)/更新(寫入)模型的一部分。這也稱為雙向綁定。

Javascript 前端設計模式

具有MVVM模式的Angular和Vue.js的代碼片段

使用這種模式,我們實現了關注點的分離 - 將業務邏輯(模型)與表示層(View)分離。此模式允許快速和直接操作數據模型,這是基於CRUD(創建 - 讀取 - 更新 - 刪除)的應用程序的理想選擇。

CRUD應用和基於任務的應用

CRUD應用程序例如是Todo List,Employee List等。為您顯示數據項的行,對於每個數據項,您可以單擊“編輯”以更新該項目的某些屬性,然後“保存”它。您還可以使用“添加”按鈕插入新行,使用“刪除”按鈕刪除某行。這就像擁有一個用於數據庫操作的圖形用戶界面。

我們也想構建的另一種應用是基於任務的應用。示例應用程序是酒店/航班預訂應用程序,電子商務應用程序或MacBook上的“系統偏好設置”應用程序。您需要完成一系列步驟才能完成工作。就數據模型/應用程序狀態而言,CRUD應用程序和基於任務的應用程序之間的根本區別在於後面的應用程序的狀態將不僅僅具有“書籍列表”的數據,例如“currentStep”,“currentUser”, “isDarkMode”。

Javascript 前端設計模式

如果我們要使用雙向綁定模式,我們將為每個UI組件創建與模型相關部分的綁定。在這些綁定中的每一箇中,讀取和寫入操作都是強耦合的。雖然這在CRUD應用程序案例中可能是一個好主意,其中每個UI組件負責數據模型的某個部分的讀取和寫入操作,但在基於任務的應用程序中,讀取並不常見only /只寫UI組件。雖然可以為這些組件中的每一個創建雙向綁定,但是用於改變數據模型的相同部分的多餘“路徑”是狀態管理的混亂源自何處。

這裡我們將要實現另一種設計模式CQRS(Command Query Responsibility Segregation),或者在簡單的英文中,查詢(read)和命令(write)應該分開完成。

這並不意味著像Angular和Vue.js這樣的框架變得毫無用處。Angular服務是應用CQRS模式的一個很好的例子:你有私有變量存儲有問題的項目,公共getter(查詢)和setter(命令)作為單獨的方法.Angular的官方文檔中的“ 管理數據 ”部分有一個很好的說明。是否有利用CQRS的架構模式?當然有。

事件總線,單向綁定

當事件發生時,組件可以向事件總線發送消息(例如,用戶單擊按鈕)。組件還可以訂閱事件總線以獲取他們關注的事件。事件總線會在收到消息時將消息發送給訂閱者。這種類似中間人的模式也稱為單向綁定,因為該組件不是直接讀寫綁定到模型的。相反,組件訂閱要讀取的模型的一部分; 並將事件發送到“狀態處理程序”來編寫而不是自己編寫。React是一個實現單向綁定的庫。換句話說,我們需要自己連接讀寫週期。

"

工具匆匆過,模式永流傳

雖然在我們的項目中使用新的框架/庫可能很酷,但我們經常忽略了為什麼使用它們,而是“為了使用它而使用它”。

在人們製作桌面/企業應用程序的日子裡,出現了許多設計模式/軟件架構設計。它們由明智的工程師設計,以解決其應用程序中信息流的複雜性。今天,當我們忙於製作Web應用程序時,這種複雜性並不會消失,只有這一次階段才會從桌面/企業私有服務器變為瀏覽器。因此,我們應該能夠從這些看似不那麼性感的架構模式中學習,以管理我們的前端應用程序。

由於有豐富的代碼示例和資源來學習前端社區中工具“使用方法”,因此本文不應該是另一個。相反,我們的重點將放在“前端應用程序的體系結構”上,或更明確地說,“在應用程序中管理大量不斷變化的部分的方法”,這在當今豐富的UI交互中。如果這篇文章可以促進這一主題的思考和討論,那麼它的目的就大大提高了。

在React,Angular 之前。。。

Javascript 前端設計模式

這是作者開始Web開發之旅的地方(甚至在學習vanilla javascript之前)。jQuery提供了一種選擇和操作DOM的便捷方法。假設我們正在構建像Netflix這樣的網絡應用。我們將向用戶顯示電影列表。我們以下列格式保存這些數據:

[{id:123,title:'Ironman',savedForLater:true},
{id:456,title:'X-Men',savedForLater:false},
{id:789,title:'Aquaman',savedForLater:false} ,
...
]

我們可以遍歷數組並使用“appendChild”到document 來記錄包含的相關信息。然後,對於每部電影,我們提供一個按鈕供用戶點擊,以便切換savedForLater布爾字段。我們可以綁定onClick事件並更新列表。要更新UI,我們可以刪除所有子節點並重新渲染它們,或者我們可以通過id選擇DOM子節點,創建容器div,使用新節點添加appendChild,刪除舊節點和容器。

接下來,我們要添加一個顯示savedForLater計數的功能,導航欄中出現的書籤圖標按鈕上的數字徽章。(像購物車一樣!?)為了使這個計數保持最新,我們可以將它綁定到每個savedForLater按鈕的onClick事件 - 更新列表變量,更新卡片UI,更新計數顯示。

(可能有另一種不創建數組變量的方法。它是在每個影片DOM元素的數據屬性中保存每個影片的所有信息。為了得到計數,我們可以遍歷元素並總結值像data-savedForLater這樣的屬性)

但是,我們可以看到,當有越來越多的功能/ UI交互時,我們必須自己處理越來越多的DOM操作,如有必要,我們要同時管理任何全局變量(movie array,isLoading,isLoggedIn,themeColor。。。)。

Javascript 前端設計模式

UI狀態交互的示意圖

這就是Angular,React,Vue等前端框架的用武之地。一旦我們更新了應用程序的狀態(Model),所有這些框架/庫都將為我們處理DOM操作(View)。更新模型,更改視圖,聽起來很熟悉?是的,讓我們說下架構模式。

架構模式

MVVM模式,雙向綁定

在構造應用程序時,我們都聽說過MVC(模型視圖控制器)模式。在SPA的上下文中,我們可以說Model = App State,V = Html模板。對於Angular和Vue.js,它們的模式更接近於MVC的變體 - MVVM(模型視圖 - 模型)。在這種情況下,每個DOM元素(或一組元素)僅對模型的某個部分感興趣(即僅是app狀態的一部分)。通過將每個元素綁定到模型的負責部分(View-Model層),它可以直接監聽(讀取)/更新(寫入)模型的一部分。這也稱為雙向綁定。

Javascript 前端設計模式

具有MVVM模式的Angular和Vue.js的代碼片段

使用這種模式,我們實現了關注點的分離 - 將業務邏輯(模型)與表示層(View)分離。此模式允許快速和直接操作數據模型,這是基於CRUD(創建 - 讀取 - 更新 - 刪除)的應用程序的理想選擇。

CRUD應用和基於任務的應用

CRUD應用程序例如是Todo List,Employee List等。為您顯示數據項的行,對於每個數據項,您可以單擊“編輯”以更新該項目的某些屬性,然後“保存”它。您還可以使用“添加”按鈕插入新行,使用“刪除”按鈕刪除某行。這就像擁有一個用於數據庫操作的圖形用戶界面。

我們也想構建的另一種應用是基於任務的應用。示例應用程序是酒店/航班預訂應用程序,電子商務應用程序或MacBook上的“系統偏好設置”應用程序。您需要完成一系列步驟才能完成工作。就數據模型/應用程序狀態而言,CRUD應用程序和基於任務的應用程序之間的根本區別在於後面的應用程序的狀態將不僅僅具有“書籍列表”的數據,例如“currentStep”,“currentUser”, “isDarkMode”。

Javascript 前端設計模式

如果我們要使用雙向綁定模式,我們將為每個UI組件創建與模型相關部分的綁定。在這些綁定中的每一箇中,讀取和寫入操作都是強耦合的。雖然這在CRUD應用程序案例中可能是一個好主意,其中每個UI組件負責數據模型的某個部分的讀取和寫入操作,但在基於任務的應用程序中,讀取並不常見only /只寫UI組件。雖然可以為這些組件中的每一個創建雙向綁定,但是用於改變數據模型的相同部分的多餘“路徑”是狀態管理的混亂源自何處。

這裡我們將要實現另一種設計模式CQRS(Command Query Responsibility Segregation),或者在簡單的英文中,查詢(read)和命令(write)應該分開完成。

這並不意味著像Angular和Vue.js這樣的框架變得毫無用處。Angular服務是應用CQRS模式的一個很好的例子:你有私有變量存儲有問題的項目,公共getter(查詢)和setter(命令)作為單獨的方法.Angular的官方文檔中的“ 管理數據 ”部分有一個很好的說明。是否有利用CQRS的架構模式?當然有。

事件總線,單向綁定

當事件發生時,組件可以向事件總線發送消息(例如,用戶單擊按鈕)。組件還可以訂閱事件總線以獲取他們關注的事件。事件總線會在收到消息時將消息發送給訂閱者。這種類似中間人的模式也稱為單向綁定,因為該組件不是直接讀寫綁定到模型的。相反,組件訂閱要讀取的模型的一部分; 並將事件發送到“狀態處理程序”來編寫而不是自己編寫。React是一個實現單向綁定的庫。換句話說,我們需要自己連接讀寫週期。

Javascript 前端設計模式

實現單向綁定的React組件的示例

在上面的示例中,我們可以說按鈕是發送消息到事件總線的發佈者,而h1是一個訂閱者,用於監聽數據模型/應用程序狀態的計數部分的更改。

這種分離讀寫問題的方法在這個簡單的基於任務的應用程序的可維護性方面似乎非常令人滿意(好吧,所以你的任務是將顯示數量抽到100 ......無論如何),僅使用這種方法來處理大規模的e-商務應用可能會成為一場噩夢。你可以想象在著陸頁上有許多“狀態處理函數”改變了同一個狀態(例如,單擊按鈕A將切換狀態值.A,在輸入B中鍵入文本將同時更新狀態值.B和state.A,從api獲取數據將在完成時更新state.B和state.C的值,依此類推)。我們需要一種方法來管理一個數據模型的變異方式和時間。

Flux 模式 Redux

Flux模式通過提供狀態突變的明確性來解決這個問題。我們來看一下通量模式下的典型數據流。

"

工具匆匆過,模式永流傳

雖然在我們的項目中使用新的框架/庫可能很酷,但我們經常忽略了為什麼使用它們,而是“為了使用它而使用它”。

在人們製作桌面/企業應用程序的日子裡,出現了許多設計模式/軟件架構設計。它們由明智的工程師設計,以解決其應用程序中信息流的複雜性。今天,當我們忙於製作Web應用程序時,這種複雜性並不會消失,只有這一次階段才會從桌面/企業私有服務器變為瀏覽器。因此,我們應該能夠從這些看似不那麼性感的架構模式中學習,以管理我們的前端應用程序。

由於有豐富的代碼示例和資源來學習前端社區中工具“使用方法”,因此本文不應該是另一個。相反,我們的重點將放在“前端應用程序的體系結構”上,或更明確地說,“在應用程序中管理大量不斷變化的部分的方法”,這在當今豐富的UI交互中。如果這篇文章可以促進這一主題的思考和討論,那麼它的目的就大大提高了。

在React,Angular 之前。。。

Javascript 前端設計模式

這是作者開始Web開發之旅的地方(甚至在學習vanilla javascript之前)。jQuery提供了一種選擇和操作DOM的便捷方法。假設我們正在構建像Netflix這樣的網絡應用。我們將向用戶顯示電影列表。我們以下列格式保存這些數據:

[{id:123,title:'Ironman',savedForLater:true},
{id:456,title:'X-Men',savedForLater:false},
{id:789,title:'Aquaman',savedForLater:false} ,
...
]

我們可以遍歷數組並使用“appendChild”到document 來記錄包含的相關信息。然後,對於每部電影,我們提供一個按鈕供用戶點擊,以便切換savedForLater布爾字段。我們可以綁定onClick事件並更新列表。要更新UI,我們可以刪除所有子節點並重新渲染它們,或者我們可以通過id選擇DOM子節點,創建容器div,使用新節點添加appendChild,刪除舊節點和容器。

接下來,我們要添加一個顯示savedForLater計數的功能,導航欄中出現的書籤圖標按鈕上的數字徽章。(像購物車一樣!?)為了使這個計數保持最新,我們可以將它綁定到每個savedForLater按鈕的onClick事件 - 更新列表變量,更新卡片UI,更新計數顯示。

(可能有另一種不創建數組變量的方法。它是在每個影片DOM元素的數據屬性中保存每個影片的所有信息。為了得到計數,我們可以遍歷元素並總結值像data-savedForLater這樣的屬性)

但是,我們可以看到,當有越來越多的功能/ UI交互時,我們必須自己處理越來越多的DOM操作,如有必要,我們要同時管理任何全局變量(movie array,isLoading,isLoggedIn,themeColor。。。)。

Javascript 前端設計模式

UI狀態交互的示意圖

這就是Angular,React,Vue等前端框架的用武之地。一旦我們更新了應用程序的狀態(Model),所有這些框架/庫都將為我們處理DOM操作(View)。更新模型,更改視圖,聽起來很熟悉?是的,讓我們說下架構模式。

架構模式

MVVM模式,雙向綁定

在構造應用程序時,我們都聽說過MVC(模型視圖控制器)模式。在SPA的上下文中,我們可以說Model = App State,V = Html模板。對於Angular和Vue.js,它們的模式更接近於MVC的變體 - MVVM(模型視圖 - 模型)。在這種情況下,每個DOM元素(或一組元素)僅對模型的某個部分感興趣(即僅是app狀態的一部分)。通過將每個元素綁定到模型的負責部分(View-Model層),它可以直接監聽(讀取)/更新(寫入)模型的一部分。這也稱為雙向綁定。

Javascript 前端設計模式

具有MVVM模式的Angular和Vue.js的代碼片段

使用這種模式,我們實現了關注點的分離 - 將業務邏輯(模型)與表示層(View)分離。此模式允許快速和直接操作數據模型,這是基於CRUD(創建 - 讀取 - 更新 - 刪除)的應用程序的理想選擇。

CRUD應用和基於任務的應用

CRUD應用程序例如是Todo List,Employee List等。為您顯示數據項的行,對於每個數據項,您可以單擊“編輯”以更新該項目的某些屬性,然後“保存”它。您還可以使用“添加”按鈕插入新行,使用“刪除”按鈕刪除某行。這就像擁有一個用於數據庫操作的圖形用戶界面。

我們也想構建的另一種應用是基於任務的應用。示例應用程序是酒店/航班預訂應用程序,電子商務應用程序或MacBook上的“系統偏好設置”應用程序。您需要完成一系列步驟才能完成工作。就數據模型/應用程序狀態而言,CRUD應用程序和基於任務的應用程序之間的根本區別在於後面的應用程序的狀態將不僅僅具有“書籍列表”的數據,例如“currentStep”,“currentUser”, “isDarkMode”。

Javascript 前端設計模式

如果我們要使用雙向綁定模式,我們將為每個UI組件創建與模型相關部分的綁定。在這些綁定中的每一箇中,讀取和寫入操作都是強耦合的。雖然這在CRUD應用程序案例中可能是一個好主意,其中每個UI組件負責數據模型的某個部分的讀取和寫入操作,但在基於任務的應用程序中,讀取並不常見only /只寫UI組件。雖然可以為這些組件中的每一個創建雙向綁定,但是用於改變數據模型的相同部分的多餘“路徑”是狀態管理的混亂源自何處。

這裡我們將要實現另一種設計模式CQRS(Command Query Responsibility Segregation),或者在簡單的英文中,查詢(read)和命令(write)應該分開完成。

這並不意味著像Angular和Vue.js這樣的框架變得毫無用處。Angular服務是應用CQRS模式的一個很好的例子:你有私有變量存儲有問題的項目,公共getter(查詢)和setter(命令)作為單獨的方法.Angular的官方文檔中的“ 管理數據 ”部分有一個很好的說明。是否有利用CQRS的架構模式?當然有。

事件總線,單向綁定

當事件發生時,組件可以向事件總線發送消息(例如,用戶單擊按鈕)。組件還可以訂閱事件總線以獲取他們關注的事件。事件總線會在收到消息時將消息發送給訂閱者。這種類似中間人的模式也稱為單向綁定,因為該組件不是直接讀寫綁定到模型的。相反,組件訂閱要讀取的模型的一部分; 並將事件發送到“狀態處理程序”來編寫而不是自己編寫。React是一個實現單向綁定的庫。換句話說,我們需要自己連接讀寫週期。

Javascript 前端設計模式

實現單向綁定的React組件的示例

在上面的示例中,我們可以說按鈕是發送消息到事件總線的發佈者,而h1是一個訂閱者,用於監聽數據模型/應用程序狀態的計數部分的更改。

這種分離讀寫問題的方法在這個簡單的基於任務的應用程序的可維護性方面似乎非常令人滿意(好吧,所以你的任務是將顯示數量抽到100 ......無論如何),僅使用這種方法來處理大規模的e-商務應用可能會成為一場噩夢。你可以想象在著陸頁上有許多“狀態處理函數”改變了同一個狀態(例如,單擊按鈕A將切換狀態值.A,在輸入B中鍵入文本將同時更新狀態值.B和state.A,從api獲取數據將在完成時更新state.B和state.C的值,依此類推)。我們需要一種方法來管理一個數據模型的變異方式和時間。

Flux 模式 Redux

Flux模式通過提供狀態突變的明確性來解決這個問題。我們來看一下通量模式下的典型數據流。

Javascript 前端設計模式

Flux模式中的數據流示例

狀態改變的明確性通過以下方式實現:

  • state只能通過調度程序進行改變,而不是任意的“狀態處理程序”
  • 要使調度程序改變狀態,唯一的方法是發出一個動作
  • 如此確切地說,對於一個視圖來改變一個狀態,唯一的方法是發出一個動作(或者說Redux-ly,發出一個動作)

因此,通過監視操作及其包含的信息,整個應用程序的數據變異在我們的控制之下(何時以及如何更改)。

總結

我們經歷了從古老的jQuery到今天強大的Web開發工具之旅,如Angular,React,Vue。我們將Web應用程序剖析為View層和Model層,並探索管理它們之間信息流的方法。雙向綁定採用MVVM模式,其中View通過ViewModel與模型緊密綁定,從而允許每個View直接讀取和更新模型的相應部分。單向綁定借用了CQRS的設計原則,將寫操作與讀操作分開,我們自己有意識地實現了2個操作。Flux模式進一步推動了這一概念,將數據模型的變異限制為僅通過調度操作,從而通過密切監視這些操作來控制整個app狀態。

因此,下次我們可以停一下,並在編碼之前考慮下構建應用程序的方法。

"

相關推薦

推薦中...