自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入聊聊 JavaScript 框架

開發(fā) 前端
通過回顧 JS 框架的發(fā)展歷程,和大家一起探討框架的本質(zhì)以及 JS 框架不斷變化背后的驅(qū)動力。

 

一、前言

關(guān)于 JS 框架部分能聊的內(nèi)容比較多,我相信大家對某個框架的使用、原理等知識是比較容易找到資料來學習的,鑒于此這部分內(nèi)容將會從另一個視角出發(fā):通過回顧 JS 框架的發(fā)展歷程,和大家一起探討框架的本質(zhì)以及 JS 框架不斷變化背后的驅(qū)動力。正所謂「鑒往知來」,希望大家能對 JS 框架有更全面的認知,能夠把握變化背后不變的邏輯,更好的應(yīng)對未來新的變化。

二、什么是框架

在講清楚一件事情之前,我們需要先準確定義它,這一部分我們先定義清楚什么是框架以及什么是 JS 框架。

先看一個通用意義上「框架」的的定義:

框架(framework)是一個框子——指其約束性,也是一個架子——指其支撐性。是一個基本概念上的結(jié)構(gòu),用于去解決或者處理復(fù)雜的問題。

個人非常喜歡這個定義,簡潔而準確,框架的核心就是「約束性」和「支撐性」。

如何理解「約束性」

框架是解決復(fù)雜領(lǐng)域問題的系統(tǒng)性方法,對于復(fù)雜問題而言,往往缺失「銀彈」,大家看問題的角度會有差異,每個框架背后都有自己的理念,當你選擇某個框架就需要遵循它的邏輯和規(guī)則,在規(guī)則之內(nèi)解決問題,這是「約束性」。

如何理解「支撐性」

復(fù)雜問題通??梢圆鸾獬梢幌盗行栴},問題的整體解法則是如何解決它們中的所有或者部分,框架的「支撐性」體現(xiàn)在它提供了問題的定義和一系列解決問題的方法,基于它能夠?qū)⑨槍Ω鱾€子問題的解法更加有序的組織起來,最終形成整體的解法,「支撐性」即有序組織。

如何定義 JS 框架

解決前端特定領(lǐng)域問題的代碼組織框架,約束性體現(xiàn)為需要基于約定的結(jié)構(gòu)來組織代碼,支撐性體現(xiàn)為基于框架內(nèi)置的機制或能力高效的實現(xiàn)功能。

按這個定義 JS 框架覆蓋了方方面面,例如解決 Web 整體實現(xiàn)的前端應(yīng)用框架、游戲引擎框架、后端服務(wù)框架等等,但需要指出的是大家通常認為的 JS 框架指的是前端應(yīng)用框架,這也是這部分文章介紹的重點。再順道說一下框架和庫的區(qū)別,JS 庫通常是解決系統(tǒng)構(gòu)建中某個子問題的代碼實現(xiàn),它和框架的關(guān)系往往是被調(diào)用者(庫)和調(diào)用者(框架)的關(guān)系。

JS 框架要解決什么問題

一直以來 Web 前端技術(shù)發(fā)展非常迅速,新技術(shù)更是層出不窮,但這些技術(shù)發(fā)展的背后始終圍繞著一條主線——如何更高效的構(gòu)建 Web 人機交互界面。復(fù)雜 Web 應(yīng)用的構(gòu)建首先要考慮的是如何更合理的組織代碼,這關(guān)系到協(xié)作效率、可維護性、可擴展性等等,本質(zhì)是對生產(chǎn)效率的持續(xù)追求。再進一步拆解來看,我們的問題域主要包括視圖構(gòu)建、視圖狀態(tài)管理、用戶交互、服務(wù)端交互等,在復(fù)雜場景下,隨著表達內(nèi)容和人機交互多樣性的增加,如何兼具效率、體驗等具有較大的挑戰(zhàn),而這也恰恰是 JS 框架所要解決的問題。

三、JavaScript 框架的發(fā)展

從 Tim Berners-Lee 在 1989 年的提議開始到 2019 年 3 月 12 日,WWW 迎來了它的 30 歲生日, 這 30 年無疑是人類科技進步最快的 30 年,Web 也從最初的提議變成了人類社會的基礎(chǔ)設(shè)施。從技術(shù)角度看,Web 在滿足人們越來越多線上化需求的同時,Web 前端也在變得越來越復(fù)雜:更強大的功能、更豐富多樣的內(nèi)容、更復(fù)雜的運行環(huán)境等等,從最初的小制作到現(xiàn)在的大規(guī)模復(fù)雜應(yīng)用,不斷推動開發(fā)者們尋求更高效的前端構(gòu)建方式,這也正是前端技術(shù)快速發(fā)展背后的動力。

從 Web 前端的形式看,大致可以將 30 年劃分為三個時期:只讀 Web 時期、可交互 Web 時期、Web 應(yīng)用時期。

只讀 Web 時期(1990~2000),Web 的核心功能是圖文內(nèi)容的線上化,只有少數(shù)用戶使用并且只能瀏覽內(nèi)容。從技術(shù)角度看,這個時代是 Web 標準的起源階段,同時由于單一的內(nèi)容表現(xiàn)需求,尚不存在誕生 JS 框架的土壤。

可交互 Web 時期(2000~2010),越來越多的人通過 Web 滿足需求,Web 內(nèi)容形態(tài)也從單一的只讀圖文展示演變成功能豐富的可交互形式,這種演變也促使 Web 開發(fā)領(lǐng)域演化出新的社會分工角色 —— Web 前端工程師。與此同時,有了 JS 框架的土壤之后,形形色色的前端庫和框架也逐漸誕生,但此時它們更多專注于解決某個方向的問題:例如兼容性或者組件化等等;

Web 應(yīng)用時期(2010 至今),對于很多行業(yè)而言,Web 服務(wù)已經(jīng)屬于基礎(chǔ)設(shè)施,大多數(shù)人已經(jīng)依賴 Web 能力來滿足需求。為了追求更好的體驗以及更高的效率,Web 服務(wù)的構(gòu)建也像客戶端應(yīng)用靠齊,JS 框架的發(fā)展則逐步覆蓋到高效構(gòu)建 Web 前端相關(guān)的整個領(lǐng)域。

只讀 Web 時期

1989 年,為了讓學校和科研機構(gòu)間能夠更高效的共享信息,Tim Berners-Lee 提出了「WWW」提議并且在次年發(fā)明了第一個 web 瀏覽器 - WorldWideWeb。而在隨后的 1991 年,HTML 的第一個版本 - 「HTML Tags」誕生,目標是文本、圖片等信息的在線展示以及互聯(lián)互通。第一個商業(yè)化瀏覽器的誕生則是在 1993 年,來自 Netscape 的 Netscape Navigator。W3C 的誕生則要到 1994 年,由 Tim Berners-Lee 創(chuàng)辦。

直至 1995 年,Web 上所有內(nèi)容仍然是純靜態(tài),但隨著 Web 需求的快速增長,逐步有些場景需要用戶交互的能力,因此在 1995 年 9 月,Netscape 發(fā)布了 Javascript 的第一個版本 - LiveScript,并在 3 個月后改名為 JavaScript。

這一時期除了 WWW 的起源之外,另一件值得一提的事是史上第一次「瀏覽器大戰(zhàn)」,在這場大戰(zhàn)中,Netscape 在前期以先發(fā)優(yōu)勢拿下 80% 的市場份額,微軟 IE 則后來居上,以和 Windows 捆綁的方式逐步贏回優(yōu)勢,到 2000 年微軟 IE 市場份額占比超過 80%。有意思的是在第二次「瀏覽器大戰(zhàn)」中,IE 又敗下陣來,后起之秀 Chrome 借著更高的性能、更好的標準兼容性以及更快的迭代速度攻城掠地,至 2019 年占領(lǐng) 70% 以上的市場份額,IE 市場份額則降至 10% 左右。對開發(fā)者而言,「瀏覽器大戰(zhàn)」中由于各方對標準的支持程度有差異,甚至為了實現(xiàn)差異化會特意引入新特性,因此開發(fā)者需要投入大量的工作來解決兼容性問題,這也為后續(xù)的 Javascript 庫/框架的產(chǎn)生埋下伏筆。

可交互 Web 時期

進入 2000 年,互聯(lián)網(wǎng)加速發(fā)展,隨著電商、社交等新平臺的推出,越來越多用戶加入互聯(lián)網(wǎng),此時的互聯(lián)網(wǎng)用戶群已經(jīng)逐步由最初的小眾用戶發(fā)展為大眾用戶,各大平臺也越來越重視 Web 用戶體驗,開始在 Web 用戶交互方面增加資源投入。另一方面,瀏覽器通過持續(xù)的升級也具備更多的能力來支撐更好的用戶交互,例如異步請求能力的引入等。以上需求和供給兩側(cè)為 JavaScript 庫/框架的發(fā)展提供了土壤。

這個階段,Web 主流的渲染方式是后端渲染,JavaScript 的重點工作是對頁面實現(xiàn)局部交互能力,例如表單驗證、異步提交、圖片輪播、Tab 切換等等,這一時期的 JavaScript 庫/框架圍繞完善用戶交互相關(guān)基礎(chǔ)設(shè)施發(fā)展,主要包括組件化、兼容性以及工具庫。

組件化

與其他編程語言中的人機交互界面構(gòu)建能力相比,在 Web 中缺乏豐富、標準化的 UI 組件庫。因此在這個階段涌現(xiàn)出一批以組件化為主的框架,其中比較有代表性的是 DoJo(2005)、ExtJS(2007)。這些框架的特點是提供了 All in One 的組件庫,組件類型豐富,當然交互形式也非常厚重,典型的桌面客戶端風格。

兼容性

「瀏覽器大戰(zhàn)」的大背景下,瀏覽器廠商各自為戰(zhàn),于是不論是 BOM、DOM 還是 JavaScript 層面都需要做大量的兼容性工作,于是 jQuery(2006) 便在這一背景下誕生。jQuery 一方面解決了大量兼容性問題,另一方面提供了非常便捷的基于 CSS 選擇符的 DOM 獲取方式以及 DOM 操作能力,此外還重新封裝了異步請求的 API,這些能力在以命令式(imperative)編程范式為主的時期是非常高頻的操作,因此 jQuery 的出現(xiàn)大大提升了前端編程體驗和效率。

  1. <script> 
  2. $( "div span:first-child" ) 
  3.   .css( "text-decoration""underline" ) 
  4.   .hover(function() { 
  5.     $( this ).addClass( "sogreen" ); 
  6.   }, function() { 
  7.     $( this ).removeClass( "sogreen" ); 
  8.   }); 
  9. </script> 

當然,隨著 jQuery 很多能力從事實標準演進為正式標準,瀏覽器開始提供原生支持,再者前端編程模式從命令式向聲明式(declarative)演進,針對 DOM 的獲取與操作大大減少,jQuery 的使用率也隨之快速下降。此外,隨著 Chrome 在「瀏覽器大戰(zhàn)」中勝出,兼容性問題已經(jīng)有了非常大的改善,當然移動端除外。

工具庫

這一時期原生 JavaScript 僅支持一些較「原始」的編碼能力,對比其他成熟的編程語言而言在編程效率和體驗上都存在巨大差異,各類工具庫基于「原始」能力進行再封裝,能較大程度縮小差異。工具庫類的代表有 PrototypeJS(2005)、YUI(2006)、Mootools(2007),它們主要針對面向?qū)ο蟆⑹录?、異步請求、?shù)組操作等方面進行了封裝。

  1. /*PrototypeJS 代碼示例*/ 
  2. // 面向?qū)ο?/span> 
  3. var FirstClass = Class.create( { 
  4.     // The initialize method serves as a constructor 
  5.     initialize: function () { 
  6.         this.data = "Hello World"
  7.     } 
  8. }); 
  9.  
  10.  
  11. // 異步請求 
  12. Ajax.Request = Class.create( Ajax.Base, {  
  13.     // Override the initialize method 
  14.     initialize: function(url, options) {  
  15.         this.transport = Ajax.getTransport();  
  16.         this.setOptions(options);  
  17.         this.request(url);  
  18.     },  
  19.     // ...more methods add ...  
  20. }); 
  21. // DOM 與事件 
  22. $$('#items li').each( function(item) { 
  23.   item.observe('click', function(event) { 
  24.     doSomethingWith(event.target); 
  25.   }); 
  26. }); 
  27. // 數(shù)組遍歷 
  28. myArray.each(function(item) { 
  29.   // Your code working on item here... 
  30. }); 

當然,按上述三個方面并不是能夠特別準確的去給眾多 JavaScript 庫/框架進行歸類,很多采用分層以及可拆解的設(shè)計,能夠同時兼顧各個方面的需求,就如以下 YUI 的整體架構(gòu)。

Web 應(yīng)用時期

最近 10 年,隨著前端投入的持續(xù)增加,前端團隊的話語權(quán)也越來越重,同時大家也在持續(xù)探索更高效的前端研發(fā)模式,例如這期間逐步發(fā)展的前后端分離、前端工程化等,尤其是前后端分離的協(xié)作模式給前端開發(fā)帶來了更高的自由度和空間,前端的工作職責從最初的局部動態(tài)化、局部可交互逐步擴張到整站的前端構(gòu)建,這種變化直接帶來了至少兩方面的挑戰(zhàn),一是如何解決多人協(xié)作問題,針對規(guī)模越來越大的前端工程,多人協(xié)作是必然,而協(xié)作的關(guān)鍵是明確的分工和合作;二是代碼的可維護性問題,在前端框架出現(xiàn)之前,局部動態(tài) UI 通常采用前端模板加命令式編程范式來實現(xiàn),這種方式對于輕量的 UI 構(gòu)建是可接受的,但在應(yīng)對大規(guī)模前端功能構(gòu)建時,很容易寫出可維護性極差的代碼。

這些是構(gòu)建 GUI 應(yīng)用時的典型問題,在 Web 前端出現(xiàn)之前的其他平臺的 GUI 構(gòu)建中也有類似的問題,解決的方式是引入合適的架構(gòu)模式,將看似亂做一團的代碼分門別類,各自關(guān)注各自職責范圍內(nèi)的工作,這些架構(gòu)模式包括 MVC、MVP、MVVM 等等,背后的核心理念是「關(guān)注點分離」。在 Web 前端面臨類似的挑戰(zhàn)時,自然而然的是借鑒傳統(tǒng) GUI 構(gòu)建的經(jīng)驗,通過框架的形式引入新的架構(gòu)模式來解決,在這一背景下前端也逐步出現(xiàn)了真正意義上的「框架」。

2010 年發(fā)布的 Backbone.js 引入了視圖和數(shù)據(jù)模型的概念,但它并不是標準的 MVC 實現(xiàn),沒有明確的控制器概念,而是由視圖承擔部分控制器職責,但這些并不重要,重要的是前端 GUI 構(gòu)建有了新的思路和選擇。另外一點值得一提的是,Backbone.js 仍然采用了命令式編程范式,這在前端 GUI 構(gòu)建中與后續(xù)逐漸流行的聲明式編程范式而言,編程效率上會有明顯的差距。

  1. /*Backbone.js 代碼示例(部分)詳細前往 https://backbonejs.org/docs/todos.html*/ 
  2. var AppView = Backbone.View.extend({ 
  3.     el: $("#todoapp"), 
  4.     statsTemplate: _.template($('#stats-template').html()), 
  5.     events: { 
  6.       "keypress #new-todo":  "createOnEnter"
  7.     }, 
  8.     initialize: function() { 
  9.       this.input = this.$("#new-todo"); 
  10.       this.listenTo(Todos, 'add'this.addOne); 
  11.       this.footer = this.$('footer'); 
  12.       this.main = $('#main'); 
  13.  
  14.  
  15.       Todos.fetch(); 
  16.     }, 
  17.     render: function() { 
  18.       var done = Todos.done().length; 
  19.       var remaining = Todos.remaining().length; 
  20.  
  21.  
  22.       if (Todos.length) { 
  23.         this.main.show(); 
  24.         this.footer.show(); 
  25.         this.footer.html(this.statsTemplate({done: done, remaining: remaining})); 
  26.       } else { 
  27.         this.main.hide(); 
  28.         this.footer.hide(); 
  29.       } 
  30.  
  31.  
  32.       this.allCheckbox.checked = !remaining; 
  33.     }, 
  34.     addOne: function(todo) { 
  35.       var view = new TodoView({model: todo}); 
  36.       this.$("#todo-list").append(view.render().el); 
  37.     }, 
  38.     clearCompleted: function() { 
  39.       _.invoke(Todos.done(), 'destroy'); 
  40.       return false
  41.     } 
  42.   }); 
  43.   var App = new AppView; 
  44. }); 

同年 AngularJS 發(fā)布第一個版本,和 Backbone 的最大不同,一方面它充分借鑒了微軟 WPF 的 MVVM 架構(gòu)模式,引入 VM 概念,支持視圖和數(shù)據(jù)的雙向綁定;另一方面它采用了聲明式的視圖構(gòu)建模式,大大減少了原生 DOM 操作。此外,AngularJS 提供的功能非常全面(路由管理、組件化、視圖模板、狀態(tài)管理、后端交互、事件管理、動畫等),基本達到開箱即用的狀態(tài),使用它能夠非常高效的構(gòu)建 SPA 類應(yīng)用。當然,它的缺點也非常明顯,引入了過多的概念導(dǎo)致上手成本非常高,此外它的「大而全」是優(yōu)點的同時也是缺點,對于非 SPA 類 Web 場景而言過于臃腫。總體而言,AngularJS 對于解決特定場景中的前端架構(gòu)問題是非常有效的,能夠非常顯著的提升前端協(xié)作效率。

在 AngularJS 發(fā)布后的第四年和第五年 React 以及 Vue 陸續(xù)發(fā)布,React 發(fā)布時的目標是優(yōu)化視圖構(gòu)建,但隨著整個生態(tài)的完善,React 已經(jīng)有充分的能力支撐大規(guī)模的前端應(yīng)用開發(fā)。Vue 則借鑒了 AngularJS 的架構(gòu)模式,并且同樣采用了聲明式的視圖構(gòu)建方式。相比 AngularJS,React 和 Vue 的最大優(yōu)勢是更加的輕量和靈活,能夠適應(yīng)更多的場景,此外上手成本也要低得多,尤其是 Vue,這也讓后兩者在最近幾年能夠碾壓 AngularJS。

縱觀最近 10 年前端框架的變遷,有兩點得以驗證,一是聲明式編程范式相比命令式在前端 GUI 構(gòu)建中的成功,背后的關(guān)鍵邏輯是研發(fā)效率的顯著優(yōu)勢;二是漸進式框架相比 All in One 「全家桶」式框架的成功,漸進式框架有更好的靈活性,面對前端場景的變化有更強的適應(yīng)性。

四、鑒往知來

以上走馬觀花的概覽了最近 30 年前端框架的發(fā)展,整體演進脈絡(luò)是清晰的,Web 前端從無到有,從有到逐步走向?qū)I(yè)化,技術(shù)上的關(guān)注點和挑戰(zhàn)也在不斷變化,從解決最初的 DOM 操作效率、兼容性、組件化等問題,再到提升大規(guī)模前端的協(xié)作效率等,那些能夠準確把握并且有效解決問題的框架/庫都獲得了成功,至少是階段性的成功。順著這條脈絡(luò)往前看,前端框架的后續(xù)發(fā)展仍然取決于前端領(lǐng)域在未來將面臨何種挑戰(zhàn)。

Web vs Native

在智能手機普及的初期,各平臺的移動端也曾經(jīng)以 Web 為主,當時各種 Web 服務(wù)的 m 站是必備之一。隨著智能手機的普及,移動 APP 具備明顯的路徑、性能、能力等方面的優(yōu)勢,迅速成為移動化的首選。在這個過程中,Web 前端很大程度上淡出移動應(yīng)用的核心研發(fā)工作,后來隨著 hybrid 開發(fā)模式的成熟,Web 前端又逐步參與到一些移動應(yīng)用的開發(fā)中。再看未來,逐步由流量運營到以用戶運營為核心的時期,以 Native 為主導(dǎo)的模式預(yù)計仍然會是主流,而且用戶體驗變得更加重要,尤其是用戶長停留的應(yīng)用。在這一背景下,Web 和 Native 如何更好的協(xié)作,如何取長補短,在效率和體驗上能夠進一步突破天花板將是長期的挑戰(zhàn)。

智能終端

前面更多談?wù)摰氖?PC 端和移動端,隨著 5G 的完善和普及,IoT 會迎來加速發(fā)展,屆時在移動端和 PC 端兩端之外將會出現(xiàn)更多形式各異的終端,這類終端的 GUI 需求如何解決,是否可以采用 Web 技術(shù)來提效,現(xiàn)有 Web 框架在 IoT 設(shè)備上是否是最佳選擇?隨著 IoT 的爆發(fā),這些問題會是前端框架不得不考慮的問題。

低代碼化

另外一個看得見的趨勢是低代碼化(low/no code)的普及,不久的將來大量的模式化的 Web 開發(fā)工作極大可能將通過低代碼化的方式來解決,例如運營、管理類的平臺就是典型的模式化 Web 平臺,這類平臺在當前的前端研發(fā)工作中占有很大的比例,也是當前各類前端框架的重要應(yīng)用場景,一旦這類需求由低代碼化的方式來實現(xiàn),那么具體的實現(xiàn)使用何種框架將變得不那么重要。在這個背景下,很可能會誕生一些專有框架來更高效的解決低代碼化的領(lǐng)域問題。而通用類框架的場景會更多的集中在非模式化的場景中,在這類場景中對框架的靈活性、定制化等會有更高的要求。

責任編輯:張燕妮 來源: code秘密花園
相關(guān)推薦

2022-02-09 11:02:16

JavaScript前端框架

2009-06-18 10:23:03

Javascript 基本框架

2009-06-22 15:34:00

Javascript

2021-01-07 07:53:10

JavaScript內(nèi)存管理

2022-11-26 08:16:26

2019-07-23 15:04:54

JavaScript調(diào)用棧事件循環(huán)

2021-06-02 09:01:19

JavaScript 前端異步編程

2024-08-07 08:07:23

2019-12-04 10:13:58

Kubernetes存儲Docker

2011-06-03 13:48:18

JavaScript重構(gòu)

2024-05-11 11:18:21

Kafka監(jiān)控框架

2021-09-08 08:55:45

Javascript 高階函數(shù)前端

2021-09-06 08:26:08

JavaScript數(shù)獨 LeetCode

2022-02-23 09:03:29

JavaScript開發(fā)命名約定

2018-12-19 14:40:08

Redis高級特性

2015-12-24 09:48:40

JavaScriptthis指針深

2021-02-17 11:25:33

前端JavaScriptthis

2015-09-29 08:57:46

javascript對象

2020-04-16 18:04:07

JavaScript前端技術(shù)

2015-11-04 09:57:18

JavaScript原型
點贊
收藏

51CTO技術(shù)棧公眾號