摘要:它會檢測出最大靜態(tài)子樹就是不需要動態(tài)性的子樹并且從渲染函數(shù)中萃取出來。這樣在每次重渲染的時候,它就會直接重用完全相同的同時跳過比對。需要注意的是,中的操作必須是同步的,不可以存在異步操作的情況。
新增:哈哈,最近又推出了 vue 的文章,在這里放個鏈接~
手把手教你從零寫一個簡單的 VUE
感謝有人看我扯技術(shù),這篇文章主要介紹最近非?;鸬膙ue2前端框架的特點和vue2+vuex2+webpack2各種2的前后端同構(gòu)渲染架構(gòu)搭建流程,最后會附上代碼,文章想到啥寫啥,如果存在錯誤,或者大家有什么意見建議,歡迎大家指出來
Vue2 和 Vue1 的對比vue2出來之后,基本上逛論壇逛技術(shù)群都能看到各種文章,各種討論 ,一時間大家都在學習vue2了 ,我今年年初就開始接觸vue,最初也是在react ,angular,vue 之中對比選擇,最終選擇了vue,因為其對前端比較友好(使用正常的模板,而不是JSX)、概念及學習成本相對簡單(對于團隊開發(fā),引入技術(shù)必須要考慮其學習成本),下面介紹下我理解的vue2和vue1的不同之處 ,如有不足,歡迎補充:
1.引入了virtual Dom
在vue1中,數(shù)據(jù)和視圖的綁定流程是通過 Object.defineProperty將數(shù)據(jù)轉(zhuǎn)化為getter/setter,getter/setter中加入watcher,當對數(shù)據(jù)進行操作的時候,setter的watch被觸發(fā)重新計算,然后更新和這個數(shù)據(jù)有關(guān)聯(lián)的dom元素,這就是vue1的數(shù)據(jù)驅(qū)動視圖原理
在vue2中,數(shù)據(jù)的綁定和觸發(fā)和vue1相同,基本原理都是通過Object.defineProperty對數(shù)據(jù)加入"鉤子",以便在數(shù)據(jù)發(fā)生變化的時候得以響應,而在響應之后,不像vue1一樣直接更新dom元素,而是放入virtual Dom中,進行比對計算,然后對dom元素做相應的處理。下面是vue1和vue2的響應流程對比vue:
vue2:
關(guān)于virtual Dom: 虛擬dom最初是在react上面認識的,其實做的事情就是在js內(nèi)存中建立好dom的結(jié)構(gòu),然后再更新虛擬dom時做差異比對,將差異的地方真正更新到頁面中,做到最小化頁面的渲染。當然,也不是說對于所有情景,虛擬dom的性能都是最好的,畢竟比起直接操作dom元素,他還是需要在內(nèi)存中進行計算,因此對于少量的元素更新,可能其性能比起直接操作dom元素要差。當然虛擬dom的引入,不只是在性能方面的考慮,虛擬dom可以帶來編程的變化,比如你可以使用render方法直接創(chuàng)建新的節(jié)點,虛擬dom也是vue2可以進行服務端渲染的關(guān)鍵,由于虛擬dom是在內(nèi)存重點,vue2的ssr可以將虛擬dom直接生成html的字符串,從而實現(xiàn)ssr。除此之外,vue2 從模板到 virtuel-DOM 的編譯階段使用了一些高階優(yōu)化:
(1). 它會檢測出靜態(tài)的 class 名和 attributes 這樣它們在初始化渲染之后就永遠都不會再被比對。
(2). 它會檢測出最大靜態(tài)子樹 (就是不需要動態(tài)性的子樹) 并且從渲染函數(shù)中萃取出來。這樣在每次重渲染的時候,它就會直接重用完全相同的 virtual nodes 同時跳過比對。
這些高階優(yōu)化通常只會在使用 JSX 時通過 Babel plugin 來做,但是 vue2 即使在使用瀏覽器內(nèi)的編譯器時也能做到。
2.組件事件傳遞機制的改變,組件數(shù)據(jù)雙向綁定的去除
vue2組件廢除了$dispath/$broadcast父子組件的事件傳播方式,廢除了過濾器,props參數(shù)等的數(shù)據(jù)雙向綁定以及處理功能,說明作者希望使用者通過建立全局的狀態(tài)管理,事件管理機制,通過使用事件中心,允許組件自由交流,無論組件處于組件樹的哪一層,將狀態(tài)管理集中在一起處理,官方提供的vuex就是用來幾種管理狀態(tài)的。
3.服務端渲染 ssr:server-side-render
由于virtual dom的引入,使得vue的服務端渲染成為了可能,下面是官方 vue-server-renderer提供的渲染流程圖:
可以看出vue的server-side-render有三部分組成,一部分是頁面的源碼(source),還有node層的渲染部分和瀏覽器端的渲染部分。
source分為兩種entry point,一個是前端頁面的入口client entry,主要是實例化Vue對象,將其掛載到頁面中;另外一個是后端渲染服務入口server entry,主要是控服務端渲染模塊回調(diào),返回一個Promise對象,最終返回一個Vue對象(經(jīng)過測試,直接返回Vue對象也是可以的);
前面的source部分就是業(yè)務開發(fā)的代碼,開發(fā)完成之后通過 webpack 進行構(gòu)建,生成對應的bundle,這里不再贅述client bundle,就是一個可在瀏覽器端執(zhí)行的打包文件;這里說下server bundle, vue2提供 vue-server-renderer模塊,模塊可以提供兩種render: rendererer/bundleRenderer ,下面分別介紹下這兩種render。
renderer接收一個vue對象 ,然后進行渲染,這種對于簡單的vue對象,可以這么去做,但是對于復雜的項目,如果使用這種直接require一個vue對象,這個對于服務端代碼的結(jié)構(gòu)和邏輯都不太友好,首先模塊的狀態(tài)會一直延續(xù)在每個請求渲染請求,我們需要去管理和避免這次渲染請求的狀態(tài)影響到后面的請求,因此vue-server-renderer提供了另外一種渲染模式,通過一個 bundleRenderer去做渲染。
bundleRenderer是較為復雜項目進行服務端渲染官方推薦的方式,通過webpack以server entry按照一定的要求打包生成一個 server-bundle,它相當于一個可以給服務端用的app的打包壓縮文件,每一次調(diào)用都會重新初始化 vue對象,保證了每次請求都是獨立的,對于開發(fā)者來說,只需要專注于當前業(yè)務就可以,不用為服務端渲染開發(fā)更多的邏輯代碼。
renderer生成完成之后,都存在兩個接口,分別是renderToString和renderToStream,一個是一次性將頁面渲染成字符串文件,另外一個是流式渲染,適用于支持流的web服務器,可以是請求服務的速度更快
4.除了上面說的那些不同,vue2在生命周期管理,動畫機制等地方都與vue有些差別,具體請瀏覽migration
Vuex2 和 Vuex 、Webpack2 和 Webpack 的不同之處 vuexwebpack相對于 vue2和vue 較大改動,vue的狀態(tài)管理工具 vuex的改動不是很大,底層改動由于時間關(guān)系還沒有來得及細究,但是在使用方面多了幾個 Helper,利用ES6的展開函數(shù)可以更加方便的使用state,getters,mutations,actions。下面簡單介紹下vuex各個部分的概念
state是一個全局的狀態(tài)存儲,數(shù)據(jù)會存儲在其中,vue組件可以直接訪問其中的值,但是只可以讀,不可以進行寫操作
getter,有些時候我們需要對獲取的數(shù)據(jù)進行加工,而不是直接獲取state中的數(shù)據(jù),這時候可以通過getter定義函數(shù),返回對應的數(shù)據(jù)
mutations是vuex中唯一一個可以修改數(shù)據(jù)的地方,mutations可以定義事件函數(shù),在vue組件中可以通過commit發(fā)射事件,調(diào)用函數(shù)。需要注意的是,mutations中的操作必須是同步的,不可以存在異步操作的情況。
actions和 mutation比較相似,不同的是actions中不直接修改state,而是通過commit調(diào)用mutations修改數(shù)據(jù),而且actions中可以存在異步處理邏輯
從零開始搭項目webpack2 和 webpack對比,有以下的新特性:
ES6 Modules : webpack 2 已經(jīng)支持原生的 ES6 的模塊加載器了,這意味著 webpack 2 能夠理解和處理 import和export了,而不用把他們轉(zhuǎn)化成 CommonJS 來處理了。
用 ES6 來做代碼拆分 : ES6 的模塊加載器定義了System.import這一個方法,System.import能夠在運行時動態(tài)加載 ES6 模塊。
混合使用 ES6 和 AMD 和 CommonJS (Mixing ES6 with AMD and CommonJS)
更加具體的新特性可以瀏覽鏈接地址
好了,前面扯了那么多東西,估計沒什么人看,我們還是回歸題目,開始敲代碼吧,哈哈,接下來我會使用vue2 + vuex2 + webpack2 搭建一個簡單的 ssr項目,能夠直出頁面,還能夠保存成靜態(tài)文件。雖然官方頁面響應的實例vue-hackernews-2.0,但是如果一開始把代碼下下來,還是不太容易理解的,所以我參考其例子,從零開始搭建項目,源碼在文章的最后
首先當然是使用npm init新建一個項目
然后往package.json中寫入下列依賴然后運行 npm i ,然后去上個廁所,喝杯茶也行,等所有的依賴安裝完畢
介紹下一些模塊的作用 vue,vuex 為vue項目使用的基本框架,express,vue-server-renderer,serialize-javascript為服務端渲染使用的模塊,babel-*為ES6轉(zhuǎn)換成ES5模塊,其他的webpack*,*-loader為webpack構(gòu)建所需要的模塊,如果需要項目學習webpack的使用,可以閱讀官方文檔安裝階段完成了,下面進入愉快的編碼階段了,其實按照流程應該是編碼同時搞定打包、開發(fā)環(huán)境配置等工作的,為了文章的效果,就分開說了
制作的頁面是一個沒有什么業(yè)務情景的頁面(請原諒我,想到什么就寫什么代碼了),主要是為了演示組件的引用流程,vuex狀態(tài)管理以及引用,狀態(tài)改變之后的視圖更新,異步操作的視圖更新,所以,當你下了源碼,大概頁面,你會看到下面這個奇奇怪怪的東西:
好了不要在意這些細節(jié)了,我們來看看這個怪怪的東西是怎么出來的,先展示下項目最終的目錄結(jié)構(gòu):
其中index.html就是頁面最終生成頁的模板頁,里面有簡單的頭部信息和占位符,可以在服務端渲染后進行內(nèi)容替換
app.js就是頁面的邏輯入口文件,Vue對象在這里實例化,其中使用的store,route可以在實例化中傳入可以看到app.js引用了App.vue組件,.vue是vue官方推出的單文件開發(fā)方式,配合webpack的vue-loader可以方便的實現(xiàn)模塊化開發(fā),.vue文件在打包的時候會被編譯成為一個js對象,里面包含一個render方法,用于渲染頁面,下面是App.vue文件
可以看到頁面包含三個部分template 、script 、style,其中template為組件使用的模板,現(xiàn)在vue2除了使用template,還可以使用JSX和js模板,但是相對其他兩種,template對于前端開發(fā)者來說還是比較直觀的,script為組件的邏輯部分,使用es6的進行模塊化,構(gòu)建的時候會使用Vue.extend生成一個組件,style為頁面的樣式部分,可以指定lang來聲明使用的樣式語法類型,可以用原生的css,也可以用stylus,sass等等,只要配置不同的webpack loader進行進行編譯就行了,另外可以指定 scoped,使得組件中的樣式只對組件生效,不會影響其他組件,不用擔心命名重復的問題,其原理是在生成的時候為標簽生成一段隨機數(shù)(沒研究過生成數(shù)的算法),并且為選擇器加上對應隨機數(shù)的屬性選擇器。
可以看到組件import另外一個List.vue組件,并且在components中進行了引用,template中進行了引用,這就實現(xiàn)了組件的嵌套和復用,下面是List.vue文件
這個文件使用了vuex管理的數(shù)據(jù),在此前的版本的vuex中,在組件使用數(shù)據(jù)需要寫很多的computed,methods,在新版本的可以配合ES6的展開函數(shù)和vuex的helper,簡寫很多函數(shù),組件部分內(nèi)容就說到這里了,可能有人會說啥是computed,啥是methods,這些通通自己看文檔,
總的來說,寫一個組件需要了解下面幾點:模板指令,例如v-for,v-bind,v-on等
數(shù)據(jù)使用配置屬性data,computed,props,watch等
組件的生命周期屬性created,mounted等
全局方法Vue.set,Vue.nextTick等
進階開發(fā): 動畫效果,自定義指令,自定義插件,混合組件開發(fā)
下面說下用vuex做狀態(tài)管理,下面是store/index.js文件
可以看到使用vuex需要在Vue.use中引入,然后實例化一個Vuex.Store對象就可以了,對象中需要定義state,actions,mutations,getters等內(nèi)容,這樣子就可以建立一個全局的狀態(tài)管理機制,可以從應用的頂端去處理數(shù)據(jù),各個組件中對數(shù)據(jù)進行操作也是通過事件直接傳遞到Vuex中進行數(shù)據(jù)更新,然后再進行響應到其他使用同個數(shù)據(jù)的組件中,進行視圖更新。
項目的邏輯代碼已經(jīng)完成了,但是對照上面ssr的概念,會發(fā)現(xiàn)還少了兩個webpack的entry point,一個是前端代碼的入口,可以是供服務端渲染的入口,下面是前端client-entry.js文件
文件引入了app.js,判斷如果在服務端渲染時已經(jīng)寫入狀態(tài),則將vuex的狀態(tài)進行替換,使得服務端渲染的html和vuex管理的數(shù)據(jù)是同步的。然后將vue實例掛載到html指定的節(jié)點中。
下面是server-entry.js文件
這里面服務端會傳過來一個context對象,可以從獲取信息,也可以寫入信息,可以看到將現(xiàn)有的vuex state賦值給context,給服務端渲染使用,最后返回vue對象(文檔中寫著需要返回一個Promise對象,對象中再返回一個vue對象,經(jīng)過實驗直接返回也是可以的,如果應用中存在異步操作會影響視圖和vuex數(shù)據(jù)狀態(tài),那么應該返回一個Promise對象,使得服務端得到的vue對象是最后數(shù)據(jù)和視圖同步統(tǒng)一的)
代碼擼完了,下面要讓他跑起來了,配置分為兩部分,一個是webpack打包的配置,一個是服務端渲染服務器的搭建,這里使用express進行服務器的簡單搭建,不涉及任何負載均衡和性能優(yōu)化問題,下面分別說說這兩個部分 :
webpack打包:webpack打包主要有三個文件webpack.base.config.js,webpack.client.config.js,webpack.server.cofnig.js,其中base主要配置了對應文件類型的loader,還有指定了entry的切割點,將業(yè)務代碼和庫,client指定了client-entry.js作為entry point ,還將庫文件和業(yè)務文件進行分別打包,還有一些圖片處理,代碼壓縮的工作。server指定了server-entry.js作為entry point,并且指定了打包了類型標準是commonjs2,供服務端渲染模塊使用。
而在開發(fā)過程中,可以使用webpack-hot-middleware/client,webpack-hot-middleware去實現(xiàn)代碼的watch和重新構(gòu)建雙端的代碼的流程,是得開發(fā)更加便捷,具體配置在setup-dev-server.js中
最后說一下服務端渲染的服務器配置,服務端部分使用vue-server-renderer模塊的createBundleRenderer通過傳入剛才webpack生成的server-bundler去生成一個bundleRenderer,就可以調(diào)用renderToStream或者renderToString渲染頁面了,具體配置在server.js中
具體怎么跑起項目可以看下package.json的scripts屬性,其中dev是開發(fā)用,start是正式環(huán)境動態(tài)生成頁面用,build可以直接生成client-bundler和server-bundler
基本上比較完整的vue2 前段端同構(gòu)渲染已經(jīng)介紹完了,下面說下我對框架的看法,前端框架這個東西基本上就是一時火一個,我們在學習新東西的同時也應該不忘老本,要有自己的技術(shù)棧和工作流,就像《人月神話》中的一句話說的好,沒有解決任何事情的銀彈,對于不同的項目,不同的業(yè)務情景,應該采取不同的框架,使用最合適的開發(fā)架構(gòu)去開發(fā)。
附上代碼 點我點我,給個star唄~
最后也沒啥好說的了,要不給大家拜個早年吧,祝大家代碼沒bug,哈哈
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/91030.html
摘要:它會檢測出最大靜態(tài)子樹就是不需要動態(tài)性的子樹并且從渲染函數(shù)中萃取出來。這樣在每次重渲染的時候,它就會直接重用完全相同的同時跳過比對。需要注意的是,中的操作必須是同步的,不可以存在異步操作的情況。 新增:哈哈,最近又推出了 vue 的文章,在這里放個鏈接~手把手教你從零寫一個簡單的 VUE 感謝有人看我扯技術(shù),這篇文章主要介紹最近非常火的vue2前端框架的特點和vue2+vuex2+we...
摘要:它會檢測出最大靜態(tài)子樹就是不需要動態(tài)性的子樹并且從渲染函數(shù)中萃取出來。這樣在每次重渲染的時候,它就會直接重用完全相同的同時跳過比對。需要注意的是,中的操作必須是同步的,不可以存在異步操作的情況。 新增:哈哈,最近又推出了 vue 的文章,在這里放個鏈接~手把手教你從零寫一個簡單的 VUE 感謝有人看我扯技術(shù),這篇文章主要介紹最近非?;鸬膙ue2前端框架的特點和vue2+vuex2+we...
摘要:無需使用服務器實時動態(tài)編譯,而是使用預渲染方式,在構(gòu)建時簡單地生成針對特定路由的靜態(tài)文件。與可以部署在任何靜態(tài)文件服務器上的完全靜態(tài)單頁面應用程序不同,服務器渲染應用程序,需要處于運行環(huán)境。更多的服務器端負載。 目錄結(jié)構(gòu) -no-ssr-demo 未做ssr之前的項目代碼用于對比 -vuecli2ssr 將vuecli生成的項目轉(zhuǎn)為ssr -prerender-demo 使用prer...
摘要:本文源碼簡介之前剛?cè)腴T并做好了一個簡而全的純?nèi)彝暗捻椖?,?shù)據(jù)都是本地模擬請求的詳情請移步這里為了真正做到數(shù)據(jù)庫的真實存取,于是又開始入門了并以此來為之前的頁面寫后臺數(shù)據(jù)接口。 本文源碼:Github 簡介: 之前剛?cè)腴Tvue并做好了一個簡而全的純vue2全家桶的項目,數(shù)據(jù)都是本地 json 模擬請求的;詳情請移步這里:vue-proj-demo 為了真正做到數(shù)據(jù)庫的真實存取,于是又...
閱讀 2989·2023-04-25 21:23
閱讀 3022·2021-09-22 15:24
閱讀 862·2019-08-30 12:55
閱讀 2095·2019-08-29 18:42
閱讀 2607·2019-08-29 16:27
閱讀 943·2019-08-26 17:40
閱讀 2173·2019-08-26 13:29
閱讀 2604·2019-08-26 11:45