javascript
javascript设计模式_Javascript 前端设计模式
工具匆匆過(guò),模式永流傳
雖然在我們的項(xiàng)目中使用新的框架/庫(kù)可能很酷,但我們經(jīng)常忽略了為什么使用它們,而是“為了使用它而使用它”。
在人們制作桌面/企業(yè)應(yīng)用程序的日子里,出現(xiàn)了許多設(shè)計(jì)模式/軟件架構(gòu)設(shè)計(jì)。它們由明智的工程師設(shè)計(jì),以解決其應(yīng)用程序中信息流的復(fù)雜性。今天,當(dāng)我們忙于制作Web應(yīng)用程序時(shí),這種復(fù)雜性并不會(huì)消失,只有這一次階段才會(huì)從桌面/企業(yè)私有服務(wù)器變?yōu)闉g覽器。因此,我們應(yīng)該能夠從這些看似不那么性感的架構(gòu)模式中學(xué)習(xí),以管理我們的前端應(yīng)用程序。
由于有豐富的代碼示例和資源來(lái)學(xué)習(xí)前端社區(qū)中工具“使用方法”,因此本文不應(yīng)該是另一個(gè)。相反,我們的重點(diǎn)將放在“前端應(yīng)用程序的體系結(jié)構(gòu)”上,或更明確地說(shuō),“在應(yīng)用程序中管理大量不斷變化的部分的方法”,這在當(dāng)今豐富的UI交互中。如果這篇文章可以促進(jìn)這一主題的思考和討論,那么它的目的就大大提高了。
在React,Angular 之前。。。
這是作者開(kāi)始Web開(kāi)發(fā)之旅的地方(甚至在學(xué)習(xí)vanilla javascript之前)。jQuery提供了一種選擇和操作DOM的便捷方法。假設(shè)我們正在構(gòu)建像Netflix這樣的網(wǎng)絡(luò)應(yīng)用。我們將向用戶(hù)顯示電影列表。我們以下列格式保存這些數(shù)據(jù):
[{id:123,title:'Ironman',savedForLater:true},{id:456,title:'X-Men',savedForLater:false},{id:789,title:'Aquaman',savedForLater:false} ,... ]我們可以遍歷數(shù)組并使用“appendChild”到document 來(lái)記錄包含的相關(guān)信息。然后,對(duì)于每部電影,我們提供一個(gè)按鈕供用戶(hù)點(diǎn)擊,以便切換savedForLater布爾字段。我們可以綁定onClick事件并更新列表。要更新UI,我們可以刪除所有子節(jié)點(diǎn)并重新渲染它們,或者我們可以通過(guò)id選擇DOM子節(jié)點(diǎn),創(chuàng)建容器div,使用新節(jié)點(diǎn)添加appendChild,刪除舊節(jié)點(diǎn)和容器。
接下來(lái),我們要添加一個(gè)顯示savedForLater計(jì)數(shù)的功能,導(dǎo)航欄中出現(xiàn)的書(shū)簽圖標(biāo)按鈕上的數(shù)字徽章。(像購(gòu)物車(chē)一樣!?)為了使這個(gè)計(jì)數(shù)保持最新,我們可以將它綁定到每個(gè)savedForLater按鈕的onClick事件 - 更新列表變量,更新卡片UI,更新計(jì)數(shù)顯示。
(可能有另一種不創(chuàng)建數(shù)組變量的方法。它是在每個(gè)影片DOM元素的數(shù)據(jù)屬性中保存每個(gè)影片的所有信息。為了得到計(jì)數(shù),我們可以遍歷元素并總結(jié)值像data-savedForLater這樣的屬性)
但是,我們可以看到,當(dāng)有越來(lái)越多的功能/ UI交互時(shí),我們必須自己處理越來(lái)越多的DOM操作,如有必要,我們要同時(shí)管理任何全局變量(movie array,isLoading,isLoggedIn,themeColor。。。)。
UI狀態(tài)交互的示意圖
這就是Angular,React,Vue等前端框架的用武之地。一旦我們更新了應(yīng)用程序的狀態(tài)(Model),所有這些框架/庫(kù)都將為我們處理DOM操作(View)。更新模型,更改視圖,聽(tīng)起來(lái)很熟悉?是的,讓我們說(shuō)下架構(gòu)模式。
架構(gòu)模式
MVVM模式,雙向綁定
在構(gòu)造應(yīng)用程序時(shí),我們都聽(tīng)說(shuō)過(guò)MVC(模型視圖控制器)模式。在SPA的上下文中,我們可以說(shuō)Model = App State,V = Html模板。對(duì)于Angular和Vue.js,它們的模式更接近于MVC的變體 - MVVM(模型視圖 - 模型)。在這種情況下,每個(gè)DOM元素(或一組元素)僅對(duì)模型的某個(gè)部分感興趣(即僅是app狀態(tài)的一部分)。通過(guò)將每個(gè)元素綁定到模型的負(fù)責(zé)部分(View-Model層),它可以直接監(jiān)聽(tīng)(讀取)/更新(寫(xiě)入)模型的一部分。這也稱(chēng)為雙向綁定。
具有MVVM模式的Angular和Vue.js的代碼片段
使用這種模式,我們實(shí)現(xiàn)了關(guān)注點(diǎn)的分離 - 將業(yè)務(wù)邏輯(模型)與表示層(View)分離。此模式允許快速和直接操作數(shù)據(jù)模型,這是基于CRUD(創(chuàng)建 - 讀取 - 更新 - 刪除)的應(yīng)用程序的理想選擇。
CRUD應(yīng)用和基于任務(wù)的應(yīng)用
CRUD應(yīng)用程序例如是Todo List,Employee List等。為您顯示數(shù)據(jù)項(xiàng)的行,對(duì)于每個(gè)數(shù)據(jù)項(xiàng),您可以單擊“編輯”以更新該項(xiàng)目的某些屬性,然后“保存”它。您還可以使用“添加”按鈕插入新行,使用“刪除”按鈕刪除某行。這就像擁有一個(gè)用于數(shù)據(jù)庫(kù)操作的圖形用戶(hù)界面。
我們也想構(gòu)建的另一種應(yīng)用是基于任務(wù)的應(yīng)用。示例應(yīng)用程序是酒店/航班預(yù)訂應(yīng)用程序,電子商務(wù)應(yīng)用程序或MacBook上的“系統(tǒng)偏好設(shè)置”應(yīng)用程序。您需要完成一系列步驟才能完成工作。就數(shù)據(jù)模型/應(yīng)用程序狀態(tài)而言,CRUD應(yīng)用程序和基于任務(wù)的應(yīng)用程序之間的根本區(qū)別在于后面的應(yīng)用程序的狀態(tài)將不僅僅具有“書(shū)籍列表”的數(shù)據(jù),例如“currentStep”,“currentUser”, “isDarkMode”。
如果我們要使用雙向綁定模式,我們將為每個(gè)UI組件創(chuàng)建與模型相關(guān)部分的綁定。在這些綁定中的每一個(gè)中,讀取和寫(xiě)入操作都是強(qiáng)耦合的。雖然這在CRUD應(yīng)用程序案例中可能是一個(gè)好主意,其中每個(gè)UI組件負(fù)責(zé)數(shù)據(jù)模型的某個(gè)部分的讀取和寫(xiě)入操作,但在基于任務(wù)的應(yīng)用程序中,讀取并不常見(jiàn)only /只寫(xiě)UI組件。雖然可以為這些組件中的每一個(gè)創(chuàng)建雙向綁定,但是用于改變數(shù)據(jù)模型的相同部分的多余“路徑”是狀態(tài)管理的混亂源自何處。
這里我們將要實(shí)現(xiàn)另一種設(shè)計(jì)模式CQRS(Command Query Responsibility Segregation),或者在簡(jiǎn)單的英文中,查詢(xún)(read)和命令(write)應(yīng)該分開(kāi)完成。
這并不意味著像Angular和Vue.js這樣的框架變得毫無(wú)用處。Angular服務(wù)是應(yīng)用CQRS模式的一個(gè)很好的例子:你有私有變量存儲(chǔ)有問(wèn)題的項(xiàng)目,公共getter(查詢(xún))和setter(命令)作為單獨(dú)的方法.Angular的官方文檔中的“ 管理數(shù)據(jù) ”部分有一個(gè)很好的說(shuō)明。是否有利用CQRS的架構(gòu)模式?當(dāng)然有。
事件總線(xiàn),單向綁定
當(dāng)事件發(fā)生時(shí),組件可以向事件總線(xiàn)發(fā)送消息(例如,用戶(hù)單擊按鈕)。組件還可以訂閱事件總線(xiàn)以獲取他們關(guān)注的事件。事件總線(xiàn)會(huì)在收到消息時(shí)將消息發(fā)送給訂閱者。這種類(lèi)似中間人的模式也稱(chēng)為單向綁定,因?yàn)樵摻M件不是直接讀寫(xiě)綁定到模型的。相反,組件訂閱要讀取的模型的一部分; 并將事件發(fā)送到“狀態(tài)處理程序”來(lái)編寫(xiě)而不是自己編寫(xiě)。React是一個(gè)實(shí)現(xiàn)單向綁定的庫(kù)。換句話(huà)說(shuō),我們需要自己連接讀寫(xiě)周期。
實(shí)現(xiàn)單向綁定的React組件的示例
在上面的示例中,我們可以說(shuō)按鈕是發(fā)送消息到事件總線(xiàn)的發(fā)布者,而h1是一個(gè)訂閱者,用于監(jiān)聽(tīng)數(shù)據(jù)模型/應(yīng)用程序狀態(tài)的計(jì)數(shù)部分的更改。
這種分離讀寫(xiě)問(wèn)題的方法在這個(gè)簡(jiǎn)單的基于任務(wù)的應(yīng)用程序的可維護(hù)性方面似乎非常令人滿(mǎn)意(好吧,所以你的任務(wù)是將顯示數(shù)量抽到100 ......無(wú)論如何),僅使用這種方法來(lái)處理大規(guī)模的e-商務(wù)應(yīng)用可能會(huì)成為一場(chǎng)噩夢(mèng)。你可以想象在著陸頁(yè)上有許多“狀態(tài)處理函數(shù)”改變了同一個(gè)狀態(tài)(例如,單擊按鈕A將切換狀態(tài)值.A,在輸入B中鍵入文本將同時(shí)更新?tīng)顟B(tài)值.B和state.A,從api獲取數(shù)據(jù)將在完成時(shí)更新state.B和state.C的值,依此類(lèi)推)。我們需要一種方法來(lái)管理一個(gè)數(shù)據(jù)模型的變異方式和時(shí)間。
Flux 模式 Redux
Flux模式通過(guò)提供狀態(tài)突變的明確性來(lái)解決這個(gè)問(wèn)題。我們來(lái)看一下通量模式下的典型數(shù)據(jù)流。
Flux模式中的數(shù)據(jù)流示例
狀態(tài)改變的明確性通過(guò)以下方式實(shí)現(xiàn):
- state只能通過(guò)調(diào)度程序進(jìn)行改變,而不是任意的“狀態(tài)處理程序”
- 要使調(diào)度程序改變狀態(tài),唯一的方法是發(fā)出一個(gè)動(dòng)作
- 如此確切地說(shuō),對(duì)于一個(gè)視圖來(lái)改變一個(gè)狀態(tài),唯一的方法是發(fā)出一個(gè)動(dòng)作(或者說(shuō)Redux-ly,發(fā)出一個(gè)動(dòng)作)
因此,通過(guò)監(jiān)視操作及其包含的信息,整個(gè)應(yīng)用程序的數(shù)據(jù)變異在我們的控制之下(何時(shí)以及如何更改)。
總結(jié)
我們經(jīng)歷了從古老的jQuery到今天強(qiáng)大的Web開(kāi)發(fā)工具之旅,如Angular,React,Vue。我們將Web應(yīng)用程序剖析為View層和Model層,并探索管理它們之間信息流的方法。雙向綁定采用MVVM模式,其中View通過(guò)ViewModel與模型緊密綁定,從而允許每個(gè)View直接讀取和更新模型的相應(yīng)部分。單向綁定借用了CQRS的設(shè)計(jì)原則,將寫(xiě)操作與讀操作分開(kāi),我們自己有意識(shí)地實(shí)現(xiàn)了2個(gè)操作。Flux模式進(jìn)一步推動(dòng)了這一概念,將數(shù)據(jù)模型的變異限制為僅通過(guò)調(diào)度操作,從而通過(guò)密切監(jiān)視這些操作來(lái)控制整個(gè)app狀態(tài)。
因此,下次我們可以停一下,并在編碼之前考慮下構(gòu)建應(yīng)用程序的方法。
總結(jié)
以上是生活随笔為你收集整理的javascript设计模式_Javascript 前端设计模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python打包成exe_【Python
- 下一篇: windows。forms.timer设