vue2基礎(chǔ)第一天
1.vue指令
實(shí)質(zhì)上就是特殊的 html 標(biāo)簽屬性, 特點(diǎn): v- 開(kāi)頭
插值表達(dá)式
在dom標(biāo)簽中, 直接插入內(nèi)容,又叫聲明式渲染/文本插值
語(yǔ)法: {{ 表達(dá)式 }}
dom中插值表達(dá)式賦值, vue的變量必須在data里聲明
2.vue指令-v-bind
動(dòng)態(tài)給標(biāo)簽屬性設(shè)置vue變量的值
語(yǔ)法:v-bind:屬性名="vue變量"
簡(jiǎn)寫(xiě)::屬性名="vue變量"
<!-- vue指令-v-bind屬性動(dòng)態(tài)賦值 -->
<a v-bind:href="url">我是a標(biāo)簽</a>
<img :src="imgSrc">
3.vue指令-v-on
給標(biāo)簽綁定事件
- 語(yǔ)法
- v-on:事件名="要執(zhí)行的==少量代碼=="
- v-on:事件名="methods中的函數(shù)"
- v-on:事件名="methods中的函數(shù)(實(shí)參)"
- 簡(jiǎn)寫(xiě): @事件名="methods中的函數(shù)"
v-on事件對(duì)象
語(yǔ)法:
- 無(wú)傳參, 通過(guò)形參直接接收
- 傳參, 通過(guò)$event指代事件對(duì)象傳給事件處理函數(shù)
<template>
<div>
<a @click="one" >阻止百度</a>
<hr>
<a @click="two(10, $event)" >阻止去百度</a>
</div>
</template>
<script>
export default {
methods: {
one(e){
e.preventDefault()
},
two(num, e){
e.preventDefault()
}
}
}
</script>
v-on修飾符
語(yǔ)法:
- @事件名.修飾符="methods里函數(shù)"
- .stop - 阻止事件冒泡
- .prevent - 阻止默認(rèn)行為
- .once - 程序運(yùn)行期間, 只觸發(fā)一次事件處理函數(shù)
<template>
<div @click="fatherFn">
<!-- vue對(duì)事件進(jìn)行了修飾符設(shè)置, 在事件后面.修飾符名即可使用更多的功能 -->
<button @click.stop="btn">.stop阻止事件冒泡</button>
<a @click.prevent="btn">.prevent阻止默認(rèn)行為</a>
<button @click.once="btn">.once程序運(yùn)行期間, 只觸發(fā)一次事件處理函數(shù)</button>
</div>
</template>
<script>
export default {
methods: {
fatherFn(){
console.log("father被觸發(fā)");
},
btn(){
console.log(1);
}
}
}
</script>
v-on按鍵修飾符
給鍵盤事件, 添加修飾符
語(yǔ)法:
- @keyup.enter - 監(jiān)測(cè)回車按鍵
- @keyup.esc - 監(jiān)測(cè)返回按鍵
<template>
<div>
<input type="text" @keydown.enter="enterFn">
<hr>
<input type="text" @keydown.esc="escFn">
</div>
</template>
<script>
export default {
methods: {
enterFn(){
console.log("enter回車按鍵了");
},
escFn(){
console.log("esc按鍵了");
}
}
}
</script>
4.vue指令 v-model
把表單標(biāo)簽value屬性和vue數(shù)據(jù)變量, 雙向綁定到一起
語(yǔ)法: v-model="vue數(shù)據(jù)變量"
雙向數(shù)據(jù)綁定
- 數(shù)據(jù)變化 -> 視圖自動(dòng)同步
- 視圖變化 -> 數(shù)據(jù)自動(dòng)同步
綁定在普通表單標(biāo)簽上:
<input type="text" v-model="username" />
綁定在下拉菜單select上:
<select v-model="from">
<option value="北京市">北京</option>
<option value="南京市">南京</option>
<option value="天津市">天津</option>
</select>
綁定在單選框上:
<input type="radio" value="男" name="sex" v-model="gender">男
<input type="radio" value="女" name="sex" v-model="gender">女
綁定在文本域上:
<textarea v-model="intro"></textarea>
綁定在復(fù)選框上:
特別注意: v-model, 在input[checkbox]的多選框狀態(tài)
變量為非數(shù)組, 則綁定的是checked的屬性(true/false) - 常用于: 單個(gè)綁定使用
變量為數(shù)組, 則綁定的是他們的value屬性里的值 - 常用于: 收集勾選了哪些值
<input type="checkbox" v-model="hobby" value="抽煙">抽煙
<input type="checkbox" v-model="hobby" value="喝酒">喝酒
<input type="checkbox" v-model="hobby" value="寫(xiě)代碼">寫(xiě)代碼
v-model修飾符
v-model.修飾符="vue數(shù)據(jù)變量"
- .number 以parseFloat轉(zhuǎn)成數(shù)字類型
- .trim 去除首尾空白字符
- .lazy 在change時(shí)觸發(fā)而非inupt時(shí)
<template>
<div>
<div>
<span>年齡:</span>
<input type="text" v-model.number="age">
</div>
<div>
<span>人生格言:</span>
<input type="text" v-model.trim="motto">
</div>
<div>
<span>自我介紹:</span>
<textarea v-model.lazy="intro"></textarea>
</div>
</div>
</template>
<script>
export default {
data() {
return {
age: "",
motto: "",
intro: ""
}
}
}
</script>
5.vue指令 v-text和v-html
更新DOM對(duì)象的innerText/innerHTML
- 語(yǔ)法:
- v-text="vue數(shù)據(jù)變量"
- v-html="vue數(shù)據(jù)變量"
- 注意: 會(huì)覆蓋插值表達(dá)式
<template>
<div>
<p v-text="str"></p>
<p v-html="str"></p>
</div>
</template>
<script>
export default {
data() {
return {
str: "<span>我是一個(gè)span標(biāo)簽</span>"
}
}
}
</script>
6.vue指令 v-show和v-if
控制標(biāo)簽的隱藏或出現(xiàn)
- 語(yǔ)法:
- v-show="vue變量"
- v-if="vue變量"
- 原理
- v-show 用的display:none隱藏 (頻繁切換使用)
- v-if 直接從DOM樹(shù)上移除
- 高級(jí)
- v-else使用
<template>
<div>
<h1 v-show="isOk">v-show的盒子</h1>
<h1 v-if="isOk">v-if的盒子</h1>
<div>
<p v-if="age > 18">我成年了</p>
<p v-else>還得多吃飯</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isOk: true,
age: 15
}
}
}
</script>
7.vue指令-v-for
循環(huán)生成結(jié)構(gòu)命令
口訣: 讓誰(shuí)循環(huán)生成, v-for就寫(xiě)誰(shuí)身上
-
語(yǔ)法
- v-for="(值, 索引) in 目標(biāo)結(jié)構(gòu)"
- v-for="值 in 目標(biāo)結(jié)構(gòu)"
-
目標(biāo)結(jié)構(gòu):
- 可以遍歷數(shù)組 / 對(duì)象 / 數(shù)字 / 字符串 (可遍歷結(jié)構(gòu))
-
注意:
v-for的臨時(shí)變量名不能用到v-for范圍外
避免v-for和v-if在一起使用: Vue 處理指令時(shí),v-for 比 v-if 具有更高的優(yōu)先級(jí), 雖然用起來(lái)也沒(méi)報(bào)錯(cuò)好使, 但是性能不高, 如果你有5個(gè)元素被v-for循環(huán), v-if也會(huì)分別執(zhí)行5次.
vue2基礎(chǔ)第二天
1.v-for更新
數(shù)組改變, v-for會(huì)監(jiān)測(cè)到并更新頁(yè)面
數(shù)組不改變, v-for不會(huì)更新頁(yè)面
vue2通過(guò)數(shù)組下標(biāo)修改數(shù)組的值的方式 雖然修改了數(shù)組 不會(huì)觸發(fā)v-for 不會(huì)同步修改視圖
vue2 解決方案:this.$set 更新數(shù)據(jù)的時(shí)候,還會(huì)更新視圖
語(yǔ)法: this.$set(要設(shè)置的原數(shù)據(jù), 數(shù)組下標(biāo), 新的值)
vue3沒(méi)有這個(gè)bug
push()pop()shift()unshift()splice()sort()reverse()
這些方法不會(huì)觸發(fā)v-for更新
slice()filter()concat()
2.動(dòng)態(tài)class
語(yǔ)法:
- :class="{類名: 布爾值}"
3.動(dòng)態(tài)style
此種方式生成的是標(biāo)簽的行內(nèi)樣式
語(yǔ)法
- :style="{css屬性: 值}"
4.計(jì)算屬性computed
基本概念
一個(gè)數(shù)據(jù), 依賴另外一些數(shù)據(jù)計(jì)算而來(lái)的結(jié)果
注意:1.計(jì)算屬性和data屬性都是變量-不能重名
2.計(jì)算屬性會(huì)根據(jù)依賴項(xiàng)的變化而自動(dòng)重新計(jì)算
3.計(jì)算屬性定義的時(shí)候是一個(gè)函數(shù),使用到的其實(shí)是個(gè)變量
4.計(jì)算屬性變量的值就是return返回的數(shù)據(jù)
簡(jiǎn)便寫(xiě)法:
computed: {
"計(jì)算屬性名" () {
return "值"
}
}
計(jì)算屬性的緩存
計(jì)算屬性相比函數(shù),具有緩存優(yōu)勢(shì),計(jì)算屬性對(duì)應(yīng)函數(shù)執(zhí)行后, 會(huì)把return值緩存起來(lái)
依賴項(xiàng)不變, 多次調(diào)用都是從緩存取值,依賴項(xiàng)值變化, 函數(shù)會(huì)"自動(dòng)"重新執(zhí)行并緩存新的值
比普通方法性能更高
計(jì)算屬性-完整寫(xiě)法
計(jì)算屬性也是變量,如果要給計(jì)算屬性賦值 , 需要使用完整寫(xiě)法
computed: {
"屬性名": {
set(值){
},
get() {
return "值"
}
}
}
5.偵聽(tīng)器-watch
簡(jiǎn)單偵聽(tīng)
可以偵聽(tīng)data/computed屬性值改變
簡(jiǎn)便寫(xiě)法: 只能偵聽(tīng)到簡(jiǎn)單數(shù)據(jù)類型的變化
watch: {
"被偵聽(tīng)的屬性名" (newVal, oldVal){
// newVal: 當(dāng)前最新值
// oldVal: 上一刻值
// 變量名對(duì)應(yīng)值改變這里自動(dòng)觸發(fā)
}
}
深度偵聽(tīng)
偵聽(tīng)復(fù)雜類型, 和立即執(zhí)行偵聽(tīng)
watch: {
"要偵聽(tīng)的屬性名": {
// 變量名對(duì)應(yīng)值改變這里自動(dòng)觸發(fā)
immediate: true, // 立即偵聽(tīng)(網(wǎng)頁(yè)打開(kāi)handler執(zhí)行一次)
deep: true, // 深度偵聽(tīng)復(fù)雜類型內(nèi)變化 對(duì)象里面層的值改變
handler (newVal, oldVal) {
}
}
}
vue2基礎(chǔ)第三天
1.組件
組件是可復(fù)用的 Vue 實(shí)例,封裝的思想,把頁(yè)面上 可重用的部分 封裝為 組件,從而方便項(xiàng)目的 開(kāi)發(fā) 和 維護(hù)
組件內(nèi)template只能有一個(gè)根標(biāo)簽
組件內(nèi)data必須是一個(gè)函數(shù), 獨(dú)立作用域
2.組件全局注冊(cè)
全局入口在main.js, 在new Vue之上注冊(cè)
//引入組件
import Pannel from './components/Pannel'
//全局注冊(cè)組件
Vue.component("PannelG", Pannel)
//使用組件
<PannelG></PannelG>
<PannelG/>
<pannel-g></pannel-g>
3.組件局部注冊(cè)
import 組件對(duì)象 from 'vue文件路徑'
export default {
components: {
"組件名": 組件對(duì)象
}
}
4.父子組件通訊
父組件向子組件傳值
<Product title="好貴的北京烤鴨" price="290" :intro="str"></Product>
export default {
data(){
return {
str: "好貴啊, 快來(lái)啊, 好吃"
}
},
}
子組件接收數(shù)據(jù)
export default {
props: ['title', 'price', 'intro']
}
單向數(shù)據(jù)流
在vue中需要遵循單向數(shù)據(jù)流原則
單向數(shù)據(jù)流:從父到子的單向數(shù)據(jù)流動(dòng)
1. 父組件的數(shù)據(jù)發(fā)生了改變,子組件會(huì)自動(dòng)跟著變
2. 子組件不能直接修改父組件傳遞過(guò)來(lái)的props props是只讀的
==父組件傳給子組件的是一個(gè)對(duì)象,子組件修改對(duì)象的屬性,是不會(huì)報(bào)錯(cuò)的,對(duì)象是引用類型, 互相更新==
子通過(guò)自定義事件通知父修改數(shù)據(jù)
子: this.$emit("自定義事件名", 傳值) - 通知父執(zhí)行父methods里函數(shù)代碼
父:@自定義事件名="父methods函數(shù)"
vue2基礎(chǔ)第四天
1.生命周期鉤子函數(shù)
Vue 框架內(nèi)置函數(shù),隨著組件的生命周期階段,自動(dòng)執(zhí)行
4大階段8個(gè)方法
初始化 beforeCreate created
掛載 beforeMount mounted
更新 beforeUpdate updated
銷毀 beforeDestroy destroyed
初始化階段
beforeCreate--此時(shí)拿不到data函數(shù)和methods中的數(shù)據(jù)
created--data和methods已初始化,此時(shí)可以拿到data函數(shù)和methods中的數(shù)據(jù),應(yīng)用場(chǎng)景:網(wǎng)絡(luò)請(qǐng)求,注冊(cè)全局事件
掛載階段
beforeMount--此時(shí)拿不到真實(shí)dom元素
mounted--可以拿到真實(shí)dom元素
更新階段
data函數(shù)里有數(shù)據(jù)改變才執(zhí)行的鉤子函數(shù),data數(shù)據(jù)改變重復(fù)執(zhí)行beforeUpdate和updated鉤子函數(shù)
beforeUpdate--data里數(shù)據(jù)更新之前, DOM更新之前執(zhí)行
updated--data數(shù)據(jù)更新之后,且虛擬dom重新渲染并打補(bǔ)丁到真實(shí)dom之后執(zhí)行的鉤子函數(shù)
銷毀階段
當(dāng)$destroy()被調(diào)用 – 比如組件DOM被移除(例v-if)執(zhí)行銷毀鉤子函數(shù)
beforeDestroy--dom元素或組件銷毀前執(zhí)行 場(chǎng)景: 移除全局事件, 移除當(dāng)前組件, 計(jì)時(shí)器, 定時(shí)器, eventBus移除事件$off方法
destroyed--dom元素或組件銷毀后執(zhí)行
2.$refs-獲取DOM和vue實(shí)例
獲取dom元素
獲取dom元素時(shí),webapi獲取方式和this.$refs獲取方式獲取到同一個(gè)對(duì)象
<h1 id="h" ref="myH">我是一個(gè)孤獨(dú)可憐又能吃的h1</h1>
export default {
mounted() {
console.log(document.getElementById("h")); // h1
console.log(this.$refs.myH); // h1
},
};
獲取組件對(duì)象
目標(biāo)是組件時(shí),webapi獲取方式獲取到dom元素,this.$refs獲取到vue實(shí)例
this.$refs可以拿到組件 甚至可以修改組件內(nèi)部的數(shù)據(jù),但是一般不會(huì)這么做 這樣做會(huì)造成后期維護(hù)困難 一般只會(huì)拿到組件調(diào)用組件的方法
3.$nextTick使用
Vue更新DOM異步的,點(diǎn)擊count++, 馬上通過(guò)"原生DOM"拿標(biāo)簽內(nèi)容, 無(wú)法拿到新值
解決: this.$nextTick()
過(guò)程: DOM更新完會(huì)挨個(gè)觸發(fā)$nextTick里的函數(shù)體
this.$nextTick(() => {
console.log(this.$refs.myP.innerHTML);
})
擴(kuò)展: await取代回調(diào)函數(shù) $nextTick()原地返回Promise對(duì)象
this.$nextTick(() => { await this.$nextTick()
this.$refs.myInp.focus() ===> this.$refs.myInp.focus()
})
4.組件name屬性使用
可以用組件的name屬性值, 來(lái)注冊(cè)組件名字
我們封裝的組件-可以自己定義name屬性組件名-讓使用者有個(gè)統(tǒng)一的前綴風(fēng)格
components/Com.vue
<template>
<div>
<p>我是一個(gè)Com組件</p>
</div>
</template>
<script>
export default {
name: "ComNameHaHa" // 可以定義組件自己的名字
}
</script>
App.vue - 注冊(cè)和使用
<template>
<div>
<ComNameHaHa></ComNameHaHa>
</div>
</template>
<script>
import Com from './components/Com'
export default {
components: {
[Com.name]: Com
// "ComNameHaHa": Com
}
}
</script>
拓展: [這里還可以放表達(dá)式]
const obj={
}
等價(jià)于====>obj={ ab:1}
vue2基礎(chǔ)第五天
1.動(dòng)態(tài)組件component
vue內(nèi)置component組件, 配合is屬性, 設(shè)置要顯示的組件名字
掛載點(diǎn): <component :is="變量"></component>
組件切換會(huì)導(dǎo)致組件被頻繁銷毀和重新創(chuàng)建, 性能不高
2.組件緩存keep-alive
使用Vue內(nèi)置的keep-alive組件, 可以讓包裹的組件保存在內(nèi)存中不被銷毀
<div style="border: 1px solid red;">
<!-- Vue內(nèi)置keep-alive組件, 把包起來(lái)的組件緩存起來(lái) -->
<keep-alive>
<component :is="comName"></component>
</keep-alive>
</div>
總結(jié):keep-alive可以提高組件的性能, 內(nèi)部包裹的標(biāo)簽不會(huì)被銷毀和重新創(chuàng)建, 觸發(fā)激活和非激活的生命周期方法
補(bǔ)充生命周期鉤子方法:
activated - 激活時(shí)觸發(fā)
deactivated - 失去激活狀態(tài)觸發(fā)
3.組件插槽slot
組件內(nèi)用<slot></slot>占位
使用組件時(shí)<Son></Son>夾著的地方, 傳入標(biāo)簽替換slot
Son.vue
<template>
<div class="box">
<!-- 坑位 -->
<slot>
<section>子組件默認(rèn)內(nèi)容</section>
</slot>
</div>
</template>
<script>
export default {};
</script>
App.vue
<template>
<div>
<Son>
<h3>你好兒子</h3>
<a href="#">鏈接</a>
</Son>
</div>
</template>
<script>
import Son from './components/Son.vue'
export default {
components: { Son },
}
</script>
<style></style>
插槽默認(rèn)內(nèi)容---<slot>夾著內(nèi)容默認(rèn)顯示內(nèi)容, 如果不給插槽slot傳東西, 則使用<slot>夾著的內(nèi)容在原地顯示
4.具名插槽
當(dāng)一個(gè)組件內(nèi)有2處以上需要外部傳入標(biāo)簽的地方
slot的name屬性起插槽名, 使用組件時(shí), template配合v-slot:插槽名傳入具體標(biāo)簽
Son.vue
<template>
<div class="box">
<slot name="title">
<h2>我是子組件標(biāo)題</h2>
</slot>
<!-- 坑位 -->
<slot name="content">
<section>子組件默認(rèn)內(nèi)容</section>
</slot>
</div>
</template>
<script>
export default {};
</script>
<style scoped>
.box {
border: 1px solid #000;
margin: 20px;
}
</style>
App.vue
<template>
<div>
<Son>
<template v-slot:title>
<h3>你好兒子</h3>
</template>
<template v-slot:content>
<a href="#">鏈接</a>
</template>
</Son>
</div>
</template>
<script>
import Son from './components/Son.vue'
export default {
components: { Son },
}
</script>
v-slot:可以簡(jiǎn)化成#使用
v-bind可以省略成: v-on:可以省略成@ v-slot:可以簡(jiǎn)化成#
5.作用域插槽
子組件里值, 在給插槽賦值時(shí)在父組件環(huán)境下使用
1.子組件, 在slot上綁定自定義屬性和子組件內(nèi)的值
2.使用組件,用template配合v-slot="自定義變量名"
3.自定義變量會(huì)收集slot身上屬性和值形成對(duì)象
Pannle.vue
<template>
<div class="box">
<!-- 作用域插槽可以看做:子傳父 -->
<slot :row="defaultObj"></slot>
</div>
</template>
<script>
export default {
data() {
return {
defaultObj: {
defaultOne: '無(wú)名氏',
defaultTwo: '小傳同學(xué)',
},
}
},
}
</script>
<style scoped>
.box {
border: 1px solid #000;
margin: 20px;
padding: 20px;
}
</style>
App.vue
<template>
<div>
<!--
作用域插槽的使用
1、子組件,<slot :屬性名="值"></slot> 傳值
2、父組件,通過(guò) v-slot="變量名" 接收
PS:作用域插槽相當(dāng)于是插槽的子傳父。
-->
<Pannle>
<!-- 父組件接收:v-slot="變量名" -->
<template v-slot="scope">
<h2>{{ scope }}</h2>
<h3>{{ scope.row.defaultTwo }}</h3>
</template>
</Pannle>
</div>
</template>
<script>
import Pannle from './components/Pannle.vue'
export default {
components: {
Pannle,
},
}
</script>
6.自定義指令
你需要對(duì)普通 DOM 元素進(jìn)行底層操作,這時(shí)候就會(huì)用到自定義指令
自定義指令作用:可以獲取標(biāo)簽,擴(kuò)展功能
自定義指令全局注冊(cè)
在main.js用 Vue.directive()方法來(lái)進(jìn)行注冊(cè), 然后項(xiàng)目中所有.vue文件里都可以直接用自定義指令
Vue.directive('color', {
// 掛載時(shí)觸發(fā) 只觸發(fā)一次 相當(dāng)于mounted鉤子函數(shù)
inserted(el) {
console.log(el);
}
});
自定義指令局部注冊(cè)
只能在當(dāng)前組件.vue文件中使用的自定義指令
使用指令:v-指令名稱
<template>
<div id="app">
<!-- 自定義指令 -->
<input type="text" autofocus v-abc />
<h2 v-color="'red'">我是大標(biāo)題</h2>
</div>
</template>
<script>
export default {
data() {
return {};
},
methods: {},
// 自定義指令局部注冊(cè)
directives: {
abc: {
// 掛載到頁(yè)面后觸發(fā), 相當(dāng)于mounted鉤子函數(shù)
// el表示使用指令時(shí)的標(biāo)簽
inserted(el) {
console.log(el);
},
},
},
};
</script>
自定義指令-傳值
定義自定義指令時(shí)定義接收參數(shù)
binding為使用自定義指令時(shí)傳進(jìn)來(lái)的對(duì)象
// 全局注冊(cè)自定義指令-傳值
Vue.directive('color', {
// 掛載時(shí)觸發(fā) 只觸發(fā)一次 相當(dāng)于mounted鉤子函數(shù)
inserted(el, binding) {
el.style.color = binding.value;
},
// 每次更新后觸發(fā) 相當(dāng)于updated鉤子函數(shù)
update(el, binding) {
el.style.color = binding.value;
}
});
使用自定義指令時(shí)傳遞參數(shù)
<template>
<div>
<!-- 使用指令時(shí)傳值:v-指令名稱="變量" -->
<!-- 使用指令時(shí)傳值:v-指令名稱="'字符串'" -->
<h2 v-color="'red'">我是二標(biāo)題-什么顏色呢?</h2>
<h3 v-color="myColor">我是三標(biāo)題-什么顏色呢?</h3>
<button @click="myColor = 'green'">改顏色變量</button>
</div>
</template>
<script>
export default {
data() {
return {
myColor: "pink",
};
},
};
</script>
vue2基礎(chǔ)第六天
1.路由
前端中定義
路徑和組件的映射關(guān)系或接口和服務(wù)的映射關(guān)系
作用
實(shí)現(xiàn)單頁(yè)面應(yīng)用(SPA): 所有功能在一個(gè)html頁(yè)面上實(shí)現(xiàn)
實(shí)現(xiàn)業(yè)務(wù)場(chǎng)景切換
路由的優(yōu)點(diǎn)
整體不刷新頁(yè)面,用戶體驗(yàn)更好
數(shù)據(jù)傳遞容易, 開(kāi)發(fā)效率高
路由的缺點(diǎn)
開(kāi)發(fā)成本高(需要學(xué)習(xí)專門知識(shí))
首次加載會(huì)比較慢一點(diǎn),不利于seo
2.vue-router
定義:vue官方提供的路由系統(tǒng)功能模塊包
作用:在Vue項(xiàng)目中集成路由
vue-router提供2個(gè)內(nèi)置全局組件 router-link router-view
注意:vue-router@4不兼容vue2
vue2項(xiàng)目中要下載vue-router@3
3.vue-router使用步驟
在main.js中配置
1.安裝
yarn add vue-router@3
2.導(dǎo)入路由
import VueRouter from 'vue-router'
3.使用路由插件
// 在vue中,使用使用vue的插件,都需要調(diào)用Vue.use()
Vue.use(VueRouter)
4.1導(dǎo)入組件
import Find from '@/views/Find.vue';
import My from '@/views/My.vue';
import Part from '@/views/Part.vue';
import NotFound from '@/views/NotFound.vue';
4.2創(chuàng)建路由規(guī)則數(shù)組
const routes = [
{
// 默認(rèn)頁(yè)面重定向?yàn)镕ind頁(yè)
path: '/',
redirect: '/find'
},
{
path: "/find",
component: Find,
// 嵌套路由:二級(jí)路由
children: [
// main.js中二級(jí)路由路徑書(shū)寫(xiě)無(wú)需 / 開(kāi)頭
// path為空表示默認(rèn)打開(kāi)的頁(yè)面
{
path: '',
// 重定向
redirect: 'recommend'
},
{
path: 'recommend',
component: Recommend
},
{
path: 'ranking',
component: Ranking
},
{
path: 'songlist',
component: SongList
}
]
},
{
path: "/my",
name: 'mypage',
component: My
},
{
path: "/part/:id",
component: Part
},
// 404頁(yè)面
{
path: '*',
component: NotFound
}
];
5.創(chuàng)建路由對(duì)象 - 傳入規(guī)則
const router = new VueRouter({
routes,
//默認(rèn)hash模式
//history模式url地址欄上沒(méi)有#號(hào)
mode: 'history' //設(shè)置history模式,路由上線需要服務(wù)器端支持, 否則找的是文件夾
})
6.關(guān)聯(lián)到vue實(shí)例
new Vue({
router
})
7.使用路由
使用路由頁(yè)面components換成router-view
使用router-view掛載點(diǎn)顯示切換的路由
<router-view></router-view>
4.聲明式導(dǎo)航
基本使用
用全局組件router-link來(lái)替代a標(biāo)簽
router-link配合to, 實(shí)現(xiàn)點(diǎn)擊切換路由
router-link實(shí)質(zhì)上最終會(huì)渲染成a鏈接 to屬性等價(jià)于提供 href屬性
router-link提供了聲明式導(dǎo)航高亮的功能(router-link-exact-active router-link-active)
router-link自帶的2個(gè)類名
router-link-exact-active (精確匹配) url中hash值路徑, 與href屬性值完全相同, 設(shè)置此類名
router-link-active (模糊匹配) url中hash值, 包含href屬性值這個(gè)路徑, 設(shè)置此類名
<template>
<div id="app">
<ul>
<!-- 聲明式導(dǎo)航 -->
<!-- 聲明式導(dǎo)航也可以傳對(duì)象 此時(shí)to前要綁定: -->
<!-- <li><router-link to="/find">發(fā)現(xiàn)頁(yè)</router-link></li> -->
<li><router-link :to="{ path: '/find' }">發(fā)現(xiàn)頁(yè)</router-link></li>
<li><router-link to="/my?id=123">我的主頁(yè)</router-link></li>
<li><router-link to="/part/456">我的分頁(yè)</router-link></li>
</ul>
<!-- 路由掛載點(diǎn) -->
<router-view></router-view>
</div>
</template>
<script>
export default {};
</script>
<style scoped lang=less>
.router-link-exact-active {
color: aqua;
}
</style>
聲明式導(dǎo)航傳參
方案1: 傳值---to="/path?參數(shù)名=值"
接收---`$route.query`
方案2: 傳值---to="/path/值"(需要在路由規(guī)則數(shù)組中配置 /path/:參數(shù)名)
接收---`$route.params`
兩種方案二選一即可,選擇哪種看團(tuán)隊(duì)習(xí)慣
拓展: 聲明式導(dǎo)航也可以傳對(duì)象 此時(shí)to前面要綁定:
<router-link :to="{ path: '/find'}">發(fā)現(xiàn)頁(yè)</router-link>
等價(jià)于
<router-link to="/find">發(fā)現(xiàn)頁(yè)</router-link>
5.vue路由 - 重定向
定義:匹配path后, 強(qiáng)制切換到目標(biāo)path上
網(wǎng)頁(yè)打開(kāi)url默認(rèn)hash值是/路徑
redirect是設(shè)置要重定向到哪個(gè)路由路徑
強(qiáng)制重定向后, 還會(huì)重新來(lái)數(shù)組里匹配一次規(guī)則
//網(wǎng)頁(yè)默認(rèn)打開(kāi), 匹配路由"/", 強(qiáng)制切換到"/find"上
const routes = [
{
path: "/", // 默認(rèn)hash值路徑
redirect: "/find" // 重定向到/find
// 瀏覽器url中#后的路徑被改變成/find-重新匹配數(shù)組規(guī)則
}
]
6.404頁(yè)面
如果路由hash值, 沒(méi)有和數(shù)組里規(guī)則匹配,默認(rèn)給一個(gè)404頁(yè)面
放在路由規(guī)則數(shù)組最后, path匹配*(任意路徑) – 前面不匹配就命中最后這個(gè), 顯示對(duì)應(yīng)組件頁(yè)面
7.編程式導(dǎo)航
用JS代碼來(lái)進(jìn)行跳轉(zhuǎn),大多數(shù)情況使用聲明式導(dǎo)航,當(dāng)需要在導(dǎo)航前判斷是就要使用編程式導(dǎo)航
基礎(chǔ)使用
<template>
<div id="app">
<!-- 編程式導(dǎo)航 -->
<button @click="btnFn">編程式導(dǎo)航</button>
<!-- 路由掛載點(diǎn) -->
<router-view></router-view>
</div>
</template>
<script>
export default {
methods: {
btnFn() {
// 方式1 使用 name
// 方式1需要在路由數(shù)組里, 給路由起名字
this.$router.push("Find");
// 方式2 使用 path
this.$router.push("/find");
},
},
};
</script>
跳轉(zhuǎn)傳參
方式1: query方式傳參 搭配path 接收參數(shù)用 $route.query
方式2: params方式傳參 搭配name 接收參數(shù)用 $route.params
注意: vue2固有的bug 編程式導(dǎo)航跳轉(zhuǎn)相同的頁(yè)面 會(huì)報(bào)錯(cuò)
<template>
<div id="app">
<!-- 編程式導(dǎo)航 -->
<button @click="btnFn">編程式導(dǎo)航</button>
<!-- 路由掛載點(diǎn) -->
<router-view></router-view>
</div>
</template>
<script>
export default {
methods: {
btnFn() {
// 進(jìn)階使用:傳對(duì)象的形式,適用于參數(shù)較多的情況
// name 和path選其中一個(gè)就好
//傳參 params搭配name傳參
//格外注意: 使用path會(huì)自動(dòng)忽略params
this.$router.push({
/*name: "part",
params: {
id: 123,
aaa: "rose",
bbb: "flower",
}, */
path: "/my",
query: {
id: 1234444,
aaa: "aaa",
bbb: "15dsaaf",
},
});
},
},
};
</script>
<style scoped lang=less>
.router-link-exact-active {
color: aqua;
}
</style>
8.路由嵌套
規(guī)則
main.js繼續(xù)配置2級(jí)路由
一級(jí)路由path從/開(kāi)始定義
二級(jí)路由往后path直接寫(xiě)名字, 無(wú)需/開(kāi)頭
嵌套路由在上級(jí)路由的children數(shù)組里編寫(xiě)路由信息對(duì)象
main.js展示
// 導(dǎo)入二級(jí)路由
import Recommend from '@/views/second/Recommend';
import SongList from '@/views/second/SongList';
import Ranking from '@/views/second/Ranking';
const routes = [
{
// 默認(rèn)頁(yè)面重定向?yàn)镕ind頁(yè)
path: '/',
redirect: '/find'
},
{
path: "/find",
component: Find,
// 嵌套路由:二級(jí)路由
children: [
// main.js中二級(jí)路由路徑書(shū)寫(xiě)無(wú)需 / 開(kāi)頭
// path為空表示默認(rèn)打開(kāi)的頁(yè)面
{
path: '',
// 重定向
redirect: 'recommend'
},
{
path: 'recommend',
component: Recommend
},
{
path: 'ranking',
component: Ranking
},
{
path: 'songlist',
component: SongList
}
]
},
// 404頁(yè)面
{
path: '*',
component: NotFound
}
];
二級(jí)路由展示
跳轉(zhuǎn)時(shí), 要去的路由路徑從一級(jí)開(kāi)始寫(xiě),需要/開(kāi)頭
<template>
<div>
find頁(yè)面
<!-- 二級(jí)路由掛載點(diǎn) -->
<ul>
<!-- 注意點(diǎn):頁(yè)面中 to 屬性的每一級(jí)路徑都需要寫(xiě)/開(kāi)頭 如:/一級(jí)/二級(jí) / -->
<li>
<router-link to="/find/recommend">發(fā)現(xiàn)音樂(lè)頁(yè)/ 推薦頁(yè)面</router-link>
</li>
<li>
<router-link to="/find/ranking">發(fā)現(xiàn)音樂(lè)頁(yè) / 排行榜頁(yè)面</router-link>
</li>
<li>
<router-link to="/find/songlist">發(fā)現(xiàn)音樂(lè)頁(yè) / 歌單頁(yè)面</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</template>
<script>
export default {};
</script>
<style scoped>
/* 精確匹配類名 */
.router-link-exact-active {
color: red;
}
</style>
9.全局前置守衛(wèi)
路由跳轉(zhuǎn)之前, 先執(zhí)行一次前置守衛(wèi)函數(shù), 判斷是否可以正常跳轉(zhuǎn)
在main.js中得到路由對(duì)象router之后書(shū)寫(xiě)代碼
// 語(yǔ)法: router.beforeEach((to, from, next)=>{//路由跳轉(zhuǎn)"之前"先執(zhí)行這里, 決定是否跳轉(zhuǎn)})
// 參數(shù)1: 要跳轉(zhuǎn)到的路由 (路由對(duì)象信息) 目標(biāo)
// 參數(shù)2: 從哪里跳轉(zhuǎn)的路由 (路由對(duì)象信息) 來(lái)源
// 參數(shù)3: 函數(shù)體 - next()才會(huì)讓路由正常的跳轉(zhuǎn)切換, next(false)在原地停留, next("強(qiáng)制修改到另一個(gè)路由路徑上")
// 注意: 如果不調(diào)用next, 頁(yè)面留在原地
// 例子: 判斷用戶是否登錄, 是否決定去"我的音樂(lè)"/my
const isLogin = false; // 登錄狀態(tài)(未登錄)
router.beforeEach((to, from, next) => {
if (to.path === "/my" && isLogin === false) {
alert("請(qǐng)登錄")
next(false) // 阻止路由跳轉(zhuǎn)
} else {
next() // 正常放行
}
})