Vue Vue近幾年來特別的受關註,三年前的時候angularJS霸占前端JS框架市場很長時間,接著react框架橫空出世,因為它有一個特性是虛擬DOM,從性能上碾軋angularJS,這個時候,vue1.0悄悄 的問世了,它的優雅,輕便也吸引了一部分用戶,開始收到關註,16年中旬,VUE2.0問世 ...
Vue
Vue近幾年來特別的受關註,三年前的時候angularJS霸占前端JS框架市場很長時間,接著react框架橫空出世,因為它有一個特性是虛擬DOM,從性能上碾軋angularJS,這個時候,vue1.0悄悄
的問世了,它的優雅,輕便也吸引了一部分用戶,開始收到關註,16年中旬,VUE2.0問世,這個時候vue不管從性能上,還是從成本上都隱隱超過了react,火的一塌糊塗,這個時候,angular
開發團隊也開發了angular2.0版本,並且更名為angular,吸收了react、vue的優點,加上angular本身的特點,也吸引到很多用戶,目前已經迭代到5.0了。
學習vue是現在前端開發者必須的一個技能。
前端js框架到底在幹嘛,為什麼要用
js框架幫助開發者寫js邏輯代碼,在開發應用的時候js的功能劃分為如下幾點:
渲染數據
操作dom(寫一些效果)
操作cookie等存儲機制api
在前端開發中,如何高效的操作dom、渲染數據是一個前端工程師需要考慮的問題,而且當數據量大,流向較亂的時候,如何正確使用數據,操作數據也是一個問題
而js框架對上述的幾個問題都有自己趨於完美的解決方案,開發成本降低。高性能高效率。唯一的缺點就是需要使用一定的成本來學習。
Vue官網介紹
vue是漸進式JavaScript框架
“漸進式框架”和“自底向上增量開發的設計”是Vue開發的兩個概念
Vue可以在任意其他類型的項目中使用,使用成本較低,更靈活,主張較弱,在Vue的項目中也可以輕鬆融匯其他的技術來開發,並且因為Vue的生態系統特別龐大,可以找到基本所有類型的工
具在vue項目中使用
特點:易用(使用成本低),靈活(生態系統完善,適用於任何規模的項目),高效(體積小,優化好,性能好)
Vue是一個MVVM的js框架,但是,Vue 的核心庫只關註視圖層,開發者關註的只是m-v的映射關係
與AngularJS的對比
Vue的很多api、特性都與angularJS相似,其實是因為Vue在開發的時候借鑒了很多AngularJS中的特點,而AngularJS中固有的缺點,在Vue中已經解決,也就是青出於藍而勝於藍,Vue的學習
成本比AngularJS低很多,因為複雜性就低
AngularJS是強主張的,而Vue更靈活
Vue的數據流是單向的,數據流行更清晰
Angular里指令可以是操作dom的,也可以封裝一段結構邏輯代碼,例如:廣告展示模塊
Vue中的指令只是操作dom的,用組件來分離結構邏輯
AngularJS的性能比不上Vue
Vue的使用
Vue不支持IE8,因為使用了ES5的很多特性
可以直接通過script標簽來引入vue.js,有開發版本和生產版本,開發版本一般我們在開發項目的時候引入,當最後開發完成上線的時候引入生產版本,開發版本沒有壓縮的,並且有很多提
示,而生產版本全部刪掉了
在Vue中提供了一個腳手架(命令行工具)可以幫我們快速的搭建基於webpack的開發環境...
Vue的實例
每一個應用都有一個根實例,在根實例里我們通過組件嵌套來實現大型的應用
也就是說組件不一定是必須的,但是實例是必須要有的
在實例化實例的時候我們可以傳入一個;配置項,在配置項中設置很多屬性方法可以實現複雜的功能
在配置中可以設置el的屬性,el屬性代表的是此實例的作用範圍
在配置中同過設置data屬性來為實例綁定數據
mvc/mvvm
摘自阮一峰博客
mvc 分為三層,其實M層是數據模型層,它是真正的後端數據在前端js中的一個映射模型,他們的關係是:數據模型層和視圖層有映射關係,model改變,view展示也會更改,當view產生用戶
操作或會反饋給controller,controller更改model,這個時候view又會進行新的數據渲染
這是純純的MVC的模式,但是很多框架都會有一些更改
前端mvc框架,如angularjs,backbone:
會發現,用戶可以直接操作controller(例如用戶更改hash值,conrtoller直接監聽hash值變化後執行邏輯代碼,然後通知model更改)
控制器可以直接操作view,如果,讓某一個標簽獲得進入頁面獲得焦點,不需要model來控制,所以一般會直接操作(angularJS,指令)
view可以直接操作model (數據雙向綁定)
MVP:
view和model不能直接通信,所有的交互都由presenter來做,其他部分的通信都是雙向的
view較薄 ,presenter較為厚重
MVVM:
MVVM和MVP及其相似,只是view和viewmodel的通信是雙向綁定,view的操作會自動的像viewmodel通過
v-for
在vue中可以通過v-for來迴圈數據的通知迴圈dom,語法是item in/of items,接收第二個參數是索引 (item,index) of items,還可以迴圈鍵值對,第一個參數是value,第二個是key,第三
個依然是索引
v-on
在vue中還有v-on來為dom綁定事件,在v-on:後面加上要綁定的事件類型,值里可以執行一些簡單javascript表達式:++ -- = ...
可以將一些方法設置在methods里,這樣就可以在v-on:click的值里直接寫方法名字可以,預設會在方法中傳入事件對象,當寫方法的時候加了()就可以傳參,這個時候如果需要事件對象,那
就主動傳入$event
v-on綁定的事件可以是任意事件,v-on:可以縮寫為@
為什麼在 HTML 中監聽事件?
你可能註意到這種事件監聽的方式違背了關註點分離 (separation of concern) 這個長期以來的優良傳統。但不必擔心,因為所有的 Vue.js 事件處理方法和表達式都嚴格綁定在當前視圖的
ViewModel 上,它不會導致任何維護上的困難。實際上,使用 v-on 有幾個好處:
- 掃一眼 HTML 模板便能輕鬆定位在 JavaScript 代碼里對應的方法。
- 因為你無須在 JavaScript 里手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。
- 當一個 ViewModel 被銷毀時,所有的事件處理器都會自動被刪除。你無須擔心如何自己清理它們。
模板語法
在vue中,我們使用mustache插值({{}})來將數據渲染在模板中
使用v-once指令可以控制只能插入一次值,當數據變化的時候,模板對應的視圖不更新
使用v-html指令可以解析html格式的數據
在html標簽屬性里不能使用mustache插值,這個時候給元素添加動態屬性的時候使用v-bind來綁定屬性,可以縮寫成:
在使用v-bind綁定class和內聯樣式的時候,vue做了一些優化,可以使用對象語法和數組的語法來控制
防止表達式閃爍:
v-cloak
給模板內的元素添加v-cloak屬性後,元素在vue沒有載入完的時候就有這個屬性,當vue載入完成後這個屬性就消失了,所以我們可以給這個屬性設置css樣式為隱藏
<style> [v-cloak]{ visibility: hidden; } </style>
v-text/v-html
v-text會指定將模板內元素的textContent屬性替換為指令值所代表的數據,也可以用於防止閃爍
v-html可以解析標簽,更改元素的innerHTML,性能比v-text較差v-pre
跳過元素和其子元素的編譯過程,可以用來顯示mustache
vue-resource
這是一款vue的插件,可以用來進行數據交互,支持的請求方式:GET/POST/JSONP/OPTIONS...
這個插件官方宣佈不在更新維護,也就是說儘量不要使用
計算屬性、監聽
有的時候我們需要在模板中使用數據a,這個時候就需要用到表達式,但是有的地方我們需要對a數據進行一些簡單的處理後才能使用,那麼我們就會在表達式中寫一些js邏輯運算
```
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
```
這樣我們的維護就會非常困難,也不便於閱讀
那め我們就可以在methods里設置一個方法,在模板的表達式中使用這個方法
```
<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在組件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
```
但是這個時候,只要vm中有數據變化,這個變化的數據可能和我們關註的數據無關,但是vm都會重新渲染模板,這個時候表達式中的方法就會重新執行,大大的影響性能
這個時候其實我們可以使用監聽器里完成:
在vm實例中設置watch屬性,在裡面通過鍵值對來設置一些監聽,鍵名為數據名,值可以是一個函數,這個函數在數據改變之後才會執行,兩個參數分別是性格前的值和更改後的值
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
}
值還可以是一個方法名字,當數據改變的時候這個方法會執行
當數據為object的時候,object的鍵值對改變不會被監聽到(數組的push等方法可以),這個時候需要設置深度監聽:
c: {
deep:true,
handler:function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
}
},
監聽的handler函數前面的這幾種寫法都是在數據變化的時候才會執行,初始化的時候不會執行,但是如果設置immediate為true就可以了
num:{
immediate:true,
handler:function(val){
this.nums = val*2
}
}
我們在回到上面的問題,用監聽器加上immediate屬性就可以做到該效果,但是大家可以看到的是邏輯稍稍有點複雜
watch還可以通過實例對象直接使用:vm.$watch,返回一個取消監聽的函數,這個函數執行之後會取消監聽
我們一般都會用到一個叫計算屬性的東西來解決:
計算屬性就是在實例配置項中通過computed來為vm設置一個新的數據,而這個新數據會擁有一個依賴(一條已經存在的數據),當依賴發送變化的時候,新數據也會發送變化
與方法的方式相比,它性能更高,計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時才會重新求值。相比之下,每當觸發重新渲染時,調用方法將總會再
次執行函數。
與watch相比,寫起來簡單,邏輯性更清晰,watch一般多用於,根據數據的變化而執行某些動作,而至於這些動作是在乾什麼其實無所謂,而計算屬性更有針對性,根據數據變化而更改
另一個數據
計算屬性也擁有getter和setter,預設寫的是getter,設置setter執行可以當此計算屬性數據更改的時候去做其他的一些事情,相當於watch這個計算屬性
xm:{
get:function(){//getter 當依賴改變後設置值的時候
return this.xing+'丶'+this.ming
},
set:function(val){//setter 當自身改變後執行
this.xing = val.split('丶')[0]
this.ming = val.split('丶')[1]
}
}
過濾器
vue中可以設置filter(過濾器)來實現數據格式化,雙花括弧插值和 v-bind 表達式中使用
vue1.0的有預設的過濾器,但是在2.0的時候全部給去掉了
所以在vue中如果想要使用過濾器就需要自定義
自定義的方法有兩種:全局定義和局部定義,全局定義的過濾器在任意的實例、組件中都可以使用,局部定義就是在實例、組件中定義,只能在這個實例或組件中使用
全局定義
Vue.filter(name,handler)
name是過濾器的名字,handler是數據格式化處理函數,接收的第一個參數就是要處理的數據,返回什麼數據,格式化的結果就是什麼
在模板中通過 | (管道符) 來使用,在過濾器名字後面加()來傳參,參數會在handler函數中第二個及後面的形參來接收
<p>{{msg | firstUpper(3,2)}}</p>
Vue.filter('firstUpper',function (value,num=1,num2) {
console.log(num2)
return value.substr(0,num).toUpperCase()+value.substr(num).toLowerCase()
})
局部定義
在實例、組件的配置項中設置 filters,鍵名為過濾器名,值為handler
filters:{ firstUpper:function (value,num=1,num2) { console.log(num2) return value.substr(0,num).toUpperCase()+value.substr(num).toLowerCase() } }
註意:
過濾器只能在mustache插值、v-bind里使用,其他的指令等地方都不能用
條件渲染
在Vue中可以使用v-if來控制模板里元素的顯示和隱藏,值為true就顯示,為false就隱藏
v-if控制的是是否渲染這個節點
當我們需要控制一組元素顯示隱藏的時候,可以用template標簽將其包裹,將指令設置在template上,等等vm渲染這一組元素的時候,不會渲染template
當有else分支邏輯的時候,可以給該元素加上v-else指令來控制,v-else會根據上面的那個v-if來控制,效果與v-if相反,註意,一定要緊挨著
還有v-else-if指令可以實現多分支邏輯
<input type="text" v-model="mode">
<template v-if="mode=='A'">
<h1>1.title</h1>
<p>我的第一個P標簽</p>
</template>
<template v-else-if="mode=='B'">
<h1>2.title</h1>
<p>我的第二個P標簽</p>
</template>
<template v-else-if="mode=='C'">
<h1>3.title</h1>
<p>我的第三個P標簽</p>
</template>
<template v-else>
<p>不好意思,輸入有誤</p>
</template>
需要註意的另一個地方是:Vue 會儘可能高效地渲染元素,通常會復用已有元素而不是從頭開始渲染。這樣確實能使Vue變得更快,性能更高,但是有的時候我們需要讓實例去更新dom而不是
復用,就需要給dom加上不同的key屬性,因為vue在判斷到底渲染什麼的時候,包括哪些dom可以復用,都會參考key值,如果dom表現基本一致,符合復用的條件,但是key值不同,依然不會復
用
Vue還提供了v-show指令,用法和v-if基本一樣,控制的是元素的css中display屬性,從而控制元素的顯示和隱藏 , 不能和v-else配合使用,且不能使用在template標簽上,因為template不
會渲染,再更改它的css屬性也不會渲染,不會生效
v-if vs v-show
v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷毀和重建。
v-if 也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。
相比之下,v-show 就簡單得多——不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於 CSS 進行切換。
一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在運行時條件很少改變,則使用 v-if 較好。
mixin
在Vue中,我們可以通過定義多個mixin來實現代碼抽離復用,便於維護,提升頁面的邏輯性
要註意的是:data屬性不要使用mixin,因為從邏輯上來說,每一個實例、組件的數據都應該是獨立的
一個mixin其實就是一個純粹的對象,上面掛載著抽離出來的配置,在某一個實例中,通過mixins選項(數組)導入後,此實例就擁有導入的mixin的配置
且導入的配置不會覆蓋原有的,而是合併到一起
虛擬dom
頻繁且複雜的dom操作通常是前端性能瓶頸的產生點,Vue提供了虛擬dom的解決辦法
虛擬的DOM的核心思想是:對複雜的文檔DOM結構,提供一種方便的工具,進行最小化地DOM操作。這句話,也許過於抽象,卻基本概況了虛擬DOM的設計思想
(1) 提供一種方便的工具,使得開發效率得到保證
(2) 保證最小化的DOM操作,使得執行效率得到保證
也就是說,虛擬dom的框架/工具都是這麼做的:
- 根據現有的真實dom來生成一個完整的虛擬dom樹結構
- 當數據變化,或者說是頁面需要重新渲染的時候,會重新生成一個新的完整的虛擬dom
- 拿新的虛擬dom來和舊的虛擬dom做對比(使用diff演算法),。得到需要更新的地方之後,更新內容
這樣的話,就能大量減少真實dom的操作,提高性能
組件化
模塊化就是將系統功能分離成獨立的功能部分的方法,一般指的是單個的某一種東西,例如js、css
而組件化針對的是頁面中的整個完整的功能模塊劃分,組件是一個html、css、js、image等外鏈資源,這些部分組成的一個聚合體
優點:代碼復用,便於維護
劃分組件的原則:具有大量的佈局結構的,或者是獨立的邏輯的,都應該分成組件
組件應該擁有的特性:可組合,可重用,可測試,可維護
組件
在vue中,我們通過Vue.extend來創建Vue的子類,這個東西其實就是組件
也就是說Vue實例和組件的實例有差別但是差別不帶,因為畢竟一個是父類一個是子類
一般的應用,會擁有一個根實例,在根實例裡面都是一個一個的組件
因為組件是要嵌入到實例或者父組件里的,也就是說,組件可以互相嵌套,而且,所有的組件最外層必須有一個根實例,所以組件分為:全局組件和局部組件
全局組件在任意的實例、父級組件中都能使用,局部組件只能在創建自己的父級組件或者實例中使用
組件通過不同的註冊方法成為全局、局部組件
創建組件:
Vue.extend(options)
全局註冊:
var App = Vue.extend({
template:"<h1>hello world</h1>"
})
Vue.component('my-app',App)
組件通過template來確定自己的模板,template里的模板必須有根節點,標簽必須閉合
組件的屬性掛載通過:data方法來返回一個對象作為組件的屬性,這樣做的目的是為了每一個組件實例都擁有獨立的data屬性
響應式原理
因為vue是mvvm的框架,所以當數據變化的時候,視圖會立即更新,視圖層產生操作後會自動通知vm來更改model,所以我們可以實現雙向數據綁定,而其中的原理就是實例會將設置的data逐
個遍歷利用Object.defineProperty給數據生成getter和setter,當數據變化地方時候setter會監聽到並且通知對應的watcher工具進行邏輯運算會更新視圖
聲明式渲染
在vue中,我們可以先在vue實例中聲明數據,然後通過{{}}等方式渲染在dom中