1.插值操作
1.1Mustache
如何將data中的文字資料,插入到HTML中呢?
我們已經學習過了,可以通過Mustache語法(也就是雙大括號)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">{{firstName}} {{lastName}}</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
firstName: 'li',
lastName: 'lei'
}
})
</script>
</html>
1.2v-once
我們知道vue中data資料改變的時候,頁面元素的資料也會改變。但是,在某些情況下,我們可能不希望介面隨意的跟隨改變,這個時候,我們就可以使用一個Vue的指令。
v-once:
- 該指令後面不需要跟任何表示式
- 該指令表示元素和元件(元件後面才會學習)只渲染一次,不會隨著資料的改變而改變。
程式碼如下:
1.3v-html
某些情況下,我們從伺服器請求到的資料本身就是一個HTML程式碼,現在我們想將這個html程式碼渲染出來
- 如果我們直接通過{{}}來輸出,會將HTML程式碼也一起輸出。
- 但是我們可能希望的是按照HTML格式進行解析,並且顯示對應的內容。
我們可以看到頁面並不是我們想要的結果,這時候就需要用到v-html
如果我們希望解析出HTML展示,可以使用v-html指令
- 該指令後面往往會跟上一個string型別
- 會將string的html解析出來並且進行渲染
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{message}}</h2>
<h2 v-html="message"></h2>
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
message: '<a href="www.baidu.com">百度一下</a>'
}
})
</script>
</html>
1.4v-text
v-text作用和Mustache比較相似:都是用於將資料顯示在介面中
v-text通常情況下,接受一個string型別
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{message}}</h2>
<h2 v-text="message"></h2>
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
message: '你好呀,小貓咪'
}
})
</script>
</html>
v-text和{{}}的區別:
{{}}不會覆蓋頁面元素中的資料,但是v-text會覆蓋頁面元素中的資料
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{message}},小貓咪</h2>
<h2 v-text="message">,小貓咪</h2>
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
</script>
</html>
1.5v-pre
v-pre用於跳過這個元素和它子元素的編譯過程,用於顯示原本的Mustache語法,不經常用,瞭解一下
比如下面的程式碼:
-
第一個h2元素中的內容會被編譯解析出來對應的內容
-
第二個h2元素中會直接顯示{{message}}
1.6v-cloak
在某些情況下,我們瀏覽器可能會直接顯然出未編譯的Mustache標籤。
下面這段程式碼,你將display: none;去掉就可以看到效果了,display: none就是控制當瀏覽器還沒渲染完成就不顯示頁面元素
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<style type="text/css">
[v-cloak] {
display: none;
}
</style>
<body>
<div id="app">
<h2 v-cloak>Hello {{message}}</h2>
</div>
</body>
<script type="text/javascript">
setTimeout(() => {
new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
},100)
</script>
</html>
2.繫結屬性
前面我們學習的指令主要作用是將值插入到我們模板的內容當中。
但是,除了內容需要動態來決定外,某些屬性我們也希望動態來繫結。
-
比如動態繫結a元素的href屬性
-
比如動態繫結img元素的src屬性
這個時候,我們可以使用v-bind指令:
v-bind用於繫結一個或多個屬性值,或者向另一個元件傳遞props值(這個學到元件時再介紹),在開發中有很多的屬性需要動態繫結,比如圖片的連結src、網站的連結href、動態繫結一些類、樣式等等
v-bind基礎
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<a v-bind:href="link">Vue官網</a>
<img v-bind:src="logoUrl" >
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
link: 'https://cn.vuejs.org/',
logoUrl: 'https://cn.vuejs.org/images/logo.png'
}
})
</script>
</html>
v-bind語法糖
在實際開發中,我們為了簡便通常可以將v-bind簡寫為:
<a :href="link">Vue官網</a>
<img :src="logoUrl" >
v-bind繫結class
v-bind繫結class的語法是:class後面跟的是一個物件
用法一:直接通過{}繫結一個類
<h2 :class="{'active': isActive}">Hello World</h2>
用法二:也可以通過判斷,傳入多個值
當isActive為true時,則active這個類生效,否則不生效
<h2 :class="{'active': isActive}">Hello World</h2>
用法三:和普通的類同時存在,並不衝突
注:如果isActive和isLine都為true,那麼會有title/active/line三個類
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法四:如果過於複雜,可以放在一個methods或者computed中
注:classes是一個計算屬性
<h2 class="title" :class="classes">Hello World</h2>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<style type="text/css">
.aaa{
color: red;
}
.bbb{
font-size: 30px;
}
</style>
<body>
<div id="app">
<h2 class="title" :class="[active,line]">{{message}}</h2>
<h2 :class="getClasses()">{{message}}</h2> //通過方法計算屬性
<h2 :class={'active':true,'line':false}>{{message}}</h2> //active有效 line無效
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
message: '你好呀',
active: 'aaa',
line: 'bbb'
},
methods: {
getClasses: function(){
return [this.active,this.line]
}
}
})
</script>
</html>
3.計算屬性
3.1什麼是計算屬性
我們知道,在模板中可以直接通過插值語法顯示一些data中的資料。但是在某些情況,我們可能需要對資料進行一些轉化後再顯示,或者需要將多個資料結合起來進行顯示。
比如我們有firstName和lastName兩個變數,我們需要顯示完整的名稱。但是如果多個地方都需要顯示完整的名稱,我們就需要寫多個{{firstName}} {{lastName}},這個時候就需要計算屬性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{fullName}}</h2>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
firstName: '王',
lastName: '小明'
},
computed:{
fullName(){
return this.firstName+" "+this.lastName;
}
}
})
</script>
</html>
計算屬性也可以進行一些複雜操作,比如下面這段程式碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{totalPrice}}</h2>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
books: [
{name: 'Java程式設計思想' , price: 99, count: 3},
{name: 'Linux藝術程式設計' , price: 49, count: 13},
{name: '人月神話' , price: 199, count: 2}
]
},
computed:{
totalPrice(){
return this.books.reduce((total,b)=> {
return total+b.price*b.count
},0)
}
}
})
</script>
</html>
3.2計算屬性的get和set
其實每個計算屬性都包含一個getter和一個setter,上面的案例中我們只用到了getter方法,所以省略沒寫,下面我們來看下計算屬性的完整寫法是什麼樣子的。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{fullName}}</h2>
<h2>{{firstName}}</h2>
<h2>{{lastName}}</h2>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
firstName: '王',
lastName: '小明'
},
computed:{
fullName: {
// get方法用於獲取值
get() {
console.log('----呼叫了fullName的get----');
return this.firstName+" "+this.lastName;
},
// set方法用於設定值
set(newValue) {
console.log('----呼叫了fullName的set----');
const names=newValue.split(' ')
this.firstName=names[0]
this.lastName=names[1]
}
}
}
})
</script>
</html>
3.3計算屬性的快取
在之前的例子中我們見到過通過methods來計算屬性的,methods和computed看起來都可以實現我們的功能,那麼為什麼還要多一個計算屬性這個東西呢?原因是因為計算屬性會進行快取,如果多次使用時,計算屬性只會呼叫一次。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{getfullName}}</h2>
<h2>{{getfullName}}</h2>
<h2>{{getfullName}}</h2>
<h2>{{fullName()}}</h2>
<h2>{{fullName()}}</h2>
<h2>{{fullName()}}</h2>
</div>
</body>
<script type="text/javascript">
let app = new Vue({
el: '#app',
data: {
firstName: '王',
lastName: '小明'
},
methods: {
fullName() {
console.log('執行了fullName的方法')
return this.firstName + " " + this.lastName;
}
},
computed: {
getfullName() {
console.log('執行了getfullName的計算屬性')
return this.firstName + " " + this.lastName;
}
}
})
</script>
</html>
通過控制檯的列印結果我們可以看出,fullName執行了三次,而計算屬性只執行了一次
4.事件監聽
在前端開發中,我們需要經常和使用者互動。這個時候,我們就必須監聽使用者發生的時間,比如點選、拖拽、鍵盤事件等等。在Vue中如何監聽事件呢?使用v-on指令
這裡,我們用一個監聽按鈕的點選事件,來簡單看看v-on的使用
下面的程式碼中,我們使用了v-on:click="counter++”
另外,我們可以將事件指向一個在methods中定義的函式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>點選次數{{count}}</h2>
<button type="button" v-on:click="count++">按鈕點選1</button>
<button type="button" v-on:click="btnClick()">按鈕點選2</button>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
count: 0
},
methods: {
btnClick() {
this.count++
}
}
})
</script>
</html>
當然,v-on也有自己的語法糖:@
<button type="button" @click="count++">按鈕點選1</button>
<button type="button" @click="btnClick()">按鈕點選2</button>
4.1v-on引數
當通過methods中定義方法,以供@click呼叫時,需要注意引數問題:
-
情況一:如果該方法不需要額外引數,那麼方法後的()可以不新增。
- 但是注意:如果方法本身中有一個引數,那麼會預設將原生事件event引數傳遞進去
-
情況二:如果需要同時傳入某個引數,同時需要event時,可以通過$event傳入事件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>點選次數{{count}}</h2>
<button type="button" @click="handleAdd">+1</button>
<button type="button" @click="handleAddTen(10,$event)">+10</button>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
count: 0
},
methods: {
handleAdd(event) {
console.log(event)
this.count++
},
handleAddTen(count,event){
console.log(event)
this.count += 10
}
}
})
</script>
</html>
4.2v-on修飾符
在某些情況下,我們拿到event的目的可能是進行一些事件處理。Vue提供了修飾符來幫助我們方便的處理一些事件:
-
.stop - 呼叫 event.stopPropagation()。
-
.prevent - 呼叫 event.preventDefault()。
-
.{keyCode | keyAlias} - 只當事件是從特定鍵觸發時才觸發回撥。
-
.native - 監聽元件根元素的原生事件。
-
.once - 只觸發一次回撥。
5.條件判斷
5.1v-if v-else-if v-else
v-if、v-else-if、v-else,這三個指令與JavaScript的條件語句if、else、else if類似。Vue的條件指令可以根據表示式的值在DOM中渲染或銷燬元素或元件。
簡單的案例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<p v-if="score>90">優秀</p>
<p v-else-if="score>=80">良好</p>
<p v-else-if="score>=60">及格</p>
<p v-else="score<60">不及格</p>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
score: 98
}
})
</script>
</html>
注意:v-if的原理
v-if後面的條件為false時,對應的元素以及其子元素不會渲染。也就是根本沒有不會有對應的標籤出現在DOM中。
5.2條件渲染案例
使用者再登入時,可以切換使用使用者賬號登入還是郵箱地址登入。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<span v-if="type==='username'">
<label for="">使用者賬戶:</label>
<input type="text" placeholder="使用者賬戶">
</span>
<span v-else>
<label for="">郵箱地址:</label>
<input type="text" placeholder="郵箱地址">
</span>
<button @click="handleToggle">切換型別</button>
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
type: 'username'
},
methods:{
handleToggle() {
this.type=this.type === 'email' ? 'username' : 'email'
}
}
})
</script>
</html>
小問題:
如果我們在有輸入內容的情況下,切換了型別,我們會發現文字依然顯示之前的輸入的內容。但是按道理講,我們應該切換到另外一個input元素中了。在另一個input元素中,我們並沒有輸入內容。為什麼會出現這個問題呢?
答案:
這是因為Vue在進行DOM渲染時,出於效能考慮,會盡可能的複用已經存在的元素,而不是重新建立新的元素。在上面的案例中,Vue內部會發現原來的input元素不再使用,直接作為else中的input來使用了。
解決方案:
如果我們不希望Vue出現類似重複利用的問題,可以給對應的input新增key,並且我們需要保證key的不同
5.3v-show
v-show的用法和v-if非常相似,也用於決定一個元素是否渲染
v-if和v-show都可以決定一個元素是否渲染,那麼開發中我們如何選擇呢?
-
v-if當條件為false時,壓根不會有對應的元素在DOM中。
-
v-show當條件為false時,僅僅是將元素的display屬性設定為none而已。
開發中如何選擇呢?
-
當需要在顯示與隱藏之間切片很頻繁時,使用v-show
-
當只有一次切換時,通過使用v-if
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="toggle">切換顯示</button>
<h2 v-show="isShow">我要不要顯示呢</h2>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
toggle() {
this.isShow = !this.isShow
}
}
})
</script>
</html>
6.迴圈遍歷
6.1v-for遍歷陣列
當我們有一組資料需要進行渲染時,我們就可以使用v-for來完成。
-
v-for的語法類似於JavaScript中的for迴圈。
-
格式如下:item in items的形式。
簡單案例,電影列表:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in movies">{{item}}</li>
<li>------我是分割線-----</li>
<li v-for="(movie,index) in movies">
{{index+1}}.{{movie}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
movies: ['星球大戰','盜夢空間','大話西遊','奇幻漂流']
}
})
</script>
</html>
如果在遍歷的過程中不需要使用索引值
-
v-for="item in movies"
-
依次從movies中取出item,並且在元素的內容中,我們可以使用Mustache語法,來使用item
如果在遍歷的過程中,我們需要拿到元素在陣列中的索引值呢?
-
語法格式:v-for=(item, index) in items
-
其中的index就代表了取出的item在原陣列的索引值。
6.2v-for遍歷物件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(value,key,index) in info">
<!-- value表示物件的值,key表示物件的鍵 index表示下標 -->
{{value}}--{{key}}--{{index}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
info: {
name: 'jack',
age: 18,
height: 1.88
}
}
})
</script>
</html>
7.v-model
表單控制元件在實際開發中是非常常見的。特別是對於使用者資訊的提交,需要大量的表單。Vue中使用v-model指令來實現表單元素和資料的雙向繫結。
7.1引入
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
<h2>{{message}}</h2>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
message: ''
}
})
</script>
</html>
案例的解析:
-
當我們在輸入框輸入內容時,因為input中的v-model繫結了message,所以會實時將輸入的內容傳遞給message,message發生改變。
-
當message發生改變時,因為上面我們使用Mustache語法,將message的值插入到DOM中,所以DOM會發生響應的改變。所以,通過v-model實現了雙向的繫結。
7.2v-model原理
v-model其實是一個語法糖,它的背後本質上是包含兩個操作:
-
1.v-bind繫結一個value屬性
-
2.v-on指令給當前元素繫結input事件
也就是說下面的程式碼:等同於下面的程式碼:
<input type="text" v-model="message">
等同於
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
7.3v-model radio
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<label for="male">
<input type="radio" value="male" v-model="gender" id="male"> 男
</label>
<label for="female">
<input type="radio" value="female" v-model="gender" id="female"> 女
</label>
<p>您的選擇是: {{gender}}</p>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
gender: ''
}
})
</script>
</html>
7.4v-model checkbox
核取方塊分為兩種情況:單個勾選框和多個勾選框
單個勾選框:
-
v-model即為布林值。
-
此時input的value並不影響v-model的值。
多個核取方塊:
-
當是多個核取方塊時,因為可以選中多個,所以對應的data中屬性是一個陣列。
-
當選中某一個時,就會將input的value新增到陣列中。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 單個核取方塊 -->
<label for="check">
<input type="checkbox" v-model="checked" id="check">同意協議
</label>
<p>是否選中:{{checked}}</p>
<!-- 多個核取方塊 -->
<label><input type="checkbox" v-model="hobbies" value="籃球">籃球</label>
<label><input type="checkbox" v-model="hobbies" value="足球">足球</label>
<label><input type="checkbox" v-model="hobbies" value="檯球">檯球</label>
<p>您選中的愛好:{{hobbies}}</p>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
checked: false,
hobbies: []
}
})
</script>
</html>
7.6v-model select
和checkbox一樣,select也分單選和多選兩種情況。
單選:只能選中一個值。
-
v-model繫結的是一個值。
-
當我們選中option中的一個時,會將它對應的value賦值到mySelect中
多選:可以選中多個值。
-
v-model繫結的是一個陣列。
-
當選中多個值時,就會將選中的option對應的value新增到陣列mySelects中
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 選擇單個值 -->
<select v-model="mySelect">
<option value="apple">蘋果</option>
<option value="orannge">蘋果</option>
<option value="banana">香蕉</option>
</select>
<p>您最喜歡的水果:{{mySelect}}</p>
<!-- 選擇多個值 -->
<select v-model="mySelects" multiple>
<option value="apple">蘋果</option>
<option value="orannge">蘋果</option>
<option value="banana">香蕉</option>
</select>
<p>您最喜歡的水果:{{mySelects}}</p>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
mySelect: 'apple',
mySelects: []
}
})
</script>
</html>
7.7修飾符
lazy修飾符:
預設情況下,v-model預設是在input事件中同步輸入框的資料的。也就是說,一旦有資料發生改變對應的data中的資料就會自動發生改變。lazy修飾符可以讓資料在失去焦點或者回車時才會更新。
number修飾符:
預設情況下,在輸入框中無論我們輸入的是字母還是數字,都會被當做字串型別進行處理。但是如果我們希望處理的是數字型別,那麼最好直接將內容當做數字處理。number修飾符可以讓在輸入框中輸入的內容自動轉成數字型別:
trim修飾符:
如果輸入的內容首尾有很多空格,通常我們希望將其去除。trim修飾符可以過濾內容左右兩邊的空格
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model.lazy="message">
<p>當前內容:{{message}}</p>
年齡:<input type="number" v-model.number="age">
<p>年齡:{{age}} 型別:{{typeof age}}</p>
<input type="text" v-model.trim="message2">
<p>當前內容:----{{message2}}----</p>
</div>
</body>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
message: '',
message2: '',
age:0
}
})
</script>
</html>
7.值繫結
初看Vue官方值繫結的時候,我很疑惑:what the hell is that?但是仔細閱讀之後,發現很簡單,就是動態的給value賦值而已:
我們前面的value中的值,可以回頭去看一下,都是在定義input的時候直接給定的。但是真實開發中,這些input的值可能是從網路獲取或定義在data中的。所以我們可以通過v-bind:value動態的給value繫結值。這不就是v-bind嗎?這裡不再給出對應的程式碼,因為會用v-bind,就會值繫結的應用了。