摘要:由于是需要兼容的后臺系統(tǒng),該項目并不能使用到等技術(shù),因此我在上的經(jīng)驗大都是使用原生的編寫的,可以看見一個組件分為兩部分視圖部分,和數(shù)據(jù)部分。
在公司里幫項目組里開發(fā)后臺系統(tǒng)的前端項目也有一段時間了。 vue這種數(shù)據(jù)驅(qū)動,組件化的框架和react很像,
從一開始的快速上手基本的開發(fā),到后來開始自定義組件,對element UI的組件二次封裝以滿足項目需求,期間也是踩了不少坑。
由于將來很長一段時間可能再也不會接觸前端了,趁著現(xiàn)在對vue還很熟練的時候,趕緊將這期間的收獲記錄下來。
按照我的理解,vue的特點在于,高層次的抽象模型,組件化,數(shù)據(jù)驅(qū)動與響應(yīng)式。
注意:本文中所有涉及到{ {的,實際上不包括中間的空格,因為hexo會無腦把這個語法當成hexo的一種特殊語法
vue是什么及特點 vue是什么簡單的來說,vue是一套用于前端開發(fā)的框架。
學習一門技術(shù)首先應(yīng)該對該技術(shù)有著一個清晰正確的認識和思路,否則猶如浮沙之上建高樓。下面就來談?wù)勎覍ue這個框架的理解。
vue它的驚艷之處在于,對上,它提供了一套非常優(yōu)秀的與傳統(tǒng)前端截然不同的前端開發(fā)模型,對下,它屏蔽了傳統(tǒng)前端開發(fā)的各種丑陋的技術(shù)。
在實現(xiàn)復雜的頁面需求時,vue幫你從傳統(tǒng)前端的各種HACK般的奇淫技巧解脫出來,vue提供的抽象開發(fā)模型擁有強大的 表達能力,能夠如絲順滑般的完成各種復雜的需求。
總而言之,vue之于傳統(tǒng)前端,類似C語言之于匯編語言,就像C語言提供了一個強大的表達能力強的語言模型一樣,vue同樣提供了一個強悍的表達前端的框架模型,這是抽象的威力。
因此,學習vue的80%的重心,都在學習這個強悍的vue模型上。
從我個人對vue的理解,它的幾個重要特點有:
抽象的組件。這是vue框架模型中的一個基礎(chǔ),vue的一切都是基于vue組件的。你在vue組件上可以使用vue提供的各種特性,vue會將其轉(zhuǎn)換成瀏覽器能夠識別的結(jié)果通過瀏覽器渲染出來。
數(shù)據(jù)驅(qū)動。這是vue的理念之一,數(shù)據(jù)才是項目的核心,也是狀態(tài)的最終保存者。而視圖,只不過是一種能夠由數(shù)據(jù)延遲計算出來的最終結(jié)果而已,它本身不存儲狀態(tài)。
響應(yīng)式。既然渲染結(jié)果只是數(shù)據(jù)的衍生產(chǎn)物,那么當數(shù)據(jù)改變時,渲染結(jié)果自然而然的也要改變。這種機制就是響應(yīng)式。
組件化。vue本身提供的 抽象特性 。從我個人的理解來看,自定義組件在vue中的地位,類似于函數(shù)在C,java之類的語言之中的地位。
它還有幾個其它的的特點:
易用和功能兼顧。在我傳統(tǒng)的思維里,易用的東西一般會犧牲一部分功能,而功能強大的東西會需要很大的成本學習,魚和熊掌不可兼得。
然而vue用實際行動狠狠給了我一耳光,只要模型設(shè)計的正交完美,完全能夠兼顧易用性和功能性。
與傳統(tǒng)前端的良好兼容。
我目前所做的項目中,由于需求的復雜化項目需要從easy UI迭代到vue,原本我做好了大刀闊斧大規(guī)模重構(gòu)的準備,不過,經(jīng)過查閱文檔和幾個小demo實驗我發(fā)現(xiàn),這玩意居然能夠和傳統(tǒng)前端并存!
結(jié)果是非常令人開心的,我逐步的,慢慢的將項目從easy UI迭代到vue版本,一個頁面一個頁面的替換,對項目的影響降低到了最小。
下面的例子定義了一個簡單的組件,x-my-component。
由于是需要兼容easy UI的后臺系統(tǒng),該項目并不能使用到webpack + babel + es6等技術(shù),因此我在vue上的經(jīng)驗大都是使用原生的js編寫的,
{ { message }}
可以看見一個組件分為兩部分:視圖部分,和數(shù)據(jù)部分。
視圖部分使用html定義,但是vue會對一些特別的語法賦予vue自己的意義。如 { { message }} 表示將數(shù)據(jù)message綁定到視圖的這個地方來。
這里是使用原生js編寫的,因此數(shù)據(jù)部分和視圖部分通過id選擇器關(guān)聯(lián)起來,定義了一個x-my-component全局組件。
從這里就可以初步感受到數(shù)據(jù)驅(qū)動。組件的狀態(tài)都是存放的數(shù)據(jù)中的,而視圖只負責渲染,本身不保存狀態(tài)。
當數(shù)據(jù)不變時,渲染結(jié)果一定不變;當數(shù)據(jù)改變時,渲染結(jié)果就要發(fā)生改變。
由于vue是組件化的,組件可以層層嵌套。不過,最終的根節(jié)點得是app節(jié)點,這樣才能渲染出結(jié)果。它的定義方式不太相同:
從這里可以看出,自定義的全局組件在vue的其它組件中可以直接使用,就像使用一個已經(jīng)存在的html標簽一樣。
數(shù)據(jù)綁定從數(shù)據(jù)驅(qū)動的觀點,我們很容易分析出數(shù)據(jù)流向:
數(shù)據(jù)源 --> vue對象 --> DOM
{ { message }} { { message.split("").reverse().join("") }}
將數(shù)據(jù)綁定到一般的內(nèi)容上,用簡單的 { {}} 的語法就可以了。
將數(shù)據(jù)綁定到屬性上,需要用特殊的 v-bind 語法。上面將 message 數(shù)據(jù)綁定到了title屬性上。
由于這個語法太常用了, v-bind:title 可直接縮寫為 :title 。
用 -v-html 語法,綁定原始的html數(shù)據(jù)。
能綁定的不僅僅是屬性鍵值,還可以是 單個表達式 。注意 只能 是單個表達式。
這些表達式只能訪問全局變量的一個白名單,如Math和Date, 不能訪問用戶自定義的全局變量 。
在傳統(tǒng)的前端編程中,需要仔細預防的一點是xss攻擊。xss攻擊的原理是:
用戶輸入的數(shù)據(jù)直接被插入到了DOM中。
用戶輸入的數(shù)據(jù)中含有html或js代碼,那么它會直接作為DOM的一部分,被渲染或被執(zhí)行出來。
利用這一點,就能夠創(chuàng)造一個指向攻擊者頁面的一張圖片或者鏈接,從而盜取用戶的cookies或sid,或者誘導用戶點擊釣魚網(wǎng)址。
因此,為預防xss,任何用戶給定的數(shù)據(jù)展現(xiàn)到頁面上都需要仔細的處理。但是如果使用vue,就不必太操心這個問題。
因為,vue提供了一個更高層次的前端模型,所有的業(yè)務(wù)代碼都需要通過vue處理。我們只需要看vue對xss的處理情況就可以了。
從上面我們可以看到,數(shù)據(jù)到視圖渲染中必須使用vue的插值語法:
普通的文本插值。vue會過濾xss攻擊,因此可以安全使用。
使用v-html語法將html插入渲染后的DOM中。這當然會造成xss攻擊,因此,使用v-html語法時要非常的小心。
條件與循環(huán)現(xiàn)在你看到我了
- { { todo.text }}
用 v-if 綁定的數(shù)據(jù),控制此元素是否顯示。
用 v-for 綁定的特殊語法,用于控制循環(huán), v-for 的元素會被重復。如上所示,todos是一個數(shù)組。
響應(yīng)式上面的例子中可以數(shù)據(jù)綁定的語法,實際上,將數(shù)據(jù)綁定到視圖上的操作并不少見,這些操作,和后端技術(shù)常用的模樣引擎類似,如python的Jinja2, java的freemarker。
但是,vue的數(shù)據(jù)綁定的還有一大不同點點是 響應(yīng)式 。
由于視圖渲染是從數(shù)據(jù)計算出來的產(chǎn)物,類似一個傳入數(shù)據(jù)傳出渲染結(jié)果的純函數(shù),因此,當數(shù)據(jù)改變時,渲染結(jié)果也會改變,所得到的結(jié)果是頁面展示的界面也會發(fā)送改變。
數(shù)據(jù)綁定還不能完全走通一個vue組件的數(shù)據(jù)流程,從上面的數(shù)據(jù)綁定我們可以發(fā)現(xiàn)一個事實:
數(shù)據(jù)由vue對象流向視圖進而渲染出來。
那么,反過來呢?如果讓數(shù)據(jù)從頁面流向vue對象?這就是下面要說到的事件處理。
事件處理事件處理的數(shù)據(jù)流向是這樣的:
用戶操作頁面產(chǎn)生數(shù)據(jù) --> 頁面 --> vue對象
{ { message }}
通過 v-on 語法,綁定事件。按鈕的數(shù)據(jù)傳入到vue對象中。
這個語法太常用了,所以 v-on:click 可縮寫成 @click 。
通過 v-model 語法,將表單的數(shù)據(jù)傳入到vue對象中。v-model的數(shù)據(jù)流動是雙向的,相當于:value數(shù)據(jù)綁定和@input事件綁定的語法糖。
能夠與用戶交互的組件都能夠產(chǎn)生數(shù)據(jù)。當用戶操作組件時,組件的相應(yīng)事件被觸發(fā),進而執(zhí)行綁定到事件的相應(yīng)函數(shù)。
在函數(shù)內(nèi)部你可以做任何處理邏輯,比如說改變vue對象記錄的狀態(tài),也就是數(shù)據(jù)。
那么,這樣,一個完整的數(shù)據(jù)流程就跑通了:
用戶操作vue組件。
相應(yīng)的事件被觸發(fā),從而導致綁定事件的函數(shù)被觸發(fā)。
函數(shù)執(zhí)行業(yè)務(wù)代碼,改變vue組件的狀態(tài),也就是前面說到的數(shù)據(jù)綁定中的數(shù)據(jù)。
數(shù)據(jù)被改變,綁定了該數(shù)據(jù)的視圖也會發(fā)送改變,視圖被重新渲染。
頁面發(fā)生相應(yīng)改變,用戶觀察到了自己操作的反饋結(jié)果。
再談響應(yīng)式 virtual DOM我們知道,數(shù)據(jù)被綁定到視圖上,視圖本身不存儲狀態(tài),當數(shù)據(jù)不變時,渲染結(jié)果不變;當數(shù)據(jù)改變時,視圖也需要重新渲染。
好了,現(xiàn)在頭腦里可能會有一個簡單的思路了:
當數(shù)據(jù)改變時,觸發(fā)數(shù)據(jù)的setter,setter除了更改數(shù)據(jù)變動外,還需要執(zhí)行數(shù)據(jù)更新邏輯。
重新執(zhí)行渲染函數(shù),從新的數(shù)據(jù)中計算出新的渲染結(jié)果。
將渲染結(jié)果插入瀏覽器DOM樹中。
但是,我們仔細考察下第三步。瀏覽器的DOM樹改變后,瀏覽器才會真正的重新渲染這個DOM,計算各種css,各種布局,層層調(diào)用各種繪圖函數(shù)重新繪制GUI等等。。。
總而言之,這個步驟是非常非常耗時的。
那么,一個優(yōu)化的手段是,盡可能讓真正的DOM改變的最少,這樣瀏覽器只需要渲染最少的結(jié)果就能達到效果,提升性能。
因此,vurtual DOM就出現(xiàn)了。如下:
當數(shù)據(jù)改變時,觸發(fā)數(shù)據(jù)的setter,setter除了更改數(shù)據(jù)變動外,還需要執(zhí)行數(shù)據(jù)更新邏輯。
重新執(zhí)行渲染函數(shù),從新的數(shù)據(jù)中計算出新的渲染結(jié)果。
渲染結(jié)果被放在virtual DOM中,vue將新的DOM和就的DOM進行diff。
將diff后的差異結(jié)果更新到真正的瀏覽器DOM樹中。
可以看到,整個流程中的一大重點是diff算法。關(guān)于DOM的diff算法,我沒有接觸過。。。。。。。
之前研究過文本diff算法是基于LCS算法的動態(tài)規(guī)劃優(yōu)化,之后有興趣可以研究下DOM的diff算法。
從上面我們知道,當直接設(shè)置一個vue屬性的值時,會觸發(fā)getter函數(shù)。
實際上,getter函數(shù)是js的一個機制。在修改數(shù)組或?qū)ο髸r,也有類似的機制保證vue能檢測到數(shù)據(jù)的更新以觸發(fā)渲染。
然而,有幾種情況,由于js的限制無法檢測到,實際編程中要特別注意,否則就會感覺碰到了一個玄學bug。。。
數(shù)組。
利用索引來直接設(shè)置數(shù)組元素。如 this.todos[index] = "B"。解決方案是:Vue.set(this.todos, index, "B"),通過vue的函數(shù)設(shè)置。
直接修改數(shù)組的長度。如 this.todos.length = 10。替代方案建議使用不可變數(shù)據(jù)結(jié)構(gòu)。
對象。vue無法檢測到對象屬性的添加或刪除。添加的話,可以使用Vue.set,刪除的話,可以使用不可變數(shù)據(jù)結(jié)構(gòu)。
最后此篇博文梳理了vue的基本特性,但是對于vue最重量級的功能----組件化,沒有涉及到。對于組件化的相關(guān)梳理留到下篇博文梳理。
注:該文于2018-04-09撰寫于我的github靜態(tài)頁博客,現(xiàn)同步到我的segmentfault來。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/95866.html
摘要:觸發(fā)事件可以攜帶數(shù)據(jù),這些數(shù)據(jù)被用于傳遞給綁定了事件的其它組件的回調(diào)函數(shù)上,進而被傳遞給其它組件。父組件可以在回調(diào)函數(shù)里做任何事情,頗有靈活性。一般情況下,父組件會在回調(diào)函數(shù)中更新自己的狀態(tài)數(shù)據(jù)。 上一篇博文梳理了vue的數(shù)據(jù)驅(qū)動和響應(yīng)式相關(guān)的特性,這一篇博文就來梳理vue的一個很重要的特性,組件化。自定義組件之于vue,其意義不亞于函數(shù)之于C,java之類的編程語言。函數(shù)是計算機科學...
摘要:苗條的框架正是作者的初始目的,苗條包括代碼編寫量打包大小等等。是已經(jīng)編譯后的組件有什么缺點是一個剛起步不久的前端框架,無論在維護人員還是社區(qū)上都是大大不如三大框架,這里列舉一下本人認為的存在的缺點。 Svelte 的作者也是 rollup 的作者 Rich Harris,前端界的輪子哥。sevlte 項目首次提交于 2016 年 11 月 16 日,目前版本是 3.6.1(2019-0...
摘要:的核心庫只關(guān)注視圖層,并且非常容易學習,非常容易與其它庫或已有項目整合。的目標是通過盡可能簡單的實現(xiàn)響應(yīng)的數(shù)據(jù)綁定和組合的視圖組件。并不是框架,只是和他旁邊的生態(tài)環(huán)境組成了一個框架,下面,貼一個官方的漸進式框架介紹圖吧,方便理解。 前言 本人學習了一段時間的vue,并嘗試寫了一些小Demo之后,將vue投入了幾個項目之后,一直在邊學習邊使用,經(jīng)過看了vue,vuex,vue-route...
摘要:的核心庫只關(guān)注視圖層,并且非常容易學習,非常容易與其它庫或已有項目整合。的目標是通過盡可能簡單的實現(xiàn)響應(yīng)的數(shù)據(jù)綁定和組合的視圖組件。并不是框架,只是和他旁邊的生態(tài)環(huán)境組成了一個框架,下面,貼一個官方的漸進式框架介紹圖吧,方便理解。 前言 本人學習了一段時間的vue,并嘗試寫了一些小Demo之后,將vue投入了幾個項目之后,一直在邊學習邊使用,經(jīng)過看了vue,vuex,vue-route...
摘要:原文博客地址如何理解如何實現(xiàn)是否解讀過的源碼與框架的區(qū)別實現(xiàn)實現(xiàn)獨立初始化實例兩者的區(qū)別數(shù)據(jù)和視圖的分離,解耦開放封閉原則,對擴展開放,對修改封閉在中在代碼中操作視圖和數(shù)據(jù),混在一塊了以數(shù)據(jù)驅(qū)動視圖,只關(guān)心數(shù)據(jù)變化, 原文博客地址:https://finget.github.io/2018/05/31/mvvm-vue/ MVVM 如何理解 MVVM 如何實現(xiàn) MVVM 是否解讀過 ...
閱讀 2283·2021-10-09 09:41
閱讀 3449·2021-09-13 10:34
閱讀 1952·2019-08-30 12:59
閱讀 585·2019-08-29 17:27
閱讀 1091·2019-08-29 16:07
閱讀 2985·2019-08-29 13:15
閱讀 1337·2019-08-29 13:14
閱讀 1596·2019-08-26 12:18