在公司里幫項目組裡開闢背景體系的前端項目也有一段時間了。 vue這類數據驅動,組件化的框架和react很像,
從一最先的疾速上手基本的開闢,到厥後最先自定義組件,對element UI的組件二次封裝以滿足項目需求,時期也是踩了不少坑。
由於未來很長一段時間能夠再也不會打仗前端了,趁着如今對vue還很闇練的時刻,趕忙將這時期的收成紀錄下來。
根據我的明白,vue的特徵在於,高條理的籠統模子,組件化,數據驅動與響應式。
<!–more–>
注重:本文中一切涉及到{ {
的,現實上不包括中心的空格,由於hexo會無腦把這個語法當做hexo的一種迥殊語法
vue是什麼及特徵
vue是什麼
簡樸的來講,vue是一套用於前端開闢的框架。
進修一門手藝起首應當對該手藝有着一個清楚準確的熟悉和思緒,不然如同浮沙之上建高樓。下面就來談談我對vue這個框架的明白。
vue它的冷艷的處所在於,對上,它供應了一套異常優異的與傳統前端判然差別的前端開闢模子,對下,它屏障了傳統前端開闢的種種貌寢的手藝。
在完成龐雜的頁面需求時,vue幫你從傳統前端的種種HACK般的奇淫技能擺脫出來,vue供應的籠統開闢模子具有壯大的 表達能力,能夠如絲順滑般的完成種種龐雜的需求。
總而言之,vue之於傳統前端,相似C言語之於彙編言語,就像C言語供應了一個壯大的表達能力強的言語模子一樣,vue一樣供應了一個刁悍的表達前端的框架模子,這是籠統的威力。
因而,進修vue的80%的重心,都在進修這個刁悍的vue模子上。
vue的特徵
從我個人對vue的明白,它的幾個主要特徵有:
- 籠統的組件。這是vue框架模子中的一個基本,vue的一切都是基於vue組件的。你在vue組件上能夠運用vue供應的種種特徵,vue會將其轉換成瀏覽器能夠辨認的結果經由過程瀏覽器襯着出來。
- 數據驅動。這是vue的理念之一,數據才是項目的中心,也是狀況的終究保留者。而視圖,只不過是一種能夠由數據耽誤盤算出來的終究結果罷了,它自身不存儲狀況。
- 響應式。既然襯着結果只是數據的衍生產品,那末當數據轉變時,襯着結果自然則然的也要轉變。這類機制就是響應式。
- 組件化。vue自身供應的 籠統特徵 。從我個人的明白來看,自定義組件在vue中的職位,相似於函數在C,java之類的言語當中的職位。
它另有幾個別的的的特徵:
- 易用和功用統籌。在我傳統的思想里,易用的東西平常會捐軀一部份功用,而功用壯大的東西會須要很大的本錢進修,魚和熊掌不可兼得。
然則vue用現實行動狠狠給了我一耳光,只需模子設想的正交圓滿,完全能夠統籌易用性和功用性。 - 與傳統前端的優越兼容。
我如今所做的項目中,由於需求的龐雜化項目須要從easy UI迭代到vue,底本我做好了雷厲風行大規模重構的預備,不過,經由查閱文檔和幾個小demo試驗我發明,這玩意竟然能夠和傳統前端並存!
結果是異常使人高興的,我逐漸的,逐步的將項目從easy UI迭代到vue版本,一個頁面一個頁面的替換,對項目的影響下降到了最小。
組件定義
下面的例子定義了一個簡樸的組件,x-my-component。
由因而須要兼容easy UI的背景體系,該項目並不能運用到webpack + babel + es6等手藝,因而我在vue上的履歷大都是運用原生的js編寫的,
<div id="x-my-component">
<div>
{ { message }}
</div>
</div>
<script>
Vue.component('x-my-component', {
template: '#x-my-component',
data: function () {
return {
message: 'Hello Vue!'
};
}
});
</script>
- 能夠瞥見一個組件分為兩部份:視圖部份,和數據部份。
- 視圖部份運用html定義,然則vue會對一些迥殊的語法給予vue本身的意義。如
{ { message }}
示意將數據message綁定到視圖的這個處所來。 - 這裡是運用原生js編寫的,因而數據部份和視圖部份經由過程id選擇器關聯起來,定義了一個
x-my-component
全局組件。 - 從這裏就可以夠開端感受到數據驅動。組件的狀況都是寄存的數據中的,而視圖只擔任襯着,自身不保留狀況。
當數據穩定時,襯着結果肯定穩定;當數據轉變時,襯着結果就要發作轉變。
由於vue是組件化的,組件能夠層層嵌套。不過,終究的根節點得是app節點,如許才襯着出結果。它的定義體式格局不太雷同:
<div id="app">
<x-my-component></x-my-component>
</div>
<script>
var app = new Vue({
el: '#app',
});
</script>
- 從這裡能夠看出,自定義的全局組件在vue的別的組件中能夠直接運用,就像運用一個已存在的html標籤一樣。
數據綁定
從數據驅動的看法,我們很輕易分析出數據流向:
數據源 –> vue對象 –> DOM
文本綁定,html綁定及xss進擊
<div id="x-my-component">
<span v-bind:title="message">
{ { message }}
{ { message.split('').reverse().join('') }}
</span>
<span :title="message"> </span>
<div v-html="rawHtml"></div>
</div>
<script>
Vue.component('x-my-component', {
template: '#x-my-component',
data: function () {
return {
message: 'Hello Vue!',
rawHtml: '<s>deleted!</s>'
};
}
});
</script>
- 將數據綁定到平常的內容上,用簡樸的
{ {}}
的語法就可以夠了。 - 將數據綁定到屬性上,須要用迥殊的
v-bind
語法。上面將message
數據綁定到了title屬性上。
由於這個語法太經常使用了,v-bind:title
可直接縮寫為:title
。 - 用
-v-html
語法,綁定原始的html數據。 - 能綁定的不僅僅是屬性鍵值,還能夠是 單個表達式 。注重 只能 是單個表達式。
這些表達式只能接見全局變量的一個白名單,如Math和Date, 不能接見用戶自定義的全局變量 。
在傳統的前端編程中,須要細緻防備的一點是xss進擊。xss進擊的道理是:
- 用戶輸入的數據直接被插進去到了DOM中。
- 用戶輸入的數據中含有html或js代碼,那末它會直接作為DOM的一部份,被襯着或被實行出來。
- 應用這一點,就可以夠製造一個指向進擊者頁面的一張圖片或許鏈接,從而偷取用戶的cookies或sid,或許引誘用戶點擊垂綸網址。
因而,為防備xss,任何用戶給定的數據展現到頁面上都須要細緻的處置懲罰。然則假如運用vue,就沒必要太費心這個題目。
由於,vue供應了一個更高條理的前端模子,一切的營業代碼都須要經由過程vue處置懲罰。我們只須要看vue對xss的處置懲罰狀況就可以夠了。
從上面我們能夠看到,數據到視圖襯着中必需運用vue的插值語法:
- 一般的文本插值。vue會過濾xss進擊,因而能夠平安運用。
- 運用v-html語法將html插進去襯着后的DOM中。這當然會形成xss進擊,因而,運用v-html語法時要異常的警惕。
前提與輪迴
<div id="x-my-component">
<p v-if="seen">如今你看到我了</p>
<ol>
<li v-for="todo in todos">
{ { todo.text }}
</li>
</ol>
</div>
<script>
Vue.component('x-my-component', {
template: '#x-my-component',
data: function () {
return {
seen: true,
todos: ["A", "B", "C"]
};
}
});
</script>
- 用
v-if
綁定的數據,掌握此元素是不是顯現。 - 用
v-for
綁定的迥殊語法,用於掌握輪迴,v-for
的元素會被反覆。如上所示,todos是一個數組。
響應式
上面的例子中能夠數據綁定的語法,現實上,將數據綁定到視圖上的操縱並不少見,這些操縱,和後端手藝經常使用的樣子容貌引擎相似,如python的Jinja2, java的freemarker。
然則,vue的數據綁定的另有一大差別點點是 響應式 。
由於視圖襯着是從數據盤算出來的產品,相似一個傳入數據傳出襯着結果的純函數,因而,當數據轉變時,襯着結果也會轉變,所獲得的結果是頁面展現的界面也會發送轉變。
數據綁定還不能完全走通一個vue組件的數據流程,從上面的數據綁定我們能夠發明一個現實:
數據由vue對象流向視圖進而襯着出來。
那末,反過來呢?假如讓數據從頁面流向vue對象?這就是下面要說到的事宜處置懲罰。
事宜處置懲罰
事宜處置懲罰的數據流向是如許的:
用戶操縱頁面發生數據 –> 頁面 –> vue對象
<div id="x-my-component">
<p>{ { message }}</p>
<button v-on:click="reverseMessage">逆轉音訊</button>
<button @click="reverseMessage">逆轉音訊</button>
<input v-model="message">
</div>
<script>
Vue.component('x-my-component', {
template: '#x-my-component',
data: function () {
return {
message: 'Hello Vue.js!'
};
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('');
}
}
});
</script>
- 經由過程
v-on
語法,綁定事宜。按鈕的數據傳入到vue對象中。
這個語法太經常使用了,所以v-on:click
可縮寫成@click
。 - 經由過程
v-model
語法,將表單的數據傳入到vue對象中。v-model的數據活動是雙向的,相當於:value數據綁定和@input事宜綁定的語法糖。
能夠與用戶交互的組件都能夠發生數據。當用戶操縱組件時,組件的響應事宜被觸發,進而實行綁定到事宜的響應函數。
在函數內部你能夠做任何處置懲罰邏輯,比如說轉變vue對象紀錄的狀況,也就是數據。
那末,如許,一個完全的數據流程就跑通了:
- 用戶操縱vue組件。
- 響應的事宜被觸發,從而致使綁定事宜的函數被觸發。
- 函數實行營業代碼,轉變vue組件的狀況,也就是前面說到的數據綁定中的數據。
- 數據被轉變,綁定了該數據的視圖也會發送轉變,視圖被重新襯着。
- 頁面發作響應轉變,用戶視察到了本身操縱的反應結果。
再談響應式
virtual DOM
我們曉得,數據被綁定到視圖上,視圖自身不存儲狀況,當數據穩定時,襯着結果穩定;當數據轉變時,視圖也須要重新襯着。
好了,如今思想里能夠會有一個簡樸的思緒了:
- 當數據轉變時,觸發數據的setter,setter除了更改數據更改外,還須要實行數據更新邏輯。
- 重新實行襯着函數,重新的數據中盤算出新的襯着結果。
- 將襯着結果插進去瀏覽器DOM樹中。
然則,我們細緻考核下第三步。瀏覽器的DOM樹轉變后,瀏覽器才會真正的重新襯着這個DOM,盤算種種css,種種計劃,層層挪用種種畫圖函數重新繪製GUI等等。。。
總而言之,這個步驟是異常異常耗時的。
那末,一個優化的手腕是,盡能夠讓真正的DOM轉變的起碼,如許瀏覽器只須要襯着起碼的結果就可以到達結果,提拔機能。
因而,vurtual DOM就湧現了。以下:
- 當數據轉變時,觸發數據的setter,setter除了更改數據更改外,還須要實行數據更新邏輯。
- 重新實行襯着函數,重新的數據中盤算出新的襯着結果。
- 襯着結果被放在virtual DOM中,vue將新的DOM和就的DOM舉行diff。
- 將diff后的差別結果更新到真正的瀏覽器DOM樹中。
能夠看到,全部流程中的一大重點是diff算法。關於DOM的diff算法,我沒有打仗過。。。。。。。
之前研討過文本diff算法是基於LCS算法的動態計劃優化,以後有興緻能夠研討下DOM的diff算法。
數據更新檢測的坑
從上面我們曉得,當直接設置一個vue屬性的值時,會觸發getter函數。
現實上,getter函數是js的一個機制。在修正數組或對象時,也有相似的機制保證vue能檢測到數據的更新以觸發襯着。
然則,有幾種狀況,由於js的限定沒法檢測到,現實編程中要迥殊注重,不然就會覺得碰到了一個玄學bug。。。
數組。
- 應用索引來直接設置數組元素。如
this.todos[index] = "B"
。解決計劃是:Vue.set(this.todos, index, "B")
,經由過程vue的函數設置。 - 直接修正數組的長度。如
this.todos.length = 10
。替換計劃發起運用不可變數據結構。
- 應用索引來直接設置數組元素。如
- 對象。vue沒法檢測到對象屬性的增加或刪除。增加的話,能夠運用
Vue.set
,刪除的話,能夠運用不可變數據結構。
末了
此篇博文梳理了vue的基本特徵,然則關於vue最重量級的功用—-組件化,沒有涉及到。關於組件化的相干梳理留到下篇博文梳理。
注:該文於2018-04-09撰寫於我的github靜態頁博客,現同步到我的segmentfault來。