vue基礎(chǔ)

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í)行beforeUpdateupdated鉤子函數(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)簽的地方

slotname屬性起插槽名, 使用組件時(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() // 正常放行
  }
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容