Vue學習筆記(二)模板語法和常用特性
技術標籤:vue.js
Vue學習筆記(二)
一、指令
1.v-cloak指令
**作用:**防止頁面載入時出現閃爍問題(當網路較慢,網頁還在載入 Vue.js ,而導致 Vue 來不及渲染,這時頁面就會顯示出 Vue 原始碼–>{{ msg }}等。此時我們可以使用 v-cloak 指令+css來解決這一問題。),此指令最重要的特點就是 在頁面渲染完成後,c-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: '#app',
data: {
msg: 'Hello Vue'
}
});
</script>
2.v-text指令
**作用:**v-text指令用於往標籤中填充資料,跟插值表示式類似,但不會出現閃爍問題。指令中的資料為單向繫結,Vue物件中的資料值發生改變,指令插值也會發生改變,但指令插值發生改變,並不會影響例項物件中的資料值。可以通過該標籤輸出html標籤,但輸出的形式是純文字,不會被瀏覽器解析,v-html指令輸出的值會被瀏覽器解析。
程式碼演示:
<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>
3.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>
4.v-once指令
**作用:**只進行一次插值渲染,即例項中的資料改變時,插值處的內容不會發生變化,第一次插值是什麼,之後就一直是什麼。
程式碼演示:
<!-- 即使data裡面定義了msg 並且後期我們修改了msg 但仍顯示的是第一次data裡面儲存的資料 即 Hello -->
<span v-once>{{ msg}}</span>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello'
}
});
</script>
5.v-on指令(補充)
**作用:**在使用該指令時,可以向函式中傳入引數。有兩種呼叫形式:函式名:handle 和
函式名():handle()。第一種呼叫預設會傳遞事件物件作為事件函式的引數。第二種呼叫 事件物件必須作為最後一個引數顯示傳遞, 並且事件物件的名稱必須是$event
程式碼演示:
<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>
事件修飾符:
**作用:**在v-on指令加上以 . 開頭的指令字尾,用來對事件進行修飾,有.stop、.prevent、.self等修飾符。修飾符可以串聯同時使用,但是串聯的順序很重要,不同的串聯順序可能會產生不同的結果。
例如: v-on:click.prevent.self 會阻止所有的點選,而 v-on:click.self.prevent 只會阻止對元素自身的點選。
程式碼演示:
<!-- 阻止單擊事件繼續傳播,即阻止冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再過載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯 即阻止冒泡也阻止預設事件 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只當在 event.target 是當前元素自身時觸發處理函式 -->
<!-- 即事件不是從內部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
按鍵修飾符:
作用: v-on
在監聽鍵盤事件時新增按鍵修飾符,即設定只有按下鍵盤上某個鍵的時候,才會觸發呼叫某個函式。按鍵修飾符也可以串聯使用,即按下其中任意一個對應的按鍵,就可以觸發。按鍵修飾符主要作用是代替不容易記住的按鍵碼(keyCode)。keyup(鍵盤事件)是按鍵鬆開,當指定的按鍵鬆開會觸發的事件。
鍵盤的每個按鍵,都有相應的按鍵碼(keyCode),如下圖。
常用的按鍵修飾符有:
.enter => enter鍵
.tab => tab鍵
.delete (捕獲“刪除”和“退格”按鍵) => 刪除鍵
.esc => 取消鍵
.space => 空格鍵
.up => 上
.down => 下
.left => 左
.right => 右
程式碼演示:
<!-- 只有在 `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" >
<!-- 只有在 `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" >
自定義按鍵修飾符別名:
**作用:**在Vue中可以通過config.keyCodes
對鍵盤上的按鍵進行自定義按鍵修飾符別名,可以把常用的按鍵定義別名,方便記憶並呼叫。一般定義在Vue例項之前。
程式碼演示:
<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>
6.v-show和v-if的區別
v-show本質就是標籤display設定為none,控制元素隱藏或者顯示,v-show只編譯一次,後面其實就是控制css,而v-if不停的銷燬和建立,故v-show效能更好一點。
v-if是動態的向DOM樹內新增或者刪除DOM元素,v-if切換有一個區域性編譯/解除安裝的過程,切換過程中合適地銷燬和重建內部的事件監聽和子元件。
所以v-if
有更高的切換開銷,而 v-show
有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show
較好;如果在執行時條件很少改變,則使用 v-if
較好。
7.v-for和v-if
不推薦同時使用v-if和v-for,因為當兩者同時使用時,v-for比v-if的優先順序更高。可能會出現一些意想不到的bug。
使用v-for遍歷物件時,物件中的每一條屬性都對應著一行,即迴圈一次,渲染一次標籤。遍歷陣列時,陣列中每一項對應著一行。
8.v-for跟key
作用: key來給每個節點做一個唯一的標識(通常使用資料的id或者index),主要作用是為了Vue能高效的更新虛擬DOM,可以節約很多系統開銷,提高Vue的效能。
9.自定義指令
作用:當Vue內建的指令無法滿足我們的需求的時候,Vue允許我們自定義指令。自定義指令包括全域性指令和區域性指令。使用自定義的指令,只需在對用的元素中,加上’v-‘的字首形成類似於內部指令’v-if’,'v-text’的形式,定義的時候不需要加 v- 。
用 Vue.directive 來註冊全域性指令:
<div id="app">
<input type="text" v-focus>
</div>
<script>
// 註冊一個全域性自定義指令 v-focus 使某個dom元素獲得焦點
Vue.directive('focus', {
// 當繫結元素插入到 DOM 中。 其中 el為dom元素
inserted: function (el) {
// 聚焦元素
el.focus();
}
});
new Vue({
el:'#app'
});
</script>
Vue.directive 註冊全域性指令時,可以攜帶引數
<div id="app">
<input type="text" v-color='msg'>
</div>
<script type="text/javascript">
Vue.directive('color', {
// bind宣告週期,在指令第一次繫結到元素時呼叫,只能呼叫一次,可以用來進行一次性的初始化設定
// el 為當前自定義指令的DOM元素
// binding 為自定義的函式形參 通過自定義屬性傳遞過來的值 存在 binding.value 裡面
// 此例傳過來的引數是一個物件,所以形參binding裡存放的也是一個物件。
bind: function(el, binding){
// 根據指令的引數設定背景色
el.style.backgroundColor = binding.value.color;
}
});
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'blue'
}
}
});
</script>
自定義註冊區域性指令
區域性指令的用法與全域性指令相同,只是在定義的時候,是在Vue例項裡面通過 directives 來定義,而且使用範圍侷限在當前Vue例項中,當定義的區域性指令和全域性指令發生同名時,Vue會使用區域性指令。
<div>
<input type="text" v-color='msg'>
<input type="text" v-focus>
</div>
<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>
二、表單
1.獲取單選框中的值
可以通過v-model獲得單選框中的值,但多個單選框必須都通過v-model雙向繫結同一個值,每個單選框都要有自己的value屬性,且value值必須唯一,因為是根據value值來確定選擇的是哪一個單選框。當選中某一個單選框時v-model會根據當前單選框的value值改變data繫結的那個資料的值。
程式碼演示:
<div id="app">
<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>
</div>
<script>
new Vue({
el: '#app',
data: {
// 預設會讓當前的 value 值為 2 的單選框選中
gender: 2,
}
})
</script>
2.獲取複選框中的值
也是通過v-model來實現,基本實現與單選框一樣,但有一點: data中雙向繫結的那個資料要定義成陣列形式,否則無法實現多選。
程式碼演示:
<div id="app">
<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({
el: '#app',
data: {
// 預設會讓當前的 value 值為 2 和 3 的複選框選中
hobby: ['2', '3'],
},
})
</script>
3.獲取下拉框和文字框中的值
還是通過v-model來實現,基本實現與上面兩者一樣,需要給select 用v-model雙向繫結data中的一個數據,每個option必須要有value屬性,且value屬性唯一。選中某一個option的時候v-model會根據當前option的value值改變data繫結的那個資料的值。可以通過給select新增一個multiple 屬性來實現下拉框多選,當多選時,需要將data中雙向繫結的那個資料定義成陣列形式。
文字框 textarea 是 一個雙標籤 不需要繫結value 屬性的,他裡面的內容就是他的value值。
程式碼演示:
<div id="app">
<span>職業:</span>
<select v-model='occupation' multiple>
<option value="0">請選擇職業...</option>
<option value="1">教師</option>
<option value="2">軟體工程師</option>
<option value="3">律師</option>
</select>
<!-- -->
<textarea v-model='desc'></textarea>
</div>
<script>
new Vue({
el: '#app',
data: {
// 預設會讓當前的 value 值為 2 和 3 的下拉框選中
occupation: ['2', '3'],
desc: 'nihao'
}
})
</script>
4.表單修飾符
**作用:**用來修飾表單輸入的內容,表單中輸入的內容預設為字串形式。
.number ----- 將表單內輸入的字串轉化為數值型別,當輸入非數字的字元時,無法轉換。
.trim ---- 自動過濾表單中使用者輸入的字串首尾的空白字元,但只能去掉開頭和結尾的空格,字串中間的空格無法去除。
.lazy ---- 延遲了同步更新屬性值的時機,將輸入框的input事件切換成change事件。input事件:當輸入框中的資料發生變化時,其所繫結的值也會立即更新。change事件:當輸入框中的資料發生變化時,其所繫結的值不會立即發生改變,而是在輸入框失去焦點或按下回車鍵的時候,再進行更新。
程式碼演示:
<!-- 自動將使用者的輸入值轉為數值型別 -->
<input v-model.number="age" type="number">
<!--自動過濾使用者輸入的首尾空白字元 -->
<input v-model.trim="msg">
<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg" >
三、計算屬性 computed
**作用:**使用手法與方法 methods 類似,但計算屬性可以使Vue模板變得更簡潔,更高效,因為計算屬性會根據它的響應式依賴進行快取, 計算屬性會把自己第一次計算的結果進行快取,如果它所繫結的物件沒有發生變化,那後面再次呼叫這個計算屬性時,Vue會直接返回快取中的第一次計算的結果。只有當繫結的物件發生變化時,計算屬性才會重新進行計算,大大節約了系統資源。
計算屬性與方法的區別:計算屬性是基於依賴進行快取的,而方法不快取。每次呼叫方法時,方法都會重新進行計算。
程式碼演示:
<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>
才疏學淺,待後補充
四、監聽器(偵聽器) watch
**作用:**watch用來監聽響應資料的變化。一般用於對資料的變化做出相應的反應,執行相應的方法。watch內function前面的名稱就是watch所監聽的屬性。watch所監聽的屬性一定是在 data 中已經定義的資料。但需要監聽一個物件中的資料的變化時,需要用 deep 屬性對物件進行深度監聽,因為普通的 watch 方法無法堅挺到物件內部資料的改變。
程式碼演示:
<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 引數val 就是 firstName 改變後的值
firstName: function(val) {
this.fullName = val + ' ' + this.lastName;
},
// 注意: 這裡 lastName 對應著data 中的 lastName
lastName: function(val) {
this.fullName = this.firstName + ' ' + val;
}
}
});
</script>
才疏學淺,待後補充
五、過濾器 filter
**作用:**Vue允許自定義過濾器,常用於一些文字格式化,過濾器可以在兩個地方被引用:雙花括號的文字插值 以及 v-bind表示式中。支援級聯操作,即同時引用多個過濾器,當引用多個過濾器時,會按照引用順序一一執行,第二個過濾器接受的資料是第一個過濾器過濾結束的資料,第三個過濾器接受的資料是第二個過濾器過濾結束的資料等等;過濾器雖然會對資料進行過濾,但它並不會改變資料本身,只是改變了渲染的結果;過濾器也分為全域性過濾器和區域性過濾器。
程式碼演示:
<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>
才疏學淺,待後補充
六、生命週期
Vue例項從建立到銷燬的過程稱為Vue例項的生命週期,這個過程中會伴隨著一些函式的自呼叫,我們通常稱這些函式為鉤子函式
常用的鉤子函式:
beforeCreate | 在例項初始化完成之後,資料觀測和事件配置完成之前,呼叫此方法。此時data和methods以及頁面的DOM結構都沒有初始化,無法進行任何操作。 |
---|---|
created | 在例項建立完成後,即資料和事件都配置完成後呼叫。此時雖然data和methods都可以使用 但頁面還沒進行渲染 |
beforeMount | 在掛載開始之前被呼叫 此時頁面上還看不到真實資料 只是一個模板頁面而已 |
mounted | el被新建立的vm.$el替換,並掛載到例項上去之後被呼叫。 此時資料已經渲染到頁面上了,在這個鉤子函式裡面我們可以使用一些第三方的外掛 |
beforeUpdate | 資料更新時呼叫,即發生在虛擬DOM打補丁之前。 此時, 頁面上資料還是舊的 |
updated | 資料更新後被呼叫,即虛擬DOM重新渲染和打補丁之後。 此時,頁面上資料已經替換成最新的 |
beforeDestroy | 例項銷燬之前呼叫 |
destroyed | 例項銷燬後呼叫 |
才疏學淺,待後補充
七、陣列
1.陣列的變異方法
變異陣列方法即保持陣列方法原有功能不變的前提下對其進行功能拓展。
push() | 往陣列最後面新增一個元素,成功返回當前陣列的長度 |
---|---|
pop() | 刪除陣列的最後一個元素,成功返回刪除元素的值 |
shift() | 刪除陣列的第一個元素,成功返回刪除元素的值 |
unshift() | 往陣列最前面新增一個元素,成功返回當前陣列的長度 |
splice() | 有三個引數,第一個是想要刪除的元素的下標(必選),第二個是想要刪除的個數(必選),第三個是刪除 後想要在原位置替換的值 |
sort() | sort() 使陣列按照字元編碼預設從小到大排序,成功返回排序後的陣列 |
reverse() | reverse() 將陣列倒序,成功返回倒序後的陣列 |
2.替換陣列的方法
也是對陣列的操作,只不過不會改變原有的陣列,而是返回一個新的陣列
filter | filter() 方法會建立一個新的陣列,新陣列中的元素是通過檢查指定陣列中符合條件的元素,即從一個數組中篩選出符合某些條件的陣列。 |
---|---|
concat | concat() 方法用於連線兩個或多個數組,在不改變現有的陣列的前提下,返回連線後的陣列 |
slice | slice() 方法可從已有的陣列中返回選定的元素,即從一個數組中選定一些元素組成一個新陣列。該方法並不會修改陣列,而是返回一個子陣列 |
3.動態陣列響應
Vue.set(a,b,c) 讓 觸發檢視重新更新一遍,資料動態更新,a是要更改的資料 、 b是資料的第幾項、 c是更改後的資料
才疏學淺,待後補充