vue快速入門
1. 入門篇
1-1. Vue介紹
介紹: Vue(讀音/vjuː/,類似於view) 是一套用於構建前後端分離的框架。剛開始是由國內優秀選手尤雨溪開發出來的,目前是全球“最”流行的前端框架。使用vue開發網頁很簡單,並且技術生態環境完善,社區活躍,是前後端找工作必備技能!
1-2. Vue安裝
安裝: vue的安裝大體上分成三種方式:
- 通過script標籤引用的
- 通過npm(node package manager)來安裝
- 通過vue-cli命令行來安裝
tips: 作爲初學者,建議直接通過第一種方式來安裝
html中配置環境:
# 開發環境
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
# 或者是指定版本號
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
# 或者是下載代碼保存到本地
<script src="lib/vue.js"></script>
# 生產環境,使用壓縮後的文件
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
2. 基礎篇
2-1. 基本使用
2-1-1. 創建一個Vue對象
介紹: 要使用Vue,首先需要創建一個Vue對象,並且在這個對象中傳遞el參數,el參數全稱是element,用來找到一個給vue渲染的根元素。並且我們可以傳遞一個data參數,data中的所有值都可以直接在根元素下使用{{}}來使用。
示例代碼:
<div id="app">
<p>{{username}}</p>
</div>
<script>
let vm = new Vue({
el: "#app", <!-- 傳遞給id=app -->
data: {
"username": "myname"
}
});
</script>
vue中data數據: 只能在vue的根元素下使用,在其他地方是不能被vue識別和渲染的。
<div id="app">
</div>
<!-- 這裏渲染不了 -->
<p>{{username}}</p>
<script>
let vm = new Vue({
el: "#app",
data: {
"username": "myname"
}
});
</script>
vue中methods方法: 這個屬性中專門用來存儲自己的函數。methods中的函數也可以在模板中使用,並且在methods中的函數來訪問data中的值,只需要通過this.屬性名就可以訪問到了,不需要額外加this.data.屬性名來訪問。
<div id="app">
<p>{{greet()}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"username": "myname"
},
methods: {
greet: function(){
return "晚上好!" + this.username
}
}
});
</script>
2-2. Vue模板語法
2-2-1. 文本
介紹: 在html中通過{{}}(雙大括號)中可以把Vue對象中的數據插入到網頁中。並且只要Vue對象上對應的值發生改變了,那麼html中雙大括號中的值也會立馬改變。
示例代碼:
<div id="app">
<p>{{username}}</p>
<button v-on:click="change">點擊修改</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"username": "myname"
},
methods: {
change: function(){
this.username = 'China';
}
}
});
</script>
如果在html的{{}}中,第一次渲染完成後,不想要跟着後期數據的更改而更改,那麼可以使用v-once指令來實現。
<p v-once>{{username}}</p>
2-2-2. 顯示原生的HTML
介紹: 有時候我們的Vue對象中,或者是後臺返回給我們一個段原生的html代碼,我們需要渲染出來,那麼如果直接通過{{}}渲染,會把這個html代碼當做字符串。這時候我們就可以通過v-html指令來實現。
示例代碼:
<div id="app">
<div v-html="code"></div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"code": "<a href='https://www.baidu.com/'>百度一下,你就知道!</a>"
}
});
</script>
2-2-3. 屬性綁定
介紹: 如果我們想要在html元素的屬性上綁定我們Vue對象中的變量,那麼需要通過v-bind來實現。
示例代碼:
<div id="app">
<img v-bind:src="imgSrc" alt="">
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"imgSrc": "https://i.ytimg.com/vi/5HKZ6bU6Zg0/maxresdefault.jpg"
}
});
</script>
2-2-4. 屬性綁定class和style
綁定class:
- 數組方式
<div id="app">
<p v-bind:class="[classname1,classname2]">你好,世界</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
classname1: "pcolor",
classname2: "pfont"
}
});
</script>
- 對象的方式
<div id="app">
<p v-bind:class="{pcolor:isColor,pfont:isFont}">你好,世界</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
isColor: true,
isFont: true
}
});
</script>
綁定style:
- 數組的方式
<li :style="[liStyle1,liStyle2]">首頁</li>
<script>
new Vue({
el: "#app",
data: {
liStyle: {
backgroundColor: "red",
fontSize: "14px"
},
liStyle2: {
fontWeight: 800
}
}
})
</script>
- 對象的方式
# 讀取對應樣式的值
<li :style="{backgroundColor:pBgColor,fontSize:pFontSize}">首頁</li>
# 或者是直接讀取整個字符串
<li :style="liStyle">首頁</li>
## tips :如果有橫線,則都需要變成駝峯命名的方式
2-2-5. 使用javaScript表達式
示例:
<div id="app">
<p v-bind:style="{color:color?'red':'blue'}">{{username.split(" ").reverse().
join(" ")}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
username: "luoji ketang",
color: false
}
});
</script>
// tips: 只能是JavaScript表達式,不能是語句,比如var a=1;a=2;這樣的是js語句,不是表達式了
2-2-6. 條件判斷
參數: v-if、v-else-if以及v-else
示例1:
<div id="app">
<p v-if="weather == 'sun'">今天去公園玩!</p>
<p v-else-if="weather == 'rain'">今天去看電影!</p>
<p v-else>今天哪兒也不去!</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
weather: 'sun'
}
});
</script>
示例2,加載多個html元素:
<div id="app">
<template v-if="age<18">
<p>數學多少分?</p>
<p>英語多少分?</p>
</template>
<template v-else-if="age>=18 && age<25">
<p>女朋友找到了嗎?</p>
<p>考研究生了嗎?</p>
</template>
<template v-else>
<p>二胎生了嗎?</p>
<p>工資多少?</p>
</template>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
age: 24
}
});
</script>
**tips:**在模板中,Vue會盡量重用已有的元素,而不是重新渲染,這樣可以變得更加高效。
示例3,允許用戶在不同的登錄方式之間切換:
<div id="app">
<template v-if="loginType=='username'">
<label for="username">用戶名:</label>
<input type="text" id="username" name="username" placeholder="用戶名" key
="username">
</template>
<template v-else-if="loginType=='email'">
<label for="email">郵箱:</label>
<input type="text" id="email" name="email" placeholder="郵箱" key="emai
l">
</template>
<div>
<button v-on:click="changeLoginType">切換登錄類型</button>
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
loginType: "username"
},
methods: {
changeLoginType: function(event){
this.loginType = this.loginType=="username"?"email":"username";
}
}
});
</script>
// tips: 加上唯一的key屬性, 可以讓html元素每次切換的時候都重新渲染一遍
2-2-7. v-show和v-if
介紹: v-if是“真正”的條件渲染,因爲它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷燬和重建。
v-if也是惰性的:如果在初始渲染時條件爲假,則什麼也不做——直到條件第一次變爲真時,纔會開始渲染條件
塊。 相比之下,v-show就簡單得多——不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於CSS進
行切換。 一般來說, v-if有更高的切換開銷,而v-show有更高的初始渲染開銷。因此,如果需要非常頻繁地切
換,則使用v-show較好;如果在運行時條件很少改變,則使用v-if較好。
循環:
- 循環數組:
<div id="app">
<table>
<tr>
<th>序號</th>
<th>標題</th>
<th>作者</th>
</tr>
// (第一個爲要循環的,類似python中的i)
<tr v-for="(book,index) in books">
<td>{{index}}</td>
<td>{{book.title}}</td>
<td>{{book.author}}</td>
</tr>
</table>
</div>
- 循環對象
循環對象跟循環數組是一樣的。並且都可以在循環的時候使用接收多個參數。
<div id="app">
<div v-for="(value,key) in person">
{{key}}:{{value}}
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
person: {
"username": "myname",
"age": 18,
"homepage": "https://www.baidu.com/"
}
}
});
</script>
- 保持狀態
循環出來的元素,如果沒有使用 key 元素來唯一標識,如果後期的數據發生了更改,默認是會重用的,並且元素的順序不會跟着數據的順序更改而更改。
<div id="app">
<div v-for="(book,index) in books">
<label for="book">{{book}}</label>
<input type="text" v-bind:placeholder="book">
</div>
<button v-on:click="changeBooks">更換圖書</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
books: ['三國演義','水滸傳','紅樓夢','西遊記']
},
methods: {
changeBooks: function(event){
this.books.sort((x,y) => {
return 5 - parseInt(Math.random()*10)
});
}
}
});
</script>
2-2-8. 觸發試圖更新
介紹: Vue 對一些方法進行了包裝和變異,以後數組通過這些方法進行數組更新,會出發視圖的更新。
- push() :添加元素的方法。
this.books.push("python")
- pop() :刪除數組最後一個元素。
this.books.pop()
- shift() :刪除數組的第一個元素。
this.books.shift()
- unshift(item) :在數組的開頭位置添加一個元素。
this.books.unshift("name")
- splice(index,howmany,item1,…,itemX) :向數組中添加或者刪除或者替換元素。
// 向books第0個位置添加元素
this.books.splice(0,0,"金瓶梅")
// 下標從0開始,刪除2個元素
this.books.splice(0,2)
// 下標從0開始,替換2個元素
this.books.splice(0,2,'金瓶梅','駱駝祥子')
- sort(function) :排序。
this.books.sort(function(x,y){
// 取兩個隨機數排序
a = Math.random();
b = Math.random();
return a-b;
});
- reverse() :將數組元素進行反轉。
this.books.reverse();
2-2-9. 視圖更新注意事項
- 直接修改數組中的某個值是不會出發視圖更新的。比如:
this.books[0] = 'Python';
這種情況應該改成用 splice 或者是用 Vue.set 方法來實現:
Vue.set(this.books,0,'Python');
- 如果動態的給對象添加屬性,也不會觸發視圖更新。只能通過 Vue.set 來添加。比如:
<div id="app">
<ul>
<li v-for="(value,name) in person">{{name}}:{{value}}</li>
</ul>
<script>
let vm = new Vue({
el: "#app",
data: {
person: {"username": 'myname'}
},
methods: {
changePerson: function(event){
Vue.set(this.person,'age',18)
}
}
});
</script>
</div>
2-2-10. 事件綁定
介紹: 事件綁定就是在 HTML 元素中,通過 v-on 綁定事件的。事件代碼可以直接放到 v-on 後面,也可以寫成一個函數。
示例代碼:
<div id="app">
<p>{{count}}</p>
<button v-on:click="count+=1">加</button>
<button v-on:click="subtract(10)">減10</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
count: 0
},
methods: {
subtract: function(value){
this.count -= value;
}
}
});
</script>
2-2-11. 傳入event參數
**介紹:**如果在事件處理函數中,想要獲取原生的 DOM 事件,那麼在 html 代碼中,調用的時候,可以傳遞一個 $event 參數。
代碼示例:
<button v-on:click="subtract(10,$event)">減10</button>
...
<script>
...
methods: {
subtract: function(value,event){
this.count -= value;
console.log(event);
}
}
...
</script>
3. 高級篇:
3-1. 計算機屬性和監聽器
介紹: 一般情況下屬性都是放到 data 中的,但是有些屬性可能是需要經過一些邏輯計算後才能得出來,那麼我們可以把這類屬性變成計算屬性。比如以下:
<div id="app">
<label for="length">長:</label>
<input type="number" name="length" v-model:value="length">
<label for="width">寬:</label>
<input type="number" name="width" v-model:value="width">
<label for="area">面積:</label>
<input type="number" name="area" v-bind:value="area" readonly>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
length: 0,
width: 0,
},
computed: {
area: function(){
return this.length*this.width;
}
}
});
</script>
3-2. 計算屬性的set
介紹: 計算屬性默認只有 get ,不過在需要時你也可以提供一個set ,但是提供了 set 就必須要提供 get方法。示例代碼如下:
代碼示例:
<div id="app">
<div>
<label>省:</label>
<input type="text" name="province" v-model:value="province">
</div>
<div>
<label>市:</label>
<input type="text" name="city" v-model:value="city">
</div>
<div>
<label>區:</label>
<input type="text" name="district" v-model:value="district">
</div>
<div>
<label>詳細地址:</label>
<input type="text" name="address" v-model:value="address">
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
district: "",
city: "",
province: ""
},
computed: {
address: {
get: function(){
let result = "";
if(this.province){
result = this.province + "省";
}
if(this.city){
result += this.city + "市";
}
if(this.district){
result += this.district + "區";
}
return result;
},
set: function(newValue){
let result = newValue.split(/省|市|區/)
if(result && result.length > 0){
this.province = result[0];
}
if (result && result.length > 1){
this.city = result[1];
}
if(result && result.length > 2){
this.district = result[2];
}
}
}
}
});
</script>
3-3. 監聽屬性
介紹: 監聽屬性可以針對某個屬性進行監聽,只要這個屬性的值發生改變了,那麼就會執行相應的函數。
示例代碼:
<div id="app">
<div>
<label>搜索:</label>
<input type="text" name="keyword" v-model:value="keyword">
</div>
<div>
<p>結果:</p>
<p>{{answer}}</p>
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
keyword: "",
answer: ""
},
watch: {
keyword: function(newKeyword,oldKeyword){
this.answer = '加載中...';
let that = this;
setTimeout(function(){
that.answer = that.keyword;
},Math.random()*5*1000);
}
}
});
</script>
3-4. 表單輸入綁定
3-4-1. 表單輸入綁定
介紹: v-model指定可以實現表單值與屬性的雙向綁定。即表單元素中更改了值會自動的更新屬性中的值,屬性中的值更新了會自動更新表單中的值。
綁定的屬性和事件:
v-model在內部爲不同的輸入元素使用不同的屬性並拋出不同的事件:
- text和textarea元素使用value屬性和input事件。
- checkbox和radio使用checked屬性和change事件。
- select字段將value作爲prop並將change作爲事件。
3-4-2. 表單元素綁定
input綁定:
v-model是v-model:value的縮寫,改變 input標籤中的值 可以改變下面的屬性
<input v-model="message" placeholder="請輸入...">
<input v-model:value="message" placeholder="請輸入...">
<p>輸入的內容是:{{ message }}</p>
new Vue({
el: '#example-3',
data: {
message: ""
}
})
textarea綁定:
<span>輸入的內容是:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="請輸入多行內容..."></textarea>
checkbox綁定:
<div id='example-3'>
<input type="checkbox" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
new Vue({
el: '#example-3',
data: {
checkedNames: []
}
})
radio綁定:
<div id="example-4">
<input type="radio" value="男" v-model="gender">
<label>男</label>
<br>
<input type="radio" value="女" v-model="gender">
<label>女</label>
<br>
<span>Picked: {{ gender }}</span>
</div>
new Vue({
el: '#example-4',
data: {
gender: ''
}
})
select綁定:
<div id="example-5">
<select v-model="selected">
<option disabled value="">請選擇</option>
# 如果有value值 選擇的就是value值
<option value="1">A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: '...',
data: {
selected: ''
}
})
3-4-3. 修飾符
.lazy :
在默認情況下,v-model在每次input事件觸發後將輸入框的值與數據進行同步 (除了上述輸入法組合文字時)。你可以添加lazy修飾符,從而轉變爲使用change事件進行同步:
<!-- 在"change"時而非"input"時更新 光標移除input輸入框的時候 -->
<input type="text" v-model:value.lazy="message">
<input v-model.lazy="message" >
new Vue({
el: '#app',
data: {
message: ''
}
})
.number :
可以將用戶的輸入值轉爲數值類型。
<input v-model.number="age" type="number">
tips:這通常很有用,因爲即使在type="number"時,HTML輸入元素的值也總會返回字符串。如果這個值無法被parseFloat()解析,則會返回原始的值。
.trim :
如果要自動過濾用戶輸入的首尾空白字符,可以給 v-model 添加 trim 修飾符。
<input v-model.trim="msg">
3-5. 自定義組件
3-5-1. 介紹:
有時候有一組html結構的代碼,並且這個上面可能還綁定了事件。然後這段代碼可能有多個地方都被使用到了,如果都是拷貝來拷貝去,很多代碼都是重複的,包括事件部分的代碼都是重複的。那麼這時候我們就可以把這些代碼封裝成一個組件,以後在使用的時候就跟使用普通的html元素一樣,拿過來用就可以了。
3-5-2. 基本使用:
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
Vue.component('button-counter', {
template: '<button v-on:click="count+=1">點擊了{{ count }}次</button>'
data: function(){
return {
count: 0
}
},
});
let vm = new Vue({
el: "#app",
data: {}
});
</script>
以上我們創建了一個叫做button-counter的組件,這個組件實現了能夠記錄點擊了多少次按鈕的功能。後期如果我們想要使用,就直接通過button-counter使用就可以了。然後因爲組件是可複用的Vue實例,所以它們與newVue接收相同的選項,例如data、computed、watch、methods以及生命週期鉤子等。僅有的例外是像el這樣根實例特有的選項。另外需要注意的是:組件中的data必須爲一個函數!
3-5-3. 給組件添加屬性
介紹: 像原始的html元素都有自己的一些屬性,而我們自己創建的組件,也可以通過prop來添加自己的屬性。這樣別人在使用你創建的組件的時候就可以傳遞不同的參數了。
代碼示例:
<div id="app">
<blog-post v-for="blog in blogs" :title="blog.title"></blog-post>
<blog-post v-bind:blogs="blogs"></blog-post>
</div>
<script>
Vue.component('blog-post', {
props: ['blogs'],
template: `
<table>
<tr>
<th>序號</th>
<th>標題</th>
</tr>
<tr v-for="(blog,index) in blogs">
<td>{{index+1}}</td>
<td>{{blog.title}}</td>
</tr>
</table>
`
})
new Vue({
el: "#app",
data: {
blogs: [
{"title":"鋼鐵是怎樣練成的?","id":1},
{"title":"AI會毀滅人類嗎?","id":2},
{"title":"如何學好Vue!","id":3},
]
}
});
</script>
3-5-4. 單一根元素
介紹: 如果自定義的組件中,會出現很多html元素,那麼根元素必須只能有一個,其餘的元素必須包含在這個根元素中。
代碼示例:
// 錯誤的:
<h3>{{ title }}</h3>
<div v-html="content"></div>
// 正確的:
<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
3-5-5. 子組件事件和傳遞事件到父組件
介紹: 子組件中添加事件跟之前的方式是一樣的,然後如果發生某個事件後想要通知父組件,那麼可以使用this.$emit函數來實現。
代碼示例:
<div id="app">
<blog-item v-for="blog in blogs" v-bind:blog="blog" @check-changed="checks">
</blog-item>
<div v-for="blog in componentblog">
{{blog.title}}
</div>
</div>
<script>
Vue.component('blog-item',{
props:['blog'],
template:`
<div>
<span>{{blog.title}}</span>
<input type="checkbox" @click="onCheck">
</div>
`,
methods:{
onCheck:function(){
// console.log(123)
this.$emit('check-changed',this.blog)
}
}
})
new Vue({
el: '#app',
data: {
blogs:[
{"title":"鋼鐵是怎樣練成的?","id":1},
{"title":"AI會毀滅人類嗎?","id":2},
{"title":"如何學好Vue!","id":3},
],
componentblog:[]
},
methods:{
checks:function(blog){
// indexOf 判斷某個元素在數組中的位置,返回下標
var index = this.componentblog.indexOf(blog)
if(index >= 0){
this.componentblog.splice(index,1)
}else{
this.componentblog.push(blog)
}
console.log(blog)
}
}
})
</script>
tips: 需要注意的是,因爲html中大小寫是不敏感的,所以在定義子組件傳給父組件事件名稱的時候,不要使用myEvent這種駝峯命名法,而是使用my-event這種規則。
3-5-6. 自定義組件v-model
介紹: 一個組件上的v-model默認會利用名爲value的prop(屬性)和名爲input的事件,但是像單選框、複選框等類型的輸入控件可能會將value特性用於不同的目的。這時候我們可以在定義組件的時候,通過設置model選項可以用來實現不同的處理方式。
代碼示例:
<div id="app">
<stepper v-model:value="goods_count"></stepper>
</div>
<script>
Vue.component('stepper',{
props:['count'],
model:{
event: 'count-changed',
prop: "count"
},
template:`
<div>
<button @click="sub">-</button>
<span>{{count}}</span>
<button @click="add">+</button>
</div>
`,
methods:{
sub:function(){
this.$emit("count-changed", this.count-1)
},
add:function(){
this.$emit("count-changed", this.count+1)
}
}
});
new Vue({
el: "#app",
data:{
"goods_count":0
}
})
</script>
tips: 其中的props定義的屬性分別是給外面調用組件的時候使用的。model中定義的prop:'count’是告訴後面使用v-model的時候,要修改哪個屬性;event:'count-changed’是告訴v-model,後面觸發哪個事件的時候要修改屬性。
3-5-7. 插槽
介紹: 我們定義完一個組件後,可能在使用的時候還需要往這個組件中插入新的元素或者文本。這時候就可以使用插槽來實現。
代碼示例:
<div id="app">
<navigation-link url="/profile/">
個人中心
</navigation-link>
</div>
<script>
Vue.component('navigation-link', {
props: ['url'],
template: `
<a v-bind:href="url" class="nav-link">
<slot></slot>
</a>
`
})
new Vue({
el: "#app"
});
</script>
當組件渲染的時候,將會被替換爲“個人中心”。插槽內可以包含任何模板代碼,包括HTML:
<navigation-link url="/profile">
<!-- 添加一個 Font Awesome 圖標 -->
<span class="fa fa-user"></span>
個人中心
</navigation-link>
tips: 如果沒有包含一個元素,則該組件起始標籤和結束標籤之間的任何內容都會被拋棄。
3-6. 生命週期函數&過濾器
3-6-1. 生命週期函數介紹:
生命週期函數代表的是 Vue 實例,或者是 Vue 組件,在網頁中各個生命階段所執行的函數。生命週期函數可以分爲創建階段和運行期間以及銷燬期間。
其中創建期間的函數有 beforeCreate 、 created 、 beforeMount 、 mounted ;
運行期間的函數有 beforeUpdate 、 updated ;
銷燬期間有 beforeDestroy 、 destroyed 。
以下是官方文檔給到的一張圖,從這種圖中我們可以瞭解到每個部分執行的函數。
3-6-1-1. 創建期間
-
beforeCreate:
Vue 或者組件剛剛實例化, data 、 methods 都還沒有被創建。 -
created:
此時 data 和 methods 已經被創建,可以使用了。模板還沒有被編譯。 -
beforeMount:
created 的下一階段。此時模板已經被編譯了,但是並沒有被掛在到網頁中。 -
mounted:
模板代碼已經被加載到網頁中了。此時創建期間所有事情都已經準備好了,網頁開始運行了。
2-6-1-2. 運行期間
- beforeUpdate:
在網頁網頁運行期間, data 中的數據可能會進行更新。在這個階段,數據只是在 data 中更新了,但是並沒有在模板中進行更新,因此網頁中顯示的還是之前的。 - updated:
數據在 data 中更新了,也在網頁中更新了。
2-6-1-3. 銷燬期間
- beforeDestroy:
Vue 實例或者是組件在被銷燬之前執行的函數。在這一個函數中 Vue 或者組件中所有的屬性都是可以使用的。 - destroyed:
Vue 實例或者是組件被銷燬後執行的。此時 Vue 實例上所有東西都會解綁,所有事件都會被移除,所有子元素都會被銷燬。
3-6-2. 過濾器
3-6-2-1. 過濾器介紹
過濾器就是數據在真正渲染到頁面中的時候,可以使用這個過濾器進行一些處理,把最終處理的結果渲染到網頁中。
3-6-2-2. 過濾器的使用
過濾器可以用在兩個地方:雙花括號插值**和 v-bind 表達式 (後者從2.1.0+開始支持)。過濾器應該被添加在JavaScript 表達式的尾部,由“管道”符號指示:
代碼示例:
<!-- 在雙花括號中 -->
{{ message|capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId|formatId"></div>
3-6-2-3. 過濾器的定義
定義本地的過濾器:
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
全局定義過濾器:
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
3-7. Vue-Router
3-7-1. Vue-Router介紹及安裝
3-7-1-1. 介紹:
Vue-Router 是用來將一個 Vue 程序的多個頁面進行路由的。比如一個 Vue 程序(或者說一個網站)有登錄 、 註冊 、 首頁 等模塊,那麼我們就可以定義 /login 、 /register 、 / 來映射每個模塊。
官方文檔:
https://router.vuejs.org/zh/
3-7-1-2. 安裝:
- 通過 script 加載進來:
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
- 通過 npm 安裝: npm install vue-router
3-7-2. Vue-Router基礎
3-7-2-1. 路由基本
介紹: 在網頁中,經常需要發生頁面更新或者跳轉。這時候我們就可以使用 Vue-Router 來幫我們實現。
Vue-Router 是用來做路由的,也就是定義 url規則 與具體的 View 映射的關係。可以在一個單頁面中實現數據的更新。
安裝:
- 1.使用 CDN:
- 加載最新的:
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
- 加載指定版本的:
<script src="https://unpkg.com/[email protected]/dist/vue-router.js"></script>
- 加載最新的:
3-7-2-2. 基本使用:
代碼示例:
<div id="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<ul class="nav nav-tabs">
<li role="presentation" class="active"><router-link to="/find">發現音樂</router-link></li>
<li role="presentation"><router-link to="/my">我的音樂</router-link></li>
<li role="presentation"><router-link to="/friend">朋友</router-link></li>
</ul>
<!-- 路由出口 -->
<!-- 路由匹配到的組件將渲染在這裏 -->
<router-view></router-view>
</div>
</div>
</div>
</div>
<script>
var find = Vue.extend({template: "<h1>發現音樂</h1>"});
var my = Vue.extend({template: "<h1>我的音樂</h1>"});
var friend = Vue.extend({template:"<h1>朋友</h1>"});
var routes = [
{path: "/find",component: find},
{path: "/my",component: my},
{path: "/friend",component: friend},
{path: "/",component:find}
]
const router = new VueRouter({routes});
new Vue({router}).$mount("#app");
</script>
解釋:
- 在 vue-router 中,使用
<router-link>
來加載鏈接,然後使用 to 表示跳轉的鏈接。vue-router 最終會把<router-link>
渲染成<a>
標籤。 <router-view>
是路由的出口,也就是相應 url 下的代碼會被渲染到這個地方來。Vue.extend
是用來加載模板的。routes
是定義一個 url 與組件的映射,這個就是路由。VueRouter
創建一個路由對象。
3-7-2-3. 動態路由
在路由中有一些參數是會變化的,比如查看某個用戶的個人中心,那肯定需要在 url 中加載這個人的 id ,這時候就需要用到動態路由了。
代碼示例:
div id="app">
<router-link to="/user/123">個人中心</router-link>
<router-view></router-view>
</div>
<script>
let UserProfile = {template:"<h1>個人中心:{{$route.params.userid}}</h1>"}
var routes = [
{path: "/user/:userid",component: UserProfile}
]
const router = new VueRouter({routes});
new Vue({router}).$mount("#app");
</script>
解釋:
:userid
:動態的參數。this.$route.params
:這個裏面記錄了路由中的參數。
3-7-2-4. 組件複用
當使用路由參數時,例如從 /user/foo 導航到 /user/bar ,原來的組件實例會被複用。因爲兩個路由都渲染同個組件,比起銷燬再創建,複用則顯得更加高效。不過,這也意味着組件的生命週期鉤子不會再被調用。複用組件時,想對路由參數的變化作出響應的話,你可以簡單地 watch(監測變化)``$route 對象:
代碼示例:
const User = {
template: '...',
watch: {
'$route' (to, from) {
// 對路由變化作出響應...
}
}
}
導航守衛代碼示例:
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
}
3-7-3. Vur-Router進階
3-7-3-1. 匹配404錯誤
在路由規則中, *
代表的是任意字符。所以只要在路由的最後添加一個 *
路由,那麼以後沒有匹配到的url 都會被導入到這個視圖中。
代碼示例:
let UserProfile = {template:"<h1>個人中心:{{$route.params.userid}}</h1>"};
let NotFound = {template: "<h1>您找的頁面已經到火星啦!</h1>"}
var routes = [
{path: "/user/:userid",component: UserProfile},
{path: "*",component: NotFound},
]
3-7-3-2. 嵌套路由
有時候在路由中,主要的部分是相同的,但是下面可能是不同的。比如訪問用戶的個人中心是/user/111/profile/
,查看用戶發的貼子是 /user/111/posts/
等。這時候就需要使用到嵌套路由。
代碼示例:
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// 當 /user/:id/profile 匹配成功,
// UserProfile 會被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 當 /user/:id/posts 匹配成功
// UserPosts 會被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
});
3-7-3-3. 編程式導航
之前我們學習了使用 <router-link>
可以在用戶點擊的情況下進行頁面更新。但有時候我們想要在 js 中手動的修改頁面的跳轉,這時候就需要使用編程式導航了。
$router.push
跳轉:
想要導航到不同的 URL ,則使用 router.push
方法。這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器後退按鈕時,則回到之前的 URL 。
當你點擊 <router-link>
時,這個方法會在內部調用,所以說,點擊 <router-link :to="...">
等
同於調用 router.push(...)
。
聲明式 | 編程式 |
---|---|
<router-link :to="..."> |
router.push(...) |
代碼示例:
// 字符串
router.push('home')
// 對象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意: 如果提供了 path
, params
會被忽略,上述例子中的 query
並不屬於這種情況。取而代之的是
下面例子的做法,你需要提供路由的 name
或手寫完整的帶有參數的 path :
代碼示例:
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 這裏的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
router.replace(location, onComplete?, onAbort?) :
跟 router.push
很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。
router.go(n) :
這個方法的參數是一個整數,意思是在 history 記錄中向前或者後退多少步,類似window.history.go(n)
。
// 在瀏覽器記錄中前進一步,等同於 history.forward()
router.go(1)
// 後退一步記錄,等同於 history.back()
router.go(-1)
// 前進 3 步記錄
router.go(3)
// 如果 history 記錄不夠用,那就默默地失敗唄
router.go(-100)
router.go(100)
3-7-3-4. 命名路由
有時候,通過一個名稱來標識一個路由顯得更方便一些,特別是在鏈接一個路由,或者是執行一些跳轉的時候。你可以在創建 Router 實例的時候,在 routes 配置中給某個路由設置名稱。
代碼示例:
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}]
})
要鏈接到一個命名路由,可以給 router-link 的 to 屬性傳一個對象:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
這跟代碼調用 router.push() 是一回事:
router.push({ name: 'user', params: { userId: 123 }})
3-7-3-5. 命名視圖
有時候想同時 (同級) 展示多個視圖,而不是嵌套展示,例如創建一個佈局,有 sidebar (側導航) 和 main(主內容) 兩個視圖,這個時候命名視圖就派上用場了。你可以在界面中擁有多個單獨命名的視圖,而不是隻有一個單獨的出口。如果 router-view 沒有設置名字,那麼默認爲 default 。
代碼示例:
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
一個視圖使用一個組件渲染,因此對於同個路由,多個視圖就需要多個組件。確保正確使用 components 配置 (帶上 s ):
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
3-7-3-6. 重定向和別名
重定向也是通過 routes 配置來完成,下面例子是從 /a 重定向到 /b :
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
“重定向”的意思是,當用戶訪問 /a
時, URL 將會被替換成 /b
,然後匹配路由爲 /b
,那麼“別名”又是什麼呢?
/a
的別名是 /b
,意味着,當用戶訪問 /b
時, URL 會保持爲 /b
,但是路由匹配則爲 /a
,就像用戶訪問 /a
一樣。
上面對應的路由配置爲:
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})