麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 網站 > 優化推廣 > 正文

深入分析Web應用程序前端的組件化

2024-04-26 14:21:29
字體:
來源:轉載
供稿:網友

基本思路
1. 為什么要做組件化?
無論前端也好,后端也好,都是整個軟件體系的一部分。軟件產品也是產品,它的研發過程也必然是有其目的。絕大多數軟件產品是追逐利潤的,在產品目標確定的情況下,成本有兩個途徑來優化:減少部署成本,提高開發效率。
減少部署成本的方面,業界研究得非常多,比如近幾年很流行的“去IOE”,就是很典型的,從一些費用較高的高性能產品遷移到開源的易替換的產品集群,又比如使用Linux + Mono來部署.net應用,避開Windows Server的費用。
提高開發效率這方面,業界研究得更多,主要途徑有兩點:加快開發速度,減少變更代價。怎樣才能加快開發速度呢?如果我們的開發不是重新造輪子,而是每一次做新產品都可以利用已有的東西,那就會好很多。怎樣才能減少變更代價呢?如果我們能夠理清模塊之間的關系,合理分層,每次變更只需要修改其中某個部分,甚至不需要修改代碼,僅僅是改變配置就可以,那就更好了。
我們先不看軟件行業,來看一下制造行業,比如汽車制造業,他們是怎么造汽車的呢?造汽車之前,先設計,把整個汽車分解為不同部件,比如輪子,引擎,車門,座椅等等,分別生產,最后再組裝,所以它的制造過程可以較快。如果一輛汽車輪胎被扎破了,需要送去維修,維修的人也沒有在每個地方都修一下,而是只把輪胎拆下來修修就好了,這個輪胎要是實在壞得厲害,就干脆換上個新的,整個過程不需要很多時間。
席德梅爾出過一款很不錯的游戲,叫做《文明》(Civilization),在第三代里面,有一項科技研究成功之后,會讓工人工作效率加倍,這項科技的名字就叫做:可替換部件(Replacement Parts)。所以,軟件行業也應當引入可替換的部件,一般稱為組件。
2. 早期的前端怎么做組件化的?
在服務端,我們有很多組件化的途徑,像J2EE的Beans就是一種。組件建造完成之后,需要引入一些機制來讓它們可配置,比如說,工作流引擎,規則引擎,這些引擎用配置的方式組織最基礎的組件,把它們串聯為業務流程。不管使用什么技術、什么語言,服務端的組件化思路基本沒有本質差別,大家是有共識的,具體會有服務、流程、規則、模型等幾個層次。
早期展示層基本以靜態為主,服務端把界面生成好,瀏覽器去拿來展示,所以這個時期,有代碼控制的東西幾乎全在服務端,有分層的,也有不分的。如果做了分層,大致結構就是下圖這樣:
2016526110515856.png (542×379)

這個圖里,JSP(或者其他什么P,為了舉例方便,本文中相關的服務端技術都用Java系的來表示)響應瀏覽器端的請求,把HTML生成出來,跟相關的JavaScript和CSS一起拿出去展示。注意這里的關鍵,瀏覽器端對界面的形態和相關業務邏輯基本都沒有控制權,屬于別人給什么就展示什么,想要什么要先提申請的尷尬局面。
這個時期的Web開發,前端的邏輯是基本可忽略的,所以前端組件化方式大同小異,無論是ASP還是JSP還是其他什么P,都可以自定義標簽,把HTML代碼和行間邏輯打包成一個標簽,然后使用者直接放置在想要的地方,就可以了。
在這一時代,所謂的組件化,基本都是taglib這樣的思路,把某一塊界面包括它的業務邏輯一起打成一個端到端的組件,整個非常獨立,直接一大塊從界面到邏輯都有,而且邏輯基本上都是在服務端控制,大致結構如下圖所示。
2016526110550838.png (545×384)

3. SPA時代,出現了新問題
自從Web2.0逐漸流行,Web前端已經不再是純展示了,它逐漸把以前在C/S里面做的一些東西做到B/S里面來,比如說Google和微軟的在線Office,這種復雜度的Web應用如果還用傳統那種方式做組件化,很顯然是行不通的。
我們看看之前這種組件化的方式,本質是什么?是展現層跟業務邏輯層的隔離,后端在處理業務邏輯,前端純展現。如果現在還這么劃分,就變成了前端有界面和邏輯,后端也有邏輯,這就比較亂了。我們知道,純邏輯的分層組件化還是比較容易的,任何邏輯如果跟展現混起來,就比較麻煩了,所以我們要把分層的點往前推,推到也能把單獨的展現層剝離出來。
如下圖所示,因為實際上HTML、CSS、JavaScript這些都逐漸靜態化,所以不再需要把它們放在應用服務器上了,我們可以把它們放在專門的高性能靜態服務器上,再進一步發展,就可以是CDN(Content Delivery Network,內容分發網絡)。前端跟后端的通信,基本都是通過AJAX來,也會有一些其他的比如WebSocket之類,總之盡量少刷新了。
2016526110616889.png (538×379)

在這張圖里面可以看到,真正的前端已經形成了,它跟應用服務器之間形成了天然的隔離,所以也能夠很獨立地進行一些發展演進。
現在很多Web程序在往SPA(單頁面程序,Single Page Application)的方向發展,這類系統通常比較類似傳統的C/S程序,交互過程比較復雜,因此它的開發過程也會遇到一些困難。
那為什么大家要做SPA呢?它有很多明顯的好處,最核心的優勢就是高效。這個高效體現在兩個方面:一是對于用戶來說,這種方式做出來的東西體驗較好,類似傳統桌面程序,對于那些需要頻繁操作的行業用戶,有很大優勢。二是運行的效率較高,之前集成一些菜單功能,可能要用iframe的方式引入,但每個iframe要獨立引入一些公共文件,服務器文件傳輸的壓力較大,還要初始化自己的一套內存環境,比較浪費,互相之間也不太方便通信,一般要通過postMessage之類的方式去交互。
有了SPA之后,比如一塊界面,就可以是一個HTML片段,用AJAX去加載過來處理之后放到界面上。如果有邏輯的JavaScript代碼,也可以用require之類的異步加載機制去運行時加載,整體的思路是比較好的。
很多人說,就以這樣的需求,用jQuery再加一個異步js加載框架,不是很足夠了嗎?這兩個東西用得好的話,也是能夠解決一些問題的,但它們處理的并不是最關鍵的事情。在Web體系中,展現層是很天然的,因為就是HTML和CSS,如果只從文件隔離的角度,也可以做出一種劃分的方式,邏輯放在單獨的js文件里,html內部盡量不寫js,這就是之前比較主流的前端代碼劃分方式。
剛才我們提到,SPA開發的過程中會遇到一些困難,這些困難是因為復雜度大為提升,導致了一些問題,有人把這些困難歸結為純界面的復雜度,比如說,控件更復雜了之類,沒有這么簡單。問題在于什么呢?我打個比方:我們在電腦上開兩個資源管理器窗口,瀏覽到同一個目錄,在一個目錄里把某個文件刪了,你猜猜另外一個里面會不會刷新?
毫無疑問,也會刷新,但是你看看你用的Web頁面,如果把整個復雜系統整合成單頁的,能保證對一個數據的更新就實時反饋到所有用它的地方嗎?怎么做,是不是很頭疼?代碼組織的復雜度大為提高,所以需要做一些架構方面的提升。
4. 架構的變更
提到架構,我們通常會往設計模式上想。在著名的《設計模式》一書中,剛開始就講了一種典型的處理客戶端開發的場景,那就是MVC。
傳統的MVC理念我們并不陌生,因為有Struts,所以在Web領域也有比較經典的MVC架構,這里面的V,就負責了整個前端的渲染,而且是服務端的渲染,也就是輸出HTML。如下圖所示:
2016526110644888.png (540×352)

在SPA時代,這已經不合適了,所以瀏覽器端形成了自己的MVC等層次,這里的V已經變成客戶端渲染了,通常會使用一些客戶端的HTML模版去實現,而模型和控制器,也相應地在瀏覽器端形成了。
2016526110701745.png (540×376)

我們有很多這個層面的框架,比如Backbone,Knockout,Avalon,Angular等,采用了不同的設計思想,有的是MVC,有的是MVP,有的是MVVM,各有其特點。
以Angular為例,它推薦使用雙向綁定去實現視圖和模型的關聯,這么一來,如果不同視圖綁定在同一模型上,就解決了剛才所說的問題。而模型本身也通過某種機制,跟其他的邏輯模塊進行協作。
這種方式就是依賴注入。依賴注入的核心理念就是通過配置來實例化所依賴的組件。使用這種模式來設計軟件架構,會犧牲一些性能,在跟蹤調試的便利性等方面也會有所損失,但換來的是無與倫比的松耦合和可替代性。
比如說,這些組件就可以單獨測試,然后在用的時候隨手引入,毫無壓力。對于從事某一領域的企業來說,光這一條就足以吸引他在上面大量投入,把所有不常變動領域模型的業務代碼都用此類辦法維護起來,這是一種財富。
5. MV*框架的基本原理
如果我們來設計Angular這么一個前端框架,應當如何入手呢?很顯然,邏輯的控制必須使用JavaScript,一個框架,最本質的事情在于它的邏輯處理方式。
我們的界面為什么可以多姿多彩?因為有HTML和CSS,注意到這兩種東西都是配置式的寫法,參照后端的依賴注入,如果把這兩者視為跟Spring框架中一些XML等同的配置文件,思路就豁然開朗了。
與后端不同的是,充當前端邏輯工具的JavaScript不能做入口,必須掛在HTML里才能運行,所以出現了一個怪異的狀況:邏輯要先掛在配置文件(HTML)上,先由另外的容器(瀏覽器或者Hybird的殼)把配置文件加載起來,然后才能從某個入口開始執行邏輯。好消息是,過了這一步,邏輯層就開始大放異彩了。
從這個時候開始,框架就啟動了,它要做哪些事情呢?
初始化自身(bootstrap)
異步加載可能尚未引入的JavaScript代碼(require)
解析定義在HTML上的規則(template parser)
實例化模型(scope)
創建模型和DOM的關聯關系(binding, injection)
這些是主線流程,還有一些支線,比如:
解析url的search字符串,恢復狀態(route)
加載HTML部件模板(template url)
部件模板和模型的關聯(binding)
6. 如何做組件化
6.1. HTML的組件化
SPA的一個典型特征就是部分加載,界面的部件化也是其中比較重要的一環。界面片段在動態請求得到之后,借助模版引擎之類的技術,經過某種轉換,放置到主界面相應的地方。所以,從這個角度來看,HTML的組件化非常容易理解,那就是界面的片段化和模板化。
6.2. JavaScript的組件化
JavaScript這個部分有好幾個發展階段。
早期的共享文件,把公共功能的代碼提出出來,多個頁面共用
動態引用,消滅全局變量
在某些框架上進一步劃分,比如Angular里面又分為provider,service,factory,controller
JavaScript組件化的目標是什么呢,是清晰的職責,松耦合,便于單元測試和重復利用。這里的松耦合不僅體現在js代碼之間,也體現在js跟DOM之間的關系,所以像Angular這樣的框架會有directive的概念,把DOM操作限制到這類代碼中,其他任何js代碼不操作DOM。
2016526110737109.png (541×382)

如上圖所示,總的原則是先分層次,層內再作切分。這么做的話,不再存在之前那種端到端組件了,使用起來沒有原先那么方便,但在另外很多方面比較好。
6.3. CSS的組件化
這方面,業界也有很多探索,比如LESS,SASS,Stylus等。為什么CSS也要做組件化呢?傳統的CSS是一種扁平的文本結構,變更成本較高,比如說想要把結構從松散改緊湊,需要改動很多。如果把實際使用的CSS只當作輸出結果,而另外有一種適合變更的方式當作中間過程,這就好多了。比如說,我們把一些東西定義成變量,每個細節元素使用這些變量,當需要整體變更的時候,只需修改這些變量然后重新生成一下就可以了。
以上,我們討論了大致的Web前端開發的組件化思路,后續將闡述組件化之后的協作過程和管控機制。

管控平臺
1. HTML片段
我們為什么要管理HTML片段?因為有界面要用它們,當這些片段多了之后,需要有個地方來管理起來,可以檢索、預覽它們,還能看到大致描述。
這應該是整個環節中一個相對很簡單的東西,照理說,有目錄結構,然后剩下的就是單個的HTML片段文件了,這就可以解決存儲和檢索的問題了,但我們還要考慮更多。
已有的HTML片段,如何被使用呢?這肯定是一種類似include的方式,通過某種特殊標簽(不管是前端還是后端的方式)把這些片段引用進來,這時候就有了第一個問題:
假設有界面A和界面B同時引用了片段C,在某個開發人員修改片段C內容的時候,他如何得知將會影響到界面A和B呢?一個比較勉強的方式是全項目查找,但這在很多情況下是不夠的。
如果我們的HTML片段是作為獨立的公共庫存在的,它已經不能通過項目內查找去解決這一問題了,因為不管A還是B,只要他不處于片段C的項目空間,就無從追尋。
這時候很多人會問兩個問題:
跨項目的界面片段重用,意義在哪里?
如果我們的產品是針對一個小領域,它的復雜度根本不需要劃分多個項目部分來協作完成。設想場景是面對很大的行業,各項目都是子產品,將來可能是其中若干個聯合部署,這時候,保持其中的一致性是非常重要的。比如我們有個基本配置界面,在多個子產品中都要用,如果各自開發一個,其操作風格很可能就是不一致的,給人的印象就是不專業。所以會需要把常見的界面片段都歸集起來,供業務方挑選使用。
修改C,只提供說明,但是不通知A和B,不實時更新他們的版本,然后自行決定怎樣升級,如何?
這會有一個問題,每次有小功能升級的時候,代碼是最容易同步合并的,所以才會有“持續集成”這個概念,如果是一直伴隨升級,總要比隔一個大階段才升級好,升級成本應盡量分攤到平時,就像農婦養小豬,小豬每天長一點,每天都抱來抱去,不覺得吃力,即使長大了也還能抱得動。
現在問題就很明確了,一定要有一種方式來把這個依賴關系管理起來,很顯然,已有的版本庫是肯定管不了這些的,所以只能在外圍做一些處理。
我們建立一個管理平臺,除了管理實體文件的版本,還管它們之間的關系。具體這個關系如何收集整理,有兩種方式:手動配置,代碼分析。
手動配置是比較土的方式,開發人員每提交一個文件,就去這系統上手動配置它的依賴關系。代碼分析的話,要在每次提交文件的時候解析文件的包含規則,找出確切的文件。這兩者各有利弊,前者比較笨,但容易做,后者對代碼格式的要求比較高,要考慮的情況較多。
我們的界面往往不是那么簡單,HTML片段也可能有層次的,舉例來說:
界面A里面包含了片段B,但是片段B自身又包含了片段C,所以這個依賴關系也是有層級的,需要在設計的時候一并考慮。
2. JavaScript模塊
JavaScript代碼的管理,比HTML片段的狀況好一些,因為業界很多這方面的解決方案。但它們還是沒有解決當依賴項產生變更的時候反向通知的問題。
所以我們還是得像HTML片段一樣,把它們的依賴關系都管理到平臺里。于是,每個JavaScript模塊都顯式配置了自己所依賴的其他模塊,通過這種單向關系,形成了一套完整的視圖。
在JavaScript模塊的代碼實現中,我們是不提倡直接寫依賴關系的。很多通用規范,比如AMD,往往建議我們這樣寫模塊:

JavaScript Code復制內容到剪貼板
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄色毛片免费视频 | 久久99综合 | 国产精品影视 | 日韩精品中文字幕一区二区 | 中文字幕亚洲欧美 | 国产91九色 | 一级尻逼视频 | 日日爱影院| 精品国产96亚洲一区二区三区 | 在线 日本 制服 中文 欧美 | 成人区精品一区二区婷婷 | 日本欧美一区二区三区在线观看 | 午夜精品在线视频 | 香蕉成人在线观看 | 福利在线国产 | 国产啊v在线观看 | 国产一区二区三区撒尿在线 | 在线天堂中文在线资源网 | 午夜神马福利视频 | 九九热九九热 | 91 在线观看| v11av在线视频成人 | 久久草在线视频国产 | 一色屋任你操 | 亚洲人成免费 | 国产毛片自拍 | www久久久久久 | a级在线 | 91午夜免费视频 | 国产 一区 | 色妹子久久 | 成年毛片| 一边吃奶一边摸下娇喘 | 麻豆国产一区 | 亚洲国产精品久久久久久久久 | 55夜色66夜色国产精品视频 | 精品国产一区二区三区久久久蜜月 | 黄色毛片a级 | 欧美xxxxx视频 | 国产女厕一区二区三区在线视 | 久久国产免费视频 |