本章學(xué)習(xí)目標(biāo):
- 了解Vue框架架構(gòu)思想
- 掌握Vue核心指令
- 掌握計(jì)算屬性與監(jiān)視
- 掌握組件化開發(fā)模式
一、Vue框架概述
- 官方文檔:https://cn.vuejs.org/guide/introduction.html.
- 文檔可選擇使用optionsAPI(選項(xiàng)式API)閱讀,或者CompositionApi(組合式API)閱讀。選項(xiàng)式API更適合平滑從vue2過(guò)渡,以下示例均以Compositions API方式編寫。
- 如何使用compositions API? : 在.vue文件的script標(biāo)簽上,添加setup屬性則被識(shí)別為使用compositionsAPI。不添加則默認(rèn)為optionsAPI方式
<script setup>
// 組合式API寫法
</script>
<script>
// 選項(xiàng)式寫法
export default {
components:{},
data(){ return {}},
methods:{},
}
</script>
1、VUE的優(yōu)勢(shì):
- 漸進(jìn)式框架,沒(méi)有強(qiáng)主張。
- 只是個(gè)輕量視圖,只做了自己該做的事。
- 漸進(jìn)式:數(shù)據(jù)綁定——》路由控制——》組件開發(fā)——》數(shù)據(jù)共享
2、Vue是什么?
- Vue.js (讀音 /vju:/,類似于view) 是一套構(gòu)建用戶界面的漸進(jìn)式框架。
- 與其他重量級(jí)框架不同的是,Vue 采用自底向上增量開發(fā)的設(shè)計(jì)
- 輕量級(jí)MVVM框架
- 通過(guò)簡(jiǎn)單的API,提供高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng)
3、VUE的引入步驟(三種方式)
- 直接下載vue.js的庫(kù)文件,使用script標(biāo)記引入到頁(yè)面中。
- 使用cdn進(jìn)行引入,網(wǎng)絡(luò)上的vue。
- 使用npm進(jìn)行安裝。
4、創(chuàng)建一個(gè)vue應(yīng)用
- 本節(jié)以vue官方腳架方式來(lái)進(jìn)行demo演示。
- vue3推薦使用create-vue來(lái)創(chuàng)建基于 Vite 的新項(xiàng)目。
- 腳手架地址:https://github.com/vuejs/create-vue
# 1、安裝項(xiàng)目模板
npm create vue@latest
# 2、demo用,對(duì)話內(nèi)容都選No
# 3、進(jìn)入創(chuàng)建好的文件
cd vue-project
# 4、安裝依賴
npm install
# 5、啟動(dòng)項(xiàng)目
npm run dev
-
腳手架安裝自定義選項(xiàng)
-
創(chuàng)建后生成項(xiàng)目目錄結(jié)構(gòu)如下:
-
成功啟動(dòng)后,以瀏覽器中訪問(wèn):http://127.0.0.1:5173/
打開項(xiàng)目后
- 打開App .vue(入口模板文件)
- 打開components目錄,里面的所有.vue文件即為組件
- .vue文件即為vue模板組件,主要分為三大塊script(交互腳本), template(HTML),style(樣式)
- 清除內(nèi)容,只留下script,template,style標(biāo)簽,看頁(yè)面如何變化
<template>
<h1>hello world!</h1>
</template>
<script setup>
console.log("hello world!")
</script>
<style scoped>
h1{
color:red;
}
</style>
1.1 聲明響應(yīng)式的數(shù)據(jù)
- 在vue3中,新增了ref,reactive函數(shù)來(lái)定義一個(gè)響應(yīng)式數(shù)據(jù)
- ref(): 接收參數(shù)作為初始值,并將參數(shù)包裝為具有響應(yīng)性的ref對(duì)象返回,通過(guò)返回的ref對(duì)象的.value屬性來(lái)取值,在選項(xiàng)式API的setup()函數(shù)或在帶setup屬性的script標(biāo)簽中定義使用
- reactive() : 直接定義一個(gè)具有響應(yīng)性的對(duì)象(ref是將數(shù)據(jù)包裝為特殊ref對(duì)象)
- reactive:只能用于定義對(duì)象類型 (對(duì)象、數(shù)組和如 Map、Set 這樣的集合類型)。不支持原始類型
- 不能替換整個(gè)被定義的對(duì)象,這樣會(huì)導(dǎo)致響應(yīng)性連接丟失
- reactive定義的響應(yīng)式對(duì)象,不能使用解構(gòu)取值,也會(huì)導(dǎo)致響應(yīng)性連接丟失
<template>
<div>
<p>定義的ref值:{{ refVal }}</p>
<p>定義的reactive值:{{ obj.count }}</p>
</div>
</template>
<script setup>
import {ref,reactive} from 'vue'
let refVal = ref("hello")
// 在template模板中會(huì)用ref對(duì)象的值時(shí)不需要.value,但在script中需要
console.log(refVal.value)
let obj = reactive({
count:1
})
</script>
<style scoped>
</style>
二、Vue內(nèi)置指令
以下demo以vue3的composition API為例使用
2.1、條件渲染指令v-if/v-show
-
v-if
: 條件渲染,顯示與隱藏(布爾值)- v-if: 基于表達(dá)式值的真假性,來(lái)?xiàng)l件性地渲染元素或者模板片段
- v-if-else:與v-if搭配使用,實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
- v-else:與v-if搭配使用,實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
- 注意:當(dāng) v-if 元素被觸發(fā),元素及其所包含的指令/組件都會(huì)銷毀和重構(gòu)。如果初始條件是假,那么其內(nèi)部的內(nèi)容根本都不會(huì)被渲染。
-
v-show
:條件渲染- 原理:v-show 通過(guò)設(shè)置內(nèi)聯(lián)樣式的 display CSS 屬性來(lái)工作,當(dāng)元素可見時(shí)將使用初始 display 值。
v-if與v-show的區(qū)別?
v-if通過(guò)值的真假來(lái)控制元素是否被渲染來(lái)實(shí)現(xiàn)顯隱,而v-show通過(guò)css的display屬性來(lái)控制實(shí)現(xiàn)顯示與隱藏。v-if元素每一次觸發(fā)都會(huì)引起重構(gòu)。
<template>
<div>
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>
</div>
</template>
<script setup>
// 聲明一個(gè)變量
let type ='B'
</script>
<style scoped>
</style>
2.2 v-for: 列表渲染
- 基于原始數(shù)據(jù)多次渲染元素或模板塊
- 支持遍歷的原始數(shù)據(jù)可以是:Array | Object | number | string | Iterable
<template>
<div>
<!-- 遍歷數(shù)組 -->
<div>
<span v-for="(item,index) in arr" :key="index">{{item}},</span>
</div>
<!-- 遍歷對(duì)象 -->
<div>
<span v-for="(value,key) in obj" :key="key">{{key}}-{{value}},</span>
</div>
</div>
</template>
<script setup>
let arr = ['apple','banana','peach','cherry']
let obj={
"name":"張三",
"age":"18",
"sex":"男"
}
</script>
<style scoped>
</style>
2.3、v-text/v-html 模板指令
- v-text: 更新元素的文本內(nèi)容(類似DOM API中的innerText)
- v-html:更新元素的 innerHTML。(類似innerHTML)
<template>
<div>
<div v-text="textStr"></div>
<div v-html="htmlStr"></div>
</div>
</template>
<script setup>
let textStr = "這是一段文本,html內(nèi)容不會(huì)被解析為html.如<h1>h1標(biāo)簽</h1>"
let htmlStr = "<h1>這是html內(nèi)容,可以被解析</h1>"
</script>
<style scoped>
</style>
2.4 v-on:事件監(jiān)聽器
- 給元素綁定事件監(jiān)聽器,簡(jiǎn)寫為"@"
- 參數(shù):event對(duì)象
- 修飾符:
-
.stop
- 阻止冒泡,調(diào)用 event.stopPropagation()。 -
.prevent
- 阻止默認(rèn)行為,調(diào)用 event.preventDefault()。 -
.capture
- 在捕獲模式添加事件監(jiān)聽器。 -
.self
- 只有事件從元素本身發(fā)出才觸發(fā)處理函數(shù)。 -
.{keyAlias}
- 只在某些按鍵下觸發(fā)處理函數(shù)。 -
.once
- 最多觸發(fā)一次處理函數(shù)。 -
.left
- 只在鼠標(biāo)左鍵事件觸發(fā)處理函數(shù)。 -
.right
- 只在鼠標(biāo)右鍵事件觸發(fā)處理函數(shù)。 -
.middle
- 只在鼠標(biāo)中鍵事件觸發(fā)處理函數(shù)。 -
.passive
- 通過(guò) { passive: true } 附加一個(gè) DOM 事件。
-
<template>
<div>
<button v-on:click="onclick1">普通點(diǎn)擊</button>
<div v-on:click="testPropogation">
防止冒泡點(diǎn)擊,使用@別名綁定
<button @click.stop="onclick2">防冒泡點(diǎn)擊</button>
</div>
<div @click.capture="captureHandler">
captureHandler:捕獲觸發(fā)click,點(diǎn)button,先觸發(fā)captureHandler,再必testCapture
<button @click="testCapture">testCapture</button>
</div>
<a href="https://www.baidu.com" @click.prevent="preventHandler">點(diǎn)擊不跳轉(zhuǎn)</a>
<button @click.once="onceHandler">只響應(yīng)一次,再點(diǎn)沒(méi)用</button>
<div>
按下enter觸發(fā)
<input @keyup.enter="onEnter" />
</div>
</div>
</template>
<script setup>
function onclick1(){
alert("普通點(diǎn)擊")
}
// 冒泡測(cè)試
function onclick2(){
alert("防冒泡點(diǎn)擊")
}
function testPropogation(){
alert("點(diǎn)擊div或冒泡觸發(fā)")
}
// 捕獲測(cè)試
function captureHandler(){
alert("點(diǎn)了外層div")
}
function testCapture(){
alert("捕獲觸發(fā),或者直接點(diǎn)擊按鈕觸發(fā)")
}
// prevent測(cè)試
function preventHandler(){
alert("preventHandler")
}
// .once測(cè)試
function onceHandler(){
alert("once事件觸發(fā),再點(diǎn)沒(méi)用")
}
// .{keyAlias}測(cè)試
function onEnter(){
alert("按下enter鍵")
}
</script>
<style scoped>
</style>
2.6 動(dòng)態(tài)綁定v-bind
- 用于綁定 class 或 style
- 用于綁定組件prop
- 簡(jiǎn)寫
:
<template>
<div>
<!-- 綁定DOM屬性 -->
<img style="width:100px" v-bind:src="imgSrc"/>
<!-- 綁定style -->
<img :style="{width:'200px',height:'100px',marginLeft:'20px'}" v-bind:src="imgSrc"/>
<!-- 綁定class -->
<div :class="classArr" >綁定class數(shù)組</div>
</div>
</template>
<script setup>
let imgSrc = "http://imgsrc.baidu.com/baike/pic/item/ac345982b2b7d0a25cd01174cbef76094b369a39.jpg"
// 綁定class
let classArr = ['w100','bg-blue']
</script>
<style >
.w100{
width: 100px;
height: 100px;
}
.bg-blue{
background: blue;
}
</style>
2.7 v-model表單元素值綁定
- 在表單輸入元素或組件上創(chuàng)建雙向綁定
- 支持標(biāo)簽:input,select,textarea或者vue components
- 修飾符:
- .lazy - 監(jiān)聽 change 事件而不是 input
- .number - 將輸入的合法字符串轉(zhuǎn)為數(shù)字
- .trim - 移除輸入內(nèi)容兩端空格
<template>
<div>
輸入--------》
<input type="text" v-model="inputVal">
雙向綁定顯示--------》
<div>
inputVal: {{inputVal}}
</div>
</div>
</template>
<script setup>
// 使用 ref() 函數(shù)來(lái)聲明響應(yīng)式狀態(tài)
import {ref,reactive} from "vue"
let inputVal=ref("aaa")
// ref對(duì)象通過(guò).value來(lái)獲取其值
console.log(inputVal.value)
</script>
<style>
</style>
三、計(jì)算屬性與監(jiān)視
3.1 計(jì)算屬性computed
- 對(duì)于復(fù)雜的變量值(需要進(jìn)一步通過(guò)邏輯處理返回的值)推薦通過(guò)計(jì)算屬性來(lái)定義
- 返回值:一個(gè)計(jì)算屬性 ref,但計(jì)算屬性 ref 也會(huì)在模板中自動(dòng)解包,因此在模板表達(dá)式中引用時(shí)無(wú)需添加 .value
- 計(jì)算屬性會(huì)自動(dòng)追蹤響應(yīng)式依賴
- computed函數(shù)參數(shù):默認(rèn)為一個(gè)getter函數(shù),函數(shù)返回值即為想要的計(jì)算結(jié)果。傳入包括get,set函數(shù)的對(duì)象可設(shè)置讀寫操作
<template>
<div>計(jì)算屬性1(默認(rèn)只可讀):{{ authorMsg }}</div>
<div>計(jì)算屬性2:{{fullName}}</div>
</template>
<script setup>
// ref() 函數(shù)來(lái)聲明響應(yīng)式狀態(tài)
// computed() 函數(shù)來(lái)聲明計(jì)算屬性
import { ref,computed } from "vue";
let author = {
name:"張三",
fruits:["apple","banana","peach","cherry"]
}
// 示例1:默認(rèn)傳入一個(gè)getter函數(shù)
let authorMsg = computed(()=>{
let authorName = author.name
let fruitsStr = author.fruits.map(item=>item+',')
return `${authorName}喜歡吃的水果有:${fruitsStr}`
})
const firstName = ref('張')
const lastName = ref('三')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// 注意:我們這里使用的是解構(gòu)賦值語(yǔ)法
let [first, last] = newValue.split("")
firstName.value=first
lastName.value =last
}
})
setTimeout(() => {
fullName.value="王五"
}, 2000);
</script>
<style>
</style>
3.2 watch偵聽器
- 概述:偵聽器,在偵聽的某個(gè)響應(yīng)式狀態(tài)發(fā)生變化時(shí),觸發(fā)其回調(diào)函數(shù)
- 應(yīng)用場(chǎng)景:根據(jù)異步操作的結(jié)果去修改另一處的狀態(tài)
- 語(yǔ)法:watch(數(shù)據(jù)源, 回調(diào)函數(shù))
- 數(shù)據(jù)源: ref (包括計(jì)算屬性)、一個(gè)響應(yīng)式對(duì)象(reactive)、一個(gè) getter 函數(shù)、或多個(gè)數(shù)據(jù)源組成的數(shù)組
- 深層偵聽屬性:deep: true
- 立即回調(diào)屬性:immediate: true
- 回調(diào)觸發(fā)時(shí)間: 默認(rèn)情況下,回調(diào)會(huì)在vue組件更新之前調(diào)用,因此若在回調(diào)中訪問(wèn)DOM會(huì)是更新前的狀態(tài),所以盡量避免在watch回調(diào)中訪問(wèn)dom。如果想在回調(diào)中訪問(wèn)Vue更新之后 的DOM,需要添加屬性 {flush: ‘post’}
- 屬性語(yǔ)法
watch(source, callback, {
deep: true, // 深層偵聽
immediate: true, // 立即執(zhí)行一次回調(diào)
flush: 'post', // 訪問(wèn)Vue更新之后的DOM
})
- 示例
<template>
<div>
<div @click="randomChange('x')">觸發(fā)x變化</div>
<div @click="randomChange('y')">觸發(fā)y變化</div>
<div @click="() => (obj.count = 10)">reactive值變化</div>
</div>
</template>
<script setup>
import { ref, watch, reactive } from "vue";
const x = ref(0);
const y = ref(0);
// 觸發(fā)變化函數(shù)
function randomChange(name) {
let randomNum = Math.random() * 10;
if (name == "x") {
x.value = randomNum;
}
if (name == "y") {
y.value = randomNum;
}
}
// 1、監(jiān)聽單個(gè) ref
watch(x, (newX) => {
console.log(`例1:監(jiān)聽單個(gè)ref,x is ${newX}`);
});
// 2、監(jiān)聽getter 函數(shù),x,y的變化都會(huì)觸發(fā)
watch(
() => x.value + y.value,
(sum) => {
console.log(`例2:getter函數(shù)監(jiān)聽變化,sum of x + y is: ${sum}`);
}
);
// 3、多個(gè)來(lái)源組成的數(shù)組
watch([x, () => y.value], ([newX, newY]) => {
console.log(`例3:多來(lái)源數(shù)組監(jiān)聽,x is ${newX} and y is ${newY}`);
});
// 4、監(jiān)聽響應(yīng)式對(duì)象
const obj = reactive({ count: 0 });
// 錯(cuò)誤寫法,因?yàn)?watch() 得到的參數(shù)是一個(gè) number
// watch(obj.count, (count) => {
// console.log(`count is: ${count}`)
// })
// 正確寫法
watch(
() => obj.count,
(count) => {
console.log(`例4、監(jiān)聽reactive響應(yīng)式對(duì)象,count is: ${count}`);
}
);
</script>
<style>
</style>
- 其他參數(shù)
watch(source, (newValue, oldValue) => {
// 注意:`newValue` 此處和 `oldValue` 是相等的
// *除非* state.someObject 被整個(gè)替換了
// deep: 深度監(jiān)聽
// immediate:立即執(zhí)行,且當(dāng) `source` 改變時(shí)再次執(zhí)行
}, { immediate: true ,deep:true})
3.3 watch、watchEffect、computed區(qū)別
watchEffect使用場(chǎng)景:有多個(gè)依賴項(xiàng)需要偵聽,或需要偵聽一個(gè)嵌套數(shù)據(jù)結(jié)構(gòu)中的幾個(gè)屬性時(shí),watchEffect() 比深度偵聽器更有效
- 區(qū)別:
watch
只追蹤明確偵聽的數(shù)據(jù)源。它不會(huì)追蹤任何在回調(diào)中訪問(wèn)到的東西.,且僅在數(shù)據(jù)源確實(shí)改變時(shí)才會(huì)觸發(fā)回調(diào)。watch 會(huì)避免在發(fā)生副作用時(shí)追蹤依賴watchEffect
,會(huì)在副作用發(fā)生期間追蹤依賴。它會(huì)在同步執(zhí)行過(guò)程中,自動(dòng)追蹤所有能訪問(wèn)到的響應(yīng)式屬性。computed
,必須有return返回,使用方法與data中的數(shù)據(jù)一樣,如果函數(shù)所依賴的屬性沒(méi)有變化,從緩存中讀取
四、高級(jí)特性
4.1 組件
組件:組件常常被組織成層層嵌套的樹狀結(jié)構(gòu)。在vue中
.vue
文件就是組件(單文件組件SFC)
4.1.1 創(chuàng)建組件
1、參考vue-project項(xiàng)目生成目錄,其中components就是約定的組件存放目錄,在components中新建Child.vue組件如下
- child.vue
<template>
<div >
<h1>{{ msg }}</h1>
</div>
</template>
<script setup >
import {ref, reactive} from "vue"
let msg = ref("這是Child")
</script>
<style scoped>
</style>
2、父組件中引入。(以App.vue為例,此處以setup語(yǔ)法糖方式編寫,只需引入Child.vue就會(huì)自動(dòng)注冊(cè)該組件。若在optionsApi中需要顯示注冊(cè)components)
- App.vue
<template>
<div class="">
這是Parent
<p>------------------------分隔線------------------</p>
<Child />
</div>
</template>
<script setup lang="ts">
// 引入組件
import Child from './components/Child.vue'
import {ref, reactive} from "vue"
</script>
4.1.2 組件通信
- 組件通信主要分為:父子組件間通信,非父子組件間通信
- 父?jìng)髯樱簆rops屬性
- 子傳父:子組件自定義事件,并通過(guò)$emit觸發(fā)
1、父?jìng)髯觩rops
- Child.vue
<template>
<div >
<h1>{{ parentMsg }}</h1>
</div>
</template>
<script setup >
// 1. 引入defineProps宏
import { defineProps} from "vue"
// 2.定義props
defineProps({
parentMsg: {type: String}
})
</script>
- App.vue
<template>
<div class="">
這是Parent
<p>------------------------分隔線------------------</p>
<!-- 3.傳入props -->
<Child :parentMsg="toChild"/>
</div>
</template>
<script setup lang="ts">
import Child from './components/Child.vue'
import {ref} from "vue"
let toChild = ref("來(lái)自Parent的消息")
</script>
- 子組件向父組件傳遞參數(shù)——自定義事件,$emit調(diào)
2、子傳父
- App.vue
<template>
<div class="">
這是Parent
<p>------------------------分隔線------------------</p>
<!-- 3.綁定子組件自定義事件 -->
<Child @sayHi="hiHandler"/>
</div>
</template>
<script setup lang="ts">
import Child from './components/Child.vue'
// 4.接收子組件拋出事件的參數(shù)msg
function hiHandler(msg){
alert(msg)
}
</script>
- child.vue
<template>
<div >
<h1 @click="clickHandler">點(diǎn)擊傳給Parent</h1>
</div>
</template>
<script setup >
// 1. 引入defineEmits宏
import { defineEmits } from "vue"
// 2.定義組件會(huì)拋出的事件
const emit = defineEmits(['sayHi'])
function clickHandler(){
console.log("child 中觸發(fā)點(diǎn)擊")
// 3.觸發(fā)拋出事件
emit('sayHi','來(lái)自Child的消息')
}
</script>
3、py: provice/inject
如果是祖輩組件與孫輩組件間傳值,可使用provide、inject
- provide(key,value), 必須在組件的setup()階段同步調(diào)用
- inject(key,defaultValue) : 注入一個(gè)由祖先組件或整個(gè)應(yīng)用(通過(guò)app.provide())提供的值,defaultValue可選,當(dāng)沒(méi)匹配到key對(duì)應(yīng)的值時(shí)顯示
- 示例:組件結(jié)構(gòu)如下App>Middle>Child
- App.vue
<template>
<div class="">
這是App.vue,子組件為Middle,孫組件為Child(由middle包含)
<p>------------------------分隔線------------------</p>
<Middle />
</div>
</template>
<script setup lang="ts">
import Middle from './components/Middle.vue'
import {provide,ref} from 'vue'
let count = ref(0)
// 提供靜態(tài)值
provide("appName",'測(cè)試Demo')
// 提供響應(yīng)值
provide("count",count)
</script>
- Middle.vue
<template>
<div >
這是隔代組件,內(nèi)部引入Child組件
<Child />
</div>
</template>
<script setup >
import Child from './Child.vue'
</script>
- Child.vue
<template>
<div >
這是Child.vue內(nèi)容
<p>來(lái)自app.vue的appName: {{ appName }}</p>
<p>這是app.vue的count: {{ count }}</p>
</div>
</template>
<script setup >
import {inject} from 'vue'
let appName = inject("appName")
let count = inject("count")
</script>
4.2 生命周期
在vue3 compositionAPI中,生命周期鉤子函數(shù)都有on前綴,常用如onMounted,onUpdated,onUnmounted(),onActived()
- onMounted(): 組件掛載完成后執(zhí)行
- onUpdated(), 在組件因?yàn)轫憫?yīng)式狀態(tài)變更而更新其 DOM 樹之后調(diào)用
- onUnMounted(), 在組件實(shí)例被卸載之后調(diào)用。
- onActived(),若組件實(shí)例是 緩存樹的一部分,當(dāng)組件被插入到 DOM 中時(shí)調(diào)用。
<template>
<div >
{{ count }}
</div>
</template>
<script setup lang="ts">
import {ref, onMounted,onUpdated} from "vue"
let count = ref(0)
setTimeout(()=>{
count.value++
console.log("count改變將觸發(fā)onUpdated")
},2000)
onMounted(()=>{
console.log("onMounted")
})
onUpdated(()=>{
console.log("onUpdated")
})
</script>
六、腳手架案例
6.1 vue-router:前端路由
官網(wǎng)地址:https://router.vuejs.org/zh/, 在創(chuàng)建單頁(yè)應(yīng)用項(xiàng)目時(shí)腳手架會(huì)提醒是否安裝vue router,VueRouter作為前端路由庫(kù),控制整個(gè)Vue項(xiàng)目的頁(yè)面跳轉(zhuǎn)服務(wù)。以下示例介紹vue-router集成到vue項(xiàng)目中的使用
1、安裝vue router
npm install vue-router@4
2、定義路由
- 項(xiàng)目目錄中新建router文件夾,并新建index.js
// router/index.js
import {createRouter,createWebHashHistory} from 'vue-router'
// 1、定義路由組件(實(shí)際應(yīng)用中通過(guò)導(dǎo)入.vue文件組件)
const Home = ()=>import("@/pages/Home.vue")
const About = ()=>import("@/pages/About.vue")
// 2、定義路由
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
// 3. 創(chuàng)建路由實(shí)例并傳遞 `routes` 配置
const router = createRouter({
history:createWebHashHistory(), // 以hash模式創(chuàng)建路由
routes,
})
export default router
3、掛載路由到Vue實(shí)例中
- 打開項(xiàng)目src/main.js文件
// main.js
import './assets/main.css'
import router from '@/router'
import { createApp } from 'vue'
import App from './App.vue'
// 創(chuàng)建應(yīng)用實(shí)例
const app = createApp(App)
// 整個(gè)應(yīng)用支持路由
app.use(router)
// 掛載整個(gè)應(yīng)用
app.mount('#app')
4、頁(yè)面中通過(guò)router-view渲染
- App.vue
<template>
<div>
這是App.vu
<p>------------------------分隔線------------------</p>
<router-link to="/">Go to Home</router-link> <br>
<router-link to="/about">Go to About</router-link>
<div class="router-page" style="border:1px solid #ddd;padding:10px;">
<router-view></router-view>
</div>
</div>
</template>
<script setup >
</script>
5、路由跳轉(zhuǎn)及傳參
在vue3中使用組合式API編寫router業(yè)務(wù)時(shí),參考文檔:https://router.vuejs.org/zh/guide/advanced/composition-api.html
<script setup >
import {useRouter, useRoute } from 'vue-router'
import {onMounted} from 'vue'
const router = useRouter()
const route = useRoute()
function goAbout(){
// 路由跳轉(zhuǎn)
router.push({path:'/about',query:{name:'lala'}})
}
onMounted(()=>{
console.log(route.path)
})
console.log(router)
</script>
6.2 axios:接口請(qǐng)求
官網(wǎng)地址: https://www.npmjs.com/package/axios#axios-api
axios是一個(gè)基于Promise的http客戶端請(qǐng)求工具,可以在瀏覽器或者node.js中使用。
1、安裝
npm install axios --save
2、src目錄下創(chuàng)建api文件夾,簡(jiǎn)單封裝
- 一般對(duì)axios進(jìn)行簡(jiǎn)單封裝,使用統(tǒng)一域名,請(qǐng)求攔截,響應(yīng)攔截,設(shè)置超時(shí)時(shí)間等文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-650172.html
// src/api/http.js
import axios from 'axios'
const request = axios.create({
baseURL: 'https://www.xxx.com', // 后端服務(wù)地址
timeout: 120000, // 超時(shí)時(shí)間
})
// 請(qǐng)求攔截器,用于在發(fā)出請(qǐng)求前,做一些操作
request.interceptors.request.use(config=>{
// 假設(shè)本地有token
if(localStorage.getItem("token")){
config.headers.token = token
}
return config
})
// 響應(yīng)攔截器,用于處理后端報(bào)錯(cuò)等
request.interceptors.response.use(response=>{
if(response.status!==200){
console.log("請(qǐng)求響應(yīng)服務(wù)出錯(cuò)了,具體再看")
}
return response
})
export default request
- 封裝業(yè)務(wù)請(qǐng)求
// src/api/login.js
import request from './http'
const Api = {
getCode:'/api/v1/getCode',
login:'/api/v1/login'
}
// 假設(shè)獲取驗(yàn)證碼
export function getCode(params){
return request.get(Api.getCode, params)
}
// 登錄
export function login(params){
return request.post(Api.login, params)
}
3、組件間使用(偽代碼示例用)
- pages/login.vue文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-650172.html
<template>
<div >
這是登錄頁(yè)
</div>
</template>
<script setup >
import {getCode,login} from "@/api/login"
import {ref, onMounted} from "vue"
// 調(diào)用請(qǐng)求
let params = {
name:'zhangsan',
password:'123455'
}
login(params).then(res=>{
console.log(res)
})
</script>
到了這里,關(guān)于第四章:前端框架Vue基礎(chǔ)入門的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!