之前介紹過bootstrap、jquery架構都是外國的,下面要介紹一款優秀的國産架構vue。
1、vue模闆文法
1.1 vue基礎概念
首先介紹庫和架構的概念:
- 庫:提供大量的api幫助程式員實作效果;
- 架構:提供基礎性服務(如vue有虛拟dom、雙向資料綁定);
vue是一個漸進式的JavaScript架構:
并具有以下特點:
1.2 vue的基本使用
下面先對比原生js、jquery以及vue實作helloworld的過程看看其之間的不同:
首先是原生js:
然後是jquery:
最後是vue:
其實vue各部分具體解釋如下:
其中的el是元素挂載的位置(值可以是css選擇器如上的#app或者dom元素,即getelement得到的dom元素),而data則是模型資料(其是一個對象);
{{}}是插值表達式,通過其将資料填充到html标簽中,并且其是支援基本的計算操作以及字元串拼接等的,如上圖中所示;
最後我們在上面所寫的vue文法會經過編譯由vue代碼變成原生js代碼去執行:
前端渲染是将資料展示在html頁面中下面分别介紹通過原生js、模闆引擎art-template以及vue将資料渲染到頁面中去的不同:
首先是原生的js,其是将資料以字元串的形式拼接到html中,但不同程式設計人員的風格差别較大,後期維護不易:
然後是通過art-template的前端模闆引擎進行開發,其代碼規範,後期維護簡單,但是沒有專門提供事件機制:
則最後在下面詳細介紹vue的内容:
1.2.1 指令介紹
指令的本質就是自定義屬性(自定義屬性是之前使用過的data-id等等,傳統的自定義屬性是寫在标簽中的,與自定義屬性相對應的是标準屬性),其格式是v-xxx的形式,如
v-cloak
,其用法如下:
之前在使用插值表達式{{}}的時候,會存在閃動的現象,即在電腦較卡的情況下打開或者重新整理頁面,可能會将插值表達式中的原内容(未解析)就顯示出來,這樣的使用者體驗并不好,我們可以通過v-cloak指令解決這個問題:
<style type="text/css">
/*
1、通過屬性選擇器 選擇到 帶有屬性 v-cloak的标簽 讓他隐藏
*/
[v-cloak]{
/* 元素隐藏 */
display: none;
}
</style>
<body>
<div id="app">
<!-- 2、 讓帶有插值 文法的 添加 v-cloak 屬性
在 資料渲染完場之後,v-cloak 屬性會被自動去除,
v-cloak一旦移除也就是沒有這個屬性了 屬性選擇器就選擇不到該标簽
也就是對應的标簽會變為可見
-->
<div v-cloak >{{msg}}</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
// el 指定元素 id 是 app 的元素
el: '#app',
// data 裡面存儲的是資料
data: {
msg: 'Hello Vue'
}
});
</script>
</body>
</html>
1.2.2 資料綁定指令
上面已經介紹了指令的基本概念,下面介紹一組資料綁定指令:
1、首先v-text與插值表達式是效果是一樣的,但是v-text不存在閃動問題,其對于字元串中的html标簽會原樣輸出不會進行解析。此外,v-text是單向資料綁定,隻能從資料到頁面而不能頁面到資料:
<div id="app">
<!--
注意:在指令中不要寫插值文法 直接寫對應的變量名稱
在 v-text 中 指派的時候不要在寫 插值文法
一般屬性中不加 {{}} 直接寫 對應 的資料名
-->
<p v-text="msg"></p>
<p>
<!-- Vue 中隻有在标簽的 内容中 才用插值文法 -->
{{msg}}
</p>
</div>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
</script>
2、v-html相比于v-text,其能夠解析html标簽。但是其容易導緻xss攻擊,是以一般隻用在可信的内容上,不用在使用者送出的内容上:
<div id="app">
<p v-html="html"></p> <!-- 輸出:html标簽在渲染的時候被解析 -->
<p>{{message}}</p> <!-- 輸出:<span>通過雙括号綁定</span> -->
<p v-text="text"></p> <!-- 輸出:<span>html标簽在渲染的時候被源碼輸出</span> -->
</div>
<script>
let app = new Vue({
el: "#app",
data: {
message: "<span>通過雙括号綁定</span>",
html: "<span>html标簽在渲染的時候被解析</span>",
text: "<span>html标簽在渲染的時候被源碼輸出</span>",
}
});
</script>
3、v-pre會原原本本輸出内容,不會與下面的資料進行比對顯示,而是使用者在v-pre中寫什麼就顯示什麼(對于一些靜态内容我們可以通過該指令加快渲染):
<span v-pre>{{ this will not be compiled }}</span>
<!-- 顯示的是{{ this will not be compiled }} -->
<span v-pre>{{msg}}</span>
<!-- 即使data裡面定義了msg這裡仍然是顯示的{{msg}} -->
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
</script>
1.2.3 資料響應式與資料綁定
響應式我們在之前已經接觸過了,是在html5中根據螢幕尺寸的變化而使頁面中的内容進行變化;而這裡的資料響應式則是根據資料的變化進行頁面中的變化;
資料綁定則是将資料綁定到html标簽中,同理,資料的綁定也有幾個常用的指令:
1、v-once是一次性的插值,在執行後當資料再度改變時,其不會再進行相應的改變:
<!-- 即使data裡面定義了msg 後期我們修改了 仍然顯示的是第一次data裡面存儲的資料即 Hello Vue.js -->
<span v-once>{{ msg}}</span>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
</script>
2、下面介紹雙向資料綁定的v-model,使用該指令綁定的資料,視圖改變時資料也會改變,而當資料改變時視圖也會改變,是雙向的:
<div id="app">
<div>{{msg}}</div>
<div>
當輸入框中内容改變的時候, 頁面上的msg 會自動更新
<input type="text" v-model='msg'>
</div>
</div>
1.2.4 事件綁定
我們可以通過
v-on:具體觸發
,如
v-on:click
的形式,其可以直接在标簽中寫具體的函數處理,如下圖所示:
但是以上做法在函數代碼較多時難以了解,是以一般在vue執行個體的methods屬性中寫具體的函數處理代碼:
然後在methods中:
而對于事件傳參則如下面舉例所示,如果要傳參則隻能選擇下面的第二種方式,且在有多個參數時
$event
事件對象必須放在最後一個,而第一種方法是預設傳遞事件對象的,第一個參數就是事件對象:
<body>
<div id="app">
<div>{{num}}</div>
<div>
<!-- 如果事件直接綁定函數名稱,那麼預設會傳遞事件對象作為事件函數的第一個參數 -->
<button v-on:click='handle1'>點選1</button>
<!-- 2、如果事件綁定函數調用,那麼事件對象必須作為最後一個參數顯示傳遞,
并且事件對象的名稱必須是$event
-->
<button v-on:click='handle2(123, 456, $event)'>點選2</button>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
num: 0
},
methods: {
handle1: function(event) {
console.log(event.target.innerHTML)
},
handle2: function(p, p1, event) {
console.log(p, p1)
console.log(event.target.innerHTML)
this.num++;
}
}
});
</script>
下面介紹事件修飾符:
- 在事件處理程式中調用
或event.preventDefault()
是非常常見的需求。event.stopPropagation()
- Vue 不推薦我們操作DOM 為了解決這個問題,Vue.js 為
提供了事件修飾符v-on
- 修飾符是由點開頭的指令字尾來表示的
<!-- 阻止單擊事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 送出事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯 即阻止冒泡也阻止預設事件(阻止預設事件如a标簽的跳轉) -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 隻當在 event.target 是目前元素自身時觸發處理函數 -->
<!-- 即事件不是從内部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
使用修飾符時,順序很重要;相應的代碼會以同樣的順序産生。是以,用 v-on:click.prevent.self 會阻止所有的點選,而 v-on:click.self.prevent 隻會阻止對元素自身的點選。
原生js中阻止冒泡是通過上面提到的
event.stopPropagation()
來實作的:
傳統中阻止a标簽的跳轉功能是通過給href屬性賦
javascript:;
或者
JavaScript:void(0)
,或者在a的事件中寫上
event.preventDefault()
;
更多事件修飾符可見vue開發文檔;
下面介紹按鍵修飾符:
在做項目中有時會用到鍵盤事件,在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為
v-on
在監聽鍵盤事件時添加按鍵修飾符;
<!-- 隻有在 `keyCode` 是 13 時調用 `vm.submit()` -->
<input v-on:keyup.13="submit">
<!-- -當點選enter 時調用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<!--當點選enter或者space時 時調用 `vm.alertMe()` -->
<input type="text" v-on:keyup.enter.space="alertMe" >
常用的按鍵修飾符
.enter => enter鍵
.tab => tab鍵
.delete (捕獲“删除”和“倒退”按鍵) => 删除鍵
.esc => 取消鍵
.space => 空格鍵
.up => 上
.down => 下
.left => 左
.right => 右
<script>
var vm = new Vue({
el:"#app",
methods: {
submit:function(){},
alertMe:function(){},
}
})
</script>
而具體的keycode可以去查表可知,其他部落格有很多這裡不再進行展示;
上面是vue給我們提供的按鍵修飾符,但在通過keycode進行定義時,程式往往難懂,在Vue中可以通過
config.keyCodes
自定義按鍵修飾符别名;
<div id="app">
預先定義了keycode 116(即F5)的别名為f5,是以在文字輸入框中按下F5,會觸發prompt方法
<input type="text" v-on:keydown.f5="prompt()">
</div>
<script>
Vue.config.keyCodes.f5 = 116;
let app = new Vue({
el: '#app',
methods: {
prompt: function() {
alert('我是 F5!');
}
}
});
</script>
1.2.5屬性綁定
屬性綁定主要是通過
v-bind
指令來實作的:
- v-bind 指令被用來響應(動态)地更新 HTML 屬性
- v-bind:href 可以縮寫為 :href;
<!-- 綁定一個屬性 -->
<img v-bind:src="imageSrc">
<!-- 縮寫 -->
<img :src="imageSrc">
v-model實作原理如下:
我們可以通過v-bind來綁定class類(其會與普通的class共存),綁定形式可以是對象和數組:
注意class是把類放放在對象中作為屬性名,并把布爾變量作為屬性值決定該類是否作用,而style是把css的單項内容作為屬性名,并且屬性值是在data定義的具體屬性:
1、 v-bind 中支援綁定一個對象
如果綁定的是一個對象 則 鍵為 對應的類名 值 為對應data中的資料
<!--
HTML最終渲染為 <ul class="box textColor textSize"></ul>
注意:
textColor,textSize 對應的渲染到頁面上的CSS類名
isColor,isSize 對應vue data中的資料 如果為true 則對應的類名 渲染到頁面上
當 isColor 和 isSize 變化時,class清單将相應的更新,
例如,将isSize改成false,
class清單将變為 <ul class="box textColor"></ul>
-->
<ul class="box" v-bind:class="{textColor:isColor, textSize:isSize}">
<li>學習Vue</li>
<li>學習Node</li>
<li>學習React</li>
</ul>
<div v-bind:style="{color:activeColor,fontSize:activeSize}">對象文法</div>
<sript>
var vm= new Vue({
el:'.box',
data:{
isColor:true,
isSize:true,
activeColor:"red",
activeSize:"25px",
}
})
</sript>
<style>
.box{
border:1px dashed #f0f;
}
.textColor{
color:#f00;
background-color:#eef;
}
.textSize{
font-size:30px;
font-weight:bold;
}
</style>
注意這裡的class數組中的名字隻是data中定義的變量名,實際的css定義的類在css中指派給他;而style則是直接數組中變量是data中的具體變量,在data中定義了其值:
2、 v-bind 中支援綁定一個數組 數組中classA和 classB 對應為data中的資料
這裡的classA 對用data 中的 classA
這裡的classB 對用data 中的 classB
<ul class="box" :class="[classA, classB]">
<li>學習Vue</li>
<li>學習Node</li>
<li>學習React</li>
</ul>
<!--組文法可以将多個樣式對象應用到同一個元素 -->
<div v-bind:style="[styleObj1, styleObj2]"></div>
<script>
var vm= new Vue({
el:'.box',
data:{
classA:‘textColor‘,
classB:‘textSize‘,
styleObj1: {
color: 'red'
},
styleObj2: {
fontSize: '30px'
}
}
})
</script>
<style>
.box{
border:1px dashed #f0f;
}
.textColor{
color:#f00;
background-color:#eef;
}
.textSize{
font-size:30px;
font-weight:bold;
}
</style>
最後附上一段動态綁定class根據不同狀态切換類的寫法:
<ul>
<!-- 動态綁定class 有 active 類名高亮 無 active 不高亮-->
<li :class='currentIndex==index?"active":""'
:key='item.id' v-for='(item,index) in list'
>{{item.title}}</li>
</ul>
<!-- 動态綁定class 有 current 類名顯示 無 current 隐藏-->
<div :class='currentIndex==index?"current":""'
:key='item.id' v-for='(item, index) in list'>
<!-- : 是 v-bind 的簡寫 綁定屬性使用 v-bind -->
<img :src="item.path">
</div>
1.2.6vue中的分支結構
if使用場景如下:
- 1- 多個元素 通過條件判斷展示或者隐藏某個元素。或者多個元素
- 2- 進行兩個視圖之間的切換 v-if基本使用如下:
<div id="app">
<!-- 判斷是否加載,如果為真,就加載,否則不加載-->
<span v-if="flag">
如果flag為true則顯示,false不顯示!
</span>
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
flag:true
}
})
</script>
----------------------------------------------------------
<div v-if="type === 'A'">
A
</div>
<!-- v-else-if緊跟在v-if或v-else-if之後 表示v-if條件不成立時執行-->
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<!-- v-else緊跟在v-if或v-else-if之後-->
<div v-else>
Not A/B/C
</div>
<script>
new Vue({
el: '#app',
data: {
type: 'C'
}
})
</script>
上面還有個v-show,其與v-if的差別如下:
- v-show本質就是标簽display設定為none,控制隐藏
- v-show隻編譯一次,後面其實就是控制css,而v-if不停的銷毀和建立,故v-show性能更好一點。
- v-if是動态的向DOM樹内添加或者删除DOM元素
- v-if切換有一個局部編譯/解除安裝的過程,切換過程中合适地銷毀和重建内部的事件監聽和子元件
總結:如果頻繁的要一個元素顯示與隐藏則用v-show,而渲染出來後變化比較少則用v-if;
1.2.6vue中的循環結構
v-for
- 用于循環的數組裡面的值可以是對象,也可以是普通元素
<ul id="example-1">
<!-- 循環結構-周遊數組
item 是我們自己定義的一個名字 代表數組裡面的每一項
items對應的是 data中的數組-->
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
<script>
new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
}
})
</script>
注意循環時如果想帶上索引:
此外,為了友善區分不同元素,我們還可以給周遊到的所有元素加一個key值:這裡是因為其周遊的數組下是一個個對象,每個對象中都有id屬性,可以直接拿來使用,我們也可以直接使用其他的:
但除了周遊簡單數組以及複雜數組(數組中是一個個對象),其也可以直接周遊如下單純的一個對象:
<!-- 循環結構-周遊對象
v 代表 對象的value
k 代表對象的 鍵
i 代表索引
--->
<div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>
<script>
new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
obj: {
uname: 'zhangsan',
age: 13,
gender: 'female'
}
}
})
</script>
其中value是具體的值、key是鍵名而index是索引号,其名字可以自定義但是三者的順序不能調換;
此外,注意v-if與v-for同時出現的情況:
- 不推薦同時使用
和v-if
v-for
- 當
與v-if
一起使用時,v-for
具有比v-for
更高的優先級; 則其會進行周遊,隻有到value為12時才會進行渲染;v-if
2、vue常用特性
常用特性将分為表單操作、自定義指令、計算屬性、過濾器、偵聽器以及生命周期幾個部分進行介紹;
2.1表單操作
表單操作從以下幾個分别進行介紹:
1、對于input下的text以及textarea标簽,通過v-model進行雙向的資料綁定,綁定的變量是vue執行個體下data中的一個變量:
<!-- textarea 是 一個雙标簽 不需要綁定value 屬性的 -->
<textarea v-model='desc'></textarea>
2、對于單選框radio:
<!--
1、 兩個單選框需要同時通過v-model 雙向綁定 一個值
2、 每一個單選框必須要有value屬性 且value 值不能一樣
3、 當某一個單選框選中的時候 v-model 會将目前的 value值 改變 data 中的 資料
gender 的值就是選中的值,我們隻需要實時監控他的值就可以了
-->
<input type="radio" id="male" value="1" v-model='gender'>
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model='gender'>
<label for="female">女</label>
<script>
new Vue({
data: {
// 預設會讓目前的 value 值為 2 的單選框選中
gender: 2,
},
})
</script>
3、對于多選框checkbox:
- 通過v-model
- 和擷取單選框中的值一樣
- 複選框
這種的組合時 data 中的 hobby 我們要定義成數組 否則無法實作多選checkbox
<!--
1、 複選框需要同時通過v-model 雙向綁定 一個值
2、 每一個複選框必須要有value屬性 且value 值不能一樣
3、 當某一個單選框選中的時候 v-model 會将目前的 value值 改變 data 中的 資料
hobby 的值就是選中的值,我們隻需要實時監控他的值就可以了
-->
<div>
<span>愛好:</span>
<input type="checkbox" id="ball" value="1" v-model='hobby'>
<label for="ball">籃球</label>
<input type="checkbox" id="sing" value="2" v-model='hobby'>
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value="3" v-model='hobby'>
<label for="code">寫代碼</label>
</div>
<script>
new Vue({
data: {
// 預設會讓目前的 value 值為 2 和 3 的複選框選中
hobby: ['2', '3'],
},
})
</script>
3、對于下拉框select,在設定了多選選項multiple為true後,其是按住shift鍵進行多項的選擇:
<div>
<span>職業:</span>
<!--
1、 需要給select 通過v-model 雙向綁定 一個值
2、 每一個option 必須要有value屬性 且value 值不能一樣
3、 當某一個option選中的時候 v-model 會将目前的 value值 改變 data 中的 資料
occupation 的值就是選中的值,我們隻需要實時監控他的值就可以了
-->
<!-- multiple 多選 -->
<select v-model='occupation' multiple="true">
<option value="0">請選擇職業...</option>
<option value="1">教師</option>
<option value="2">軟體工程師</option>
<option value="3">律師</option>
</select>
</div>
<script>
new Vue({
data: {
// 預設會讓目前的 value 值為 2 和 3 的下拉框選中
occupation: ['2', '3'],
},
})
</script>
在介紹完常見的表單後,下面介紹表單修飾符:
<!-- 自動将使用者的輸入值轉為數值類型 -->
<input v-model.number="age" type="number">
<!--自動過濾使用者輸入的首尾空白字元 -->
<input v-model.trim="msg">
<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg" >
1、number是用于将表單輸入的内容轉為字元串,或者我們在擷取表單值後再通過
parseInt
方法将其
轉換為數字也可以;
2、trim是自動去除輸入首尾兩端的空格,與之前介紹過一樣;
3、lazy用于減緩同步更新屬性的時機。在以前我們監聽使用者輸入時,是使用者每輸入字元都會觸發事件。但是我們如在注冊頁面中郵箱填寫時,并不用使用者每輸入一個字元就判斷一次郵箱是否已存在,我們隻需在輸入框失去焦點或者是使用者按下enter鍵(表示輸入完成)時才更新綁定的值并觸發change事件進行判斷即可。是以加上lazy屬性
2.2自定義指令
vue給我們提供了一些列的指令
v-xx
我們已經在前面進行介紹過了,但是這些内置指令往往難以滿足我們的使用需求,是以vue允許我們自定義指令,如下面我們先定義一個可以在頁面加載時自動擷取輸入框焦點的自定義指令:
<!--
使用自定義的指令,隻需在對用的元素中,加上'v-'的字首形成類似于内部指令'v-if','v-text'的形式。
-->
<input type="text" v-focus>
<script>
// 注意點:
// 1、 在自定義指令中 如果以駝峰命名的方式定義 如 Vue.directive('focusA',function(){})
// 2、 在HTML中使用的時候 隻能通過 v-focus-a 來使用
// 注冊一個全局自定義指令 v-focus
Vue.directive('focus', {
// 當綁定元素插入到 DOM 中。 其中 el為dom元素
inserted: function (el) {
// 聚焦元素
el.focus();
}
});
new Vue({
el:'#app'
});
</script>
在定義時寫的是focus,而在使用時在html中我們必須要寫v-focus(即加上v-),這裡的inserted是鈎子函數,除其外還有其他的鈎子函數可以在vue開發文檔中進行查詢;
上面的是不帶參數的自定義指令,下面介紹帶參數的自定義指令:
<input type="text" v-color='msg'>
<script type="text/javascript">
/*
自定義指令-帶參數
bind - 隻調用一次,在指令第一次綁定到元素上時候調用
*/
Vue.directive('color', {
// bind聲明周期, 隻調用一次,指令第一次綁定到元素時調用。在這裡可以進行一次性的初始化設定
// el 為目前自定義指令的DOM元素
// binding 為自定義的函數形參 通過自定義屬性傳遞過來的值 存在 binding.value 裡面
bind: function(el, binding){
// 根據指令的參數設定背景色
// console.log(binding.value.color)
el.style.backgroundColor = binding.value.color;
}
});
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'blue'
}
}
});
</script>
這裡的鈎子函數其實也可以使用inserted,bind與inserted在很多情況下都可以互用;
上面介紹的自定義指令是全局指令,即定義在script标簽中但在vue的執行個體外的,其也可以定義局部的自定義指令,即在vue執行個體下進行定義,且該指令隻能在目前元件中使用,如果有同名的全局元件與局部元件,則局部元件會覆寫全局元件:
<input type="text" v-color='msg'>
<input type="text" v-focus>
<script type="text/javascript">
/*
自定義指令-局部指令
*/
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'red'
}
},
//局部指令,需要定義在 directives 的選項
directives: {
color: {
bind: function(el, binding){
el.style.backgroundColor = binding.value.color;
}
},
focus: {
inserted: function(el) {
el.focus();
}
}
}
});
</script>
2.3計算屬性
之前我們說過可以在插值表達式中進行基礎的運算,但是在運算邏輯複雜時,将計算内容寫在其中則閱讀起來并不友善,如下:
而使用計算屬性則可以讓html更加簡潔,如下:
- 計算屬性是基于它們的響應式依賴進行緩存的
- computed比較适合對多個變量或者對象進行處理後傳回一個結果值,也就是多個變量中的某一個值發生了變化則我們監控的這個值也就會發生變化;
<div id="app">
<!--
當多次調用 reverseString 的時候
隻要裡面的 num 值不改變 他會把第一次計算的結果直接傳回
直到data 中的num值改變 計算屬性才會重新發生計算并将得到的值進行傳回
-->
<div>{{reverseString}}</div>
<div>{{reverseString}}</div>
<!-- 調用methods中的方法的時候 他每次會重新調用 -->
<div>{{reverseMessage()}}</div>
<div>{{reverseMessage()}}</div>
</div>
<script type="text/javascript">
/*
計算屬性與方法的差別:計算屬性是基于依賴進行緩存的,而方法不緩存
*/
var vm = new Vue({
el: '#app',
data: {
msg: 'Nihao',
num: 100
},
methods: {
reverseMessage: function(){
console.log('methods')
return this.msg.split('').reverse().join('');
}
},
//computed 屬性 定義 和 data 已經 methods 平級
computed: {
// reverseString 這個是我們自己定義的名字
reverseString: function(){
console.log('computed')
var total = 0;
// 當data 中的 num 的值改變的時候 reverseString 會自動發生計算
for(var i=0;i<=this.num;i++){
total += i;
}
// 這裡一定要有return 否則 調用 reverseString 的 時候無法拿到結果
return total;
}
}
});
</script>
最後我們需要注意計算屬性computed與方法methods的差別:
即計算屬性中如果兩個地方使用到了計算屬性得到了值,則在第一次使用時會進行計算得到值,而此時如果data中依賴的資料沒有改變且第二次使用的話則會直接從緩存中拿資料進行顯示不會再次進行計算;
而如果是方法的話,每次在html中的調用其都會完整的執行一次,沒有結果的緩存;
對于多次使用且計算複雜的結果值我們可以使用計算屬性來節約資源;
2.4偵聽器
其實這裡有點像上面提到的計算屬性,偵聽器是監聽資料,當資料一旦發生變化時就會觸發其綁定的方法,其通常用于資料改變時執行異步或開銷較大的操作:
- 使用watch來響應資料的變化
- 一般用于異步或者開銷較大的操作
- watch 中的屬性 一定是data 中 已經存在的資料
- 當需要監聽一個對象的改變時,普通的watch方法無法監聽到對象内部屬性的改變,隻有data中的資料才能夠監聽到變化,此時就需要deep屬性對對象進行深度監聽
<div id="app">
<div>
<span>名:</span>
<span>
<input type="text" v-model='firstName'>
</span>
</div>
<div>
<span>姓:</span>
<span>
<input type="text" v-model='lastName'>
</span>
</div>
<div>{{fullName}}</div>
</div>
<script type="text/javascript">
/*
偵聽器
*/
var vm = new Vue({
el: '#app',
data: {
firstName: 'Jim',
lastName: 'Green',
// fullName: 'Jim Green'
},
//watch 屬性 定義 和 data 已經 methods 平級
watch: {
// 注意: 這裡firstName 對應着data 中的 firstName
// 當 firstName 值 改變的時候 會自動觸發 watch
firstName: function(val) {
this.fullName = val + ' ' + this.lastName;
},
// 注意: 這裡 lastName 對應着data 中的 lastName
lastName: function(val) {
this.fullName = this.firstName + ' ' + val;
}
}
});
</script>
上面案例無論是修改姓氏還是名字,隻要修改了值都會觸發函數最後都會拼接出一個完整的名字來;
從上面我們可以看出,其是與計算屬性有點類似的,上面例子我們通過計算屬性将fullname進行return後也可得到同樣的效果;
在異步以及開銷較大時我們一般都使用監聽器,如在使用者輸入完使用者名後進行驗證使用者名是否存在,則通過ajax發送請求是異步操作
2.5過濾器
下面介紹過濾器的相關内容,其可以将資料按照約定進行格式化,如将字元串中的首字母改為大寫或者将原始的時間格式轉換為使用者友好的時間格式等等…
- Vue.js允許自定義過濾器,可被用于一些常見的文本格式化。
- 過濾器可以用在兩個地方:雙花括号插值和v-bind表達式。
- 過濾器應該被添加在JavaScript表達式的尾部,由“管道”符号訓示
- 支援級聯操作
- 過濾器不改變真正的
,而隻是改變渲染的結果,并傳回過濾後的版本data
- 全局注冊時是filter,沒有s的。而局部過濾器是filters,是有s的(注意過濾器也是分全劇過濾器和局部過濾器的)
<div id="app">
<input type="text" v-model='msg'>
<!-- upper 被定義為接收單個參數的過濾器函數,表達式 msg 的值将作為參數傳入到函數中 -->
<div>{{msg | upper}}</div>
<!--
支援級聯操作
upper 被定義為接收單個參數的過濾器函數,表達式msg 的值将作為參數傳入到函數中。
然後繼續調用同樣被定義為接收單個參數的過濾器 lower ,将upper 的結果傳遞到lower中
-->
<div>{{msg | upper | lower}}</div>
<div :abc='msg | upper'>測試資料</div>
</div>
<script type="text/javascript">
// lower 為全局過濾器
Vue.filter('lower', function(val) {
return val.charAt(0).toLowerCase() + val.slice(1);
});
var vm = new Vue({
el: '#app',
data: {
msg: ''
},
//filters 屬性 定義 和 data 已經 methods 平級
// 定義filters 中的過濾器為局部過濾器
filters: {
// upper 自定義的過濾器名字
// upper 被定義為接收單個參數的過濾器函數,表達式 msg 的值将作為參數傳入到函數中
upper: function(val) {
// 過濾器中一定要有傳回值 這樣外界使用過濾器的時候才能拿到結果
return val.charAt(0).toUpperCase() + val.slice(1);
}
}
});
</script>
但是以上的過濾器隻是擷取了要處理的值,下面介紹可以攜帶參數的過濾器:
<div id="box">
<!--
filterA 被定義為接收三個參數的過濾器函數。
其中 message 的值作為第一個參數,
普通字元串 'arg1' 作為第二個參數,表達式 arg2 的值作為第三個參數。
-->
{{ message | filterA('arg1', 'arg2') }}
</div>
<script>
// 在過濾器中 第一個參數 對應的是 管道符前面的資料 n 此時對應 message
// 第2個參數 a 對應 實參 arg1 字元串
// 第3個參數 b 對應 實參 arg2 字元串
Vue.filter('filterA',function(n,a,b){
if(n<10){
return n+a;
}else{
return n+b;
}
});
new Vue({
el:"#box",
data:{
message: "哈哈哈"
}
})
</script>
2.6vue執行個體生命周期
Vue執行個體從建立 到銷毀的過程 ,這些過程中會伴随着一些函數的自調用(我們通常在這些函數中調用其他函數以實作想要的頁面效果)。我們稱這些函數為鈎子函數,常用的鈎子函數如下:
總的來說,挂載用于初始化相關屬性(進入頁面時調用背景資料将資料渲染到頁面中,則必須先確定頁面頁面中已經有模闆内容,是以通過mounted函數中調用相應的資料確定資料渲染前模闆中存在内容),更新則是在我們修改頁面内容時進行觸發,銷毀則用于銷毀一些内容;
2.7數組變異方法
- 在 Vue 中,直接修改對象屬性的值無法觸發響應式。當你直接修改了對象屬性的值,你會發現,隻有資料改了,但是頁面内容并沒有改變;
- 變異數組方法即保持數組方法原有功能不變的前提下對其進行功能拓展; 使用這些方法則可以達到響應式的效果:
2.8替換數組
上面對數組的操作時在原數組中進行的,其會改變原數組的内容。當我們不希望改變原數組的内容時,可以通過替換數組将内容存到一個新的數組中(注意這種情況下要用新的數組去接收内容):
2.9動态數組響應資料
上面我們已知通過索引方法去通路數組是沒有響應式的效果的,則除了通過上面的api外vue還給我們提供了其他方法去通路數組和對象:
其也可以用來處理對象: