Vue指令---總

Vue指令—總

vue.js的指令是帶有特殊前綴"v-"的HTML特性,它綁定一個表達式,並將一些特殊應用到DOM上。

1. v-cloak

v-cloak不需要表達式,它會在Vue實例結束編譯時從綁定的HTML元素上移除,經常和css的display:none;配合使用,可以解決插值表達式的閃爍的問題在vue.js沒有加載之前,頁面會顯示{{msg}},知道vue.js加載完畢之後纔會顯示真正數據

<div id="app" v-cloak>
	{{message}}
</div>
<script>
	var app = new Vue({
		el:'#app',
		data:{
			message:'這是一段文本'
		}
	})
</script>

這時雖然已經加了指令v-cloak,但是其實沒有起到任何作用,當網速較慢、Vue.js文件還沒加載完時,在頁面上會顯示{{message}}的字樣,知道Vue創建實例、編譯模版時,DOM纔會被替換,所以這個過程屏幕是有閃動的。只要加一句css就可以解決這個問題了:

[v-clock]{
	display:none;
}

在一般情況下,v-cloak是一個解決初始化慢導致頁面閃動的最佳實踐,對於簡單的項目很使用,但是在具有工程化的項目裏,比如後面學習webpack和vue-router時,項目的HTML結構只有一個空的div元素,剩餘的內容都是由路由去掛載不同組件完成的,所以不需要v-cloak。

2. v-text/v-html

v-text 是將數據當成普通文本替換整個標籤的內容。

<div id="app1" style="background:green;" v-text="text">
	v-text替換前
</div>
<script>

	var app = new Vue({
		el:'#app1',
		data:{
		text:'<a href="http://www.baidu.com">百度一下</a>'
		}
	})
</script>

v-html 是將數據當成網頁替換整個標籤的內容。

<div id="app2" style="background:yellow;" v-html="link">
	v-html替換前
</div>
<script>
	var app2 = new Vue({
		el:'#app2',
		data:{
			link:'<a href="http://www.baidu.com">百度一下</a>'
		}
	})
</script>

3. v-bind/v-on

v-bind的基本用途是動態更新HTML元素上的屬性,比如id、class等,例如下面幾個示例:

<div id="app">
	<a v-bind:href="url">鏈接</a>
	<img v-bind:src="imgUrl"/>
</div>
<script>
	var app = new Vue({
		el:"#app",
		data:{
			url:"http://www.baidu.com",
			imgUrl:"http://xxx.xxx.xx/imgpng"
		}
	})
</script>

示例中的鏈接地址與圖片的地址都與數據進行了綁定,當通過各種方式改變數據時,鏈接和圖片都會自動更新。上述渲染後的結果爲:

<a href="https://www.baidu.com">鏈接</a>
<img src="http://xxx.xxx.xx/img.png"/>

v-on 是用來綁定事件監聽器的,這樣我們就可以做一些交互了,先來看下面的示例:

<div id="app">
	<p v-if="show">這是一段文本</p>
	<button v-on:click="handleCloseOrShow">點擊隱藏/顯示</button>
</div>
<script>
	var app = new Vue({
		el:"#app",
		data:{
			show:true
		},
		methods:{
			handleCloseOrShow:function(){
				this.show = !this.show
			}
		}

	})
</script>

在button按鈕上,使用v-on:click給該元素綁定了一個點擊事件在普通元素上,v-on可以監聽原聲的DOM事件,除了click外,還有dbclick、keyup、mosemove等。表達式可以是一個方法名,這些方法都寫在Vue實例本身,因此可以直接使用this.xxx的形式來訪問或修改數據,如示例中的this.show = !this.show;當數據show爲true時,就把show修改爲false,所以點擊按鈕時,文本p元素就被移除了;當數據show爲false時,就把show修改爲true,所以點擊按鈕時,文本p元素就被添加上。

下面代碼會報錯,因爲我們給input綁定了alert方法,此時會從ViewModel實例中去找alert方法,但是我們在vm實例中沒有定義這個alert方法,所以報錯。

<input type="button" value="點我1" v-on:click="alert('hello')">

下面的代碼不會報錯,此時就是用普通的js代碼綁定alert事件。

<input type="button" value="點我2" onclick="alert('hello')">

強調: 以後我們凡是看到v-on 綁定信息,都會從VM實例中去找,如果找不到就會報錯。

4. 語法糖

語法糖是指在不影響功能的情況下,添加某種方法實現同樣的效果,從而方便程序開發。
Vue.js的v-bind和v-on指令都提供了語法糖,也可以說是縮寫,比如v-bind,可以省略v-bind直接寫一個冒號“:”。
v-on可以直接用"@"來縮寫。

5. 事件修飾符

在事件處理程序中調用event.preventDefault()或event.stopPropagation()是非常常見的需求。儘管我們可以在方法中輕鬆實現這點,但更好的方式是:方法只有純粹的數據邏輯,而不是去處理DOM事件細節。
爲了解決這個問題,Vue.js爲v-on提供了事件修飾符。在@綁定的事件後加小圓點“.”,再跟一個後綴來使用修飾符。

<!-- 阻止單擊事件冒泡 -->
<a @click.stop="handle"></a>

<!-- 提交事件不再重載頁面-->
<form @submit.prevent="handle"></form>

<!-- 添加事件監聽器時使用事件捕獲模式 -->
<!-- 即元素自身觸發的事件先在此處理,然後才交由內部元素進行處理 -->
<div @click.capture="handle">...</div>

<!-- 只當在event.target是當前元素自身時觸發處理函數 -->
<!-- 即事件不是從內部元素觸發的 -->
<div @click.self="handle">..</div>

<!-- 點擊事件將只會觸發一次 -->
<a @click.once="handle"></a>

在表單元素上監聽鍵盤事件時,還可以使用按鍵修飾符,比如按下具體某個鍵時才調用方法:

<!-- 只有在keyCode是13時調用vm.submit() -->
<input @keyup.13="submit"/>

使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。因此,用v-on:click.prevent.self 會阻止所有的點擊,而v-on:click.self.prevent 只會阻止對元素自身的點擊。

6. Vue的雙向綁定

表單控件在實際業務較爲常見,比如單選、多選、下拉選擇、輸入框等,用它們可以完成數據的錄入、校驗、提交等。Vue.js提供了v-model 指令,用於在表單類元素上雙向綁定數據,例如在輸入框上使用時,輸入的內容會實時映射到綁定的數據上。例如下面例子:

<div id="app">
	<input type="text" v-model="message" placeholder="請輸入..."/>
	<p>輸入的內容是:{{message}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			message:''
		}
	})
</script>

==在輸入=輸入的同時{{message}}也會實時將內容渲染在視圖中。==對與文本域textarea也是同樣的用法。
使用v-model後,表單控件顯示的值只依賴所綁定的數據,不再關心初始化時的value屬性,對於在<textarea></textarea>之間插入的值,也不會生效。
使用v-model時,如果用中文輸入法輸入中文,一般在沒有選定詞組前,也就是在拼音階段,Vue是不會更新數據的,當敲下漢子時纔會觸發更新。如果希望總是實時更新,可以用@input來代替v-model。 事實上v-model也是一個特殊的語法糖,只不過它會在不同的表單上智能處理。例如下面示例:

<div id="app">
	<input type="text" @input="handleInput" />
	<p>輸入的內容是:{{message}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			message:''
		},
		methods:{
			handleInput:function(e){
				this.message = e.target.value
			}
		}
	})
</script>

== 單選按鈕在單獨使用時,不需要v-model,直接使用v-bind==綁定一個布爾類型的值,爲真時選中,爲否時不選,例如:

<div id="app">
	<input type="radio" :checked="picked" />
	<label>單選按鈕</label>
</div>
<script type="text/javascript>
	var app = new Vue({
		el:"#app",
		data:{
			picked:false
		}
	})
</script>

如果是組合使用來實現互斥選擇的效果,就需要v-model配合value來使用:

<div id="app">
	<input type="radio" v-model="picked" value="html" id="html" />
	<label for="html">HTML</label>
	<br>
	<input type="radio" v-model="picked" value="js" id="js" />
	<label for="js">JavaScript</label>
	<br>
	<input type="radio" v-model="picked" value="css" id="css" />
	<label for="css">CSS</label>
	<br>
	<p>選擇的項是:{{picked}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			picked:'js'
		}
	})
</script>

== 複選框也分單獨使用和組合使用,== 不過用法稍與單選不同。複選框單獨使用時,也是用v-model 來綁定一個布爾值,例如:

<div id="app">
	<input type="checkbox" v-model="checked" id="checked">
	<label for="checked">選擇狀態:{{checked}}</lable>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			checked:false
		}
	})
</script>

組合使用時,也是v-model與value一起, 多個勾選框都綁定到同一個數組類型的數據,value的值在數組當中,就會選中這一項。 這一過程也是雙向的,在勾選時,value的值也會自動push到這個數組中,示例代碼如下:

<div id="app">
	<input type="checkbox" v-model="checked" value="html" id="html">
	<label for="html">HTML</label>
	<br>
	<input type="checkbox" v-model="checked" value="js" id="js">
	<label for="js">JavaScript</label>
	<br>
	<input type="checkbox" v-model="checked" value="css" id="css">
	<label for="css">CSS</label>
	<br>
	<p>的選擇項是:{{checkde}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#pp",
		data:{
			checked:[]
		}
	})
</script>

選擇列表就是下拉選擇器,也是常見的表單控件,同樣也分爲單選和多選兩種方式。先看一下單選的示例代碼:

<div id="app">
	<select v-model="selected">
		<option>html</option>
		<option value="js">JavaScript</option>
		<option>css</option>
	</select>
	<p>選擇的項是:{{selected}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			selected:'html'
		}
	})
</script>

<option>是備選項,如果含有value屬性,v-model就會優先匹配value的值;如果沒有,就會直接匹配<option>的text,比如選中第二項時,selected的值是js,而不是javaScript。

<selected>添加屬性multiple就可以多選了,此時v-model綁定的是一個數組,與複選框用法類似, 示例代碼如下:

<div id="app">
	<select v-model="selected" multiple="multiple">
		<option>html</option>
		<option value="js">JavaScript</option>
		<option>css</option>
	</select>
	<p>選擇的項是:{{selected}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			selected:['html','css']
		}
	})
</script>

前面介紹的單選按鈕、複選框和選擇列表在單獨使用或單選的模式下,v-model綁定的值是一個靜態字符串或者布爾值,但在業務中,有時需要綁定一個動態的數據,這時可以用v-bind來實現。
== 單選按鈕:==

<div id="app">
	<input type="radio" v-model="picked" :value="value"/>
	<label>單選按鈕</label>
	<p>{{picked}}</p>
	<p>{{value}}</P>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			picked:false,
			value=123
		}
	})
</script>

在選中時,app.picked === app.value

複選框

<div id="app">
	<input type="checkbox" v-model="toggle" :true-value="value1"
	:false-value="value2" />
	<label>複選框</label>
	<p>{{toggle}}</p>
	<p>{{value1}}</p>
	<p>{{value2}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			toggle:false,
			value1:'a',
			value2:'b'
		}
	})
</script>

勾選時,app.toggle === app.value1;未勾選時,app.toggle === app.value2。

選擇列表:

<div id="app">
	<select v-model="selected">
		<option :value="{number:123}">123</option>
	</select>
	{{selected.number}}
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			selected:''
		}
	})
</script>

當選中時,app.select是一個Object,所以app.selected.num === 123。

7. 與事件的修飾符類似,v-model也有修飾符,用於控制數據同步的時機。

  1. .lazy
    在輸入框中v-model默認是在input事件中同步輸入框的數據,使用修飾符.lazy會轉變爲在change事件中的同步,實例代碼如下:
<div id="app">
	<input type="text" v-model="message"/>
	<p>{{message}}</p>
</div>
<script type="text/javaxcript">
	var app = new Vue({
		el:"#app",
		data:{
			message:''
		}
	})
</script>

這時,message並不是實時改變的,而是在失焦或按回車時才更新。

  1. .number
    使用修飾符.number可以將輸入轉換爲Number類型。否則雖然你輸入的是數字,但它的類型其實是String,比如在數字輸入框時會比較有用,示例代碼如下:
<div id="app">
	<input type="text" v-model.number="message"/>
	<p>{{typeof messsage}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			message:123
		}
	})
</script>
  1. .trim
    修飾符.trim可以自動過濾輸入的首位空格,示例代碼如下:
<div id="app">
	<input type="text" v-model.trim="message"/>
	<p>{{message}}</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			message:''
		}
	})
</script>

8. v-if 、v-else-if、 v-else

與JavaScript的條件語句if、else、else if 類似,Vue.js的條件指令可以根據表達式的值在DOM中渲染或銷燬元素/組件,例如:

<div id="app">
	<p v-if="status === 1"> 當status爲1是顯示該行</p>
	<p v-else-if="status === 2">當status爲2時顯示該行</p>
	<p v-else>否則顯示該行</p>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			starus:1
		}
	})
</script> 

v-else-if 要緊跟 v-if ,v-else 要緊跟 v-else-if , 表達式的值爲真時,當前元素/組件及所有子節點將被渲染,爲假時被移除。如果一次判斷的是多個元素,可以在Vue.js內置的<template>元素上使用條件指令,最終渲染的結果不會包含該元素,例如:

<div id="app">
	<template v-if="status === 1">
		<p>這是一段文本</p>
		<p>這是一段文本</p>
		<p>這是一段文本</p>
	</template>
</div>
<script type="text/javascript">
	var app = new vue({
		el:"#app",
		data:{
			status:1
		}
	})
</script>
		

Vue在渲染元素時,出於效率考慮,會盡可能地服用已有的元素而非重新渲染,比如下面的示例:

<div id="app">
	<template v-if="type === 'name'">
		<label>用戶名:</label>
		<input placeholder="輸入用戶名" />
	</template>
	<template v-else>
		<label>郵箱:</label>
		<input placeholder="輸入郵箱" />
	</template>
	<button @click="handleToggleClick">切換輸入類型</button>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			type:'name'
		},
		methods:{
			handleToggleClick:function(){
				this.type = this.type ==== 'name' ? 'mail':'name'
			}
		}
	})
</script>

鍵入內容後,點擊切換按鈕,雖然DOM變了,但是之前在輸入框鍵入的內容並沒有改變,只是替換了placeholder的內容,說明<input>元素被複用了。
如果你不希望這樣做,可以使用Vue.js提供的key屬性,它可以讓你自己決定是否要複用元素,**key的值必須是唯一的,**例如:

<input placeholder="輸入用戶名" key="name-input"/>
<input placeholder="輸入郵箱" key="mail-input"/>

給兩個<input>元素都增加key後,就不會服用了,切換類型時鍵入的內容也會被刪除,不過<label>元素仍然是被服用,因爲沒有添加key屬性。

9. v-show

v-show 的用法與 v-if 基本一致,只不過 v-show 是改變元素的 css 屬性 display 。當 v-show 表達式的值爲false 時,元素會隱藏,查看DOM結構會看到元素加載了內聯樣式 display:none;

<div id="app">
	<p v-show="status === 1">當status爲1時顯示該行</p>
</div>
<script type="text/javascript>
	var app = new Vue({
		el:"#app",
		data:{
			status:2
		}
	})
</script>

渲染後的結果爲:

<p style="display:none;">當status爲1時顯示該行</p>

v-if 與 v-show 的選擇
v-if 和 v-show 具有類似的功能,不過 v-if 纔是真正的條件渲染,它會根據表達式適當地銷燬或重建元素及綁定的事件或子組件。若表達式初始爲false,則一開始元素/組件並不會渲染,只有當條件第一次變爲真時纔開始編譯。
而v-show只是簡單的css屬性切換,無論條件真與否,都會被編譯。相比之下,v-if更適合條件不經常改變的場景,因爲它切換開銷相對較大,而v-show使用與頻繁切換條件。

10. v-for

當需要將一個數組遍歷或枚舉一個對象循環顯示時,就會用到列表渲染指令v-for。它的表達式需結合 in 來使用,類似 item in items 的形式,看下面的示例:

<div id="app">
	<ul>
		<li v-for="book in books">{{book.name}}>/li>
	</ul>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			books:[
				{name:'《HTML》'},
				{name:'《CSS》'},
				{name:'《JavaScript》'}
			]
		}
	})
</script>

在表達式中,books 是數據,book 是當前數組元素的別名,循環出的每個<li>內的元素都可以訪問到對應的當前數據 book。列表渲染也支持用 of 來代替 in 作爲分隔符,它更接近JavaScript 迭代器的語法:

<li v-for="book of books">{{book.name}}</li>

v-for的表達式支持一個可選參數作爲當前項的索引,例如:

<li v-for="(book,index)" in books">{{book.name}}</li>

與v-if 一樣, v-for 可以用內置標籤 <template>上,將多個元素進行渲染:

<div id="app">
	<ul>
		<template v-for="book in books">
			<li>書名:{{book.name}}</li>
			<li>作者:{{book.author}}</li>
		</template>
	</ul>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			books:[
				{
					name:'《HTML》',
					author:'XXXX'
				}
				{
					name:'《CSS》',
					author:'YYY'
				}
				{
					name:'《JavaScript》',
					author:'ZZZ'
				}
			]
		}
	})
</script>

**除了數組外,對象的屬性也是可以遍歷的,**例如:

<div id="app">
	<span v-for="value in user">{{value}}</span>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			user:{
				name:'張三',
				gender:'男',
				age:'30'
			}
		}
	})
</script>

渲染後的結果爲:

<span>張三</span><span></span><span>30</span>

遍歷對象屬性時有兩個可選參數,分別是鍵名和索引:

<ul>
	<li v-for="(value,key,index) in user">
		{{index}} - {{key}} - {{value}}
	</li>
</ul>

v-for 還可以迭代整數:

<span v-for="n in 10">{{n}}</span>

當Vue正在更細使用 v-for 渲染的元素列表時,它默認使用“就地更新”的策略。如果數據項的順序被改變,Vue將不會移動DOM元素來匹配數據項的順序,而是就地更新每個元素,並且確保它們在每隔索引位置正確渲染。
這個默認的模式是高效的,但是適合用於不依賴子組件狀態或臨時DOM狀態(例如:表單輸入值)的列表渲染輸出。
爲了給Vue一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要爲每項提供唯一key屬性:

<div v-for="item in items" v-bind:key="item.id">
	<!-- 內容 -->
</div>

11. 類操作

在數據綁定中,最常見的兩個需求就是元素的樣式就是元素的樣式名稱class內聯樣式style的動態綁定,它們也是HTML的屬性,因此可以使用v-bind 指令。我們只需要用v-bind計算出表達式最終的字符就可以,不過有時候表達式的邏輯較複雜,使用字符串拼接方法較難閱讀和維護,所以Vue.js增強了對class和style的綁定。
給v-bind:class設置一個對象,可以動態地切換class,例如:

<div id="app">
	<div :class="{'active':isActive}"></div>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			isActive:true
		}
	})
</script>

上述示例中,類名active 依賴於數據isActive,當其爲true時,div會擁有類名active,爲false時則沒有,所以上述最終渲染完的結果是:

<div class="active"></div>

對象中也可以傳入多個屬性,來動態切換class。另外,:class可以與普通class共存,例如:

<div id="app">
	<div class="static" :class="{'active':isActive,'error':isError}">
	</div>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:'#app',
		data:{
			isActive:true,
			isError:false
		}
	})
</script>

:class內的表達式每項爲真時,對應的類名也會更新。比如當isError爲true時,渲染後的結果爲:

<div class="static active error"></div>

當:class的表達式過長或邏輯複雜時,還可以綁定一個計算屬性,這是一種很友好和常見的用法,一般當條件多餘兩個時,都可以使用data或computed,例如使用計算屬性:

<div id="app">
	<div :class="classes"></div>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			isActive:true,
			error:null
		},
		computed:{
			classes:function(){
				return{
					active:this.isActive && !this.error,
					'text-fail':this.error && this.error.type === 'fail'
				}
			}
		}
	})
</script>

當需要應用多個class時,可以使用數組語法,給:class綁定一個數組,應用一個class列表:

<div id="app">
	<div :class="[activeClass,errorClass]"></div>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			activeClass='active',
			errorClass:'error
		}
	})
</script>
		

也可以使用三元表達式類根據條件切換class,例如下面的示例:

<div id="app">
	<div :class="[isActive ? activeClass:'',errorClass]"></div>
</div>

樣式error會始終應用,當數據isActive爲真時,樣式active纔會被應用。class有多個條件,這樣寫較爲繁瑣,可以在數組語法中使用對象語法:

<div id="app">
	<div :class="[{active':isActive},{errorClass]></div>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app"
		data:{
		 isActive"true"
		 errorClass:'error'
		}
	})
</script>

12. 樣式操作

使用v-bind:style(即style)可以給元素綁定內聯樣式,方法與:class類似,也有對象語法和數組語法,看起來很像直接在元素上寫CSS:

 <div id="app">
 	<div :style="{'color':color,'fontSize':fontSize+'px'}">文本</div>
 </div>
 <script type="text/javascript">
 	var app = new Vue({
 		el:"#app",
 		data:{
 			color:'red',
 			fontSize:20
 		}
 	})
 </script>

css屬性名稱使用駝峯命名(camelCase)或短橫分隔命名(keyab-case),渲染後的結果爲:

<div style="color:red;font-size:20px;">文本</div>

大多數情況下,直接寫一長串的樣式不便與閱讀和維護,所以一般寫在data或computed裏,以data爲例改寫上面的實例:

<div id="app"
	<div :style="styles">文本</div>
</div>
<script type="text/javascript">
	var app = new Vue({
		el:"#app",
		data:{
			styles:{
				color:'red',
				fontSize:20+'px'
			}
		}
	})
</script>

應用多個樣式對象時,可以使用數組語法:

<div :style="[styleA,styleB]">文本</div>

在實際業務中,:style的數組語法並不常用,因爲往往可以寫在一個對象裏面;而比較常用的應當是計算屬性。
另外,使用:style時,Vue.js會自動給特殊的css屬性名稱增加前綴,比如transform。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章