路由的理解
- 路由就是一組key-value的對應關系,
- 多個路由,需要經過路由器的管理。
路由-基本切換效果
- 導航區、展示區
- 請來路由器
- 制定路由的具體規則(什么路徑,對應著什么組件)
- 形成一個一個的路由
【兩個注意點】
- 路由組件通常存放在
pages
或views
文件夾,一般組件通常存放在components
文件夾。 - 通過點擊導航,視覺效果上“消失”了的路由組件,默認是被卸載掉的,需要的時候再去掛載。
【to的兩種寫法】
- to的字符串寫法
<router-link active-class="active" to="/home">主頁</router-link>
- to的對象寫法
<router-link active-class="active" :to="{path:'/home'}">Home</router-link>
【路由器工作模式】
history
模式
優點:URL
更加美觀,不帶有#
,更接近傳統的網站URL
。
缺點:后期項目上線,需要服務端配合處理路徑問題,否則刷新會有404
錯誤。
const router =createRouter({
history:createWebHistory(),//history模式
})
hash
模式
優點:兼容性更好,因為不需要服務器端處理路徑。
缺點:URL帶有#
不太美觀,且在SEO
優化方面相對較差。
const router =createRouter({
history:createWebHashHistory(),//hash模式
})
【命名路由】
作用:可以簡化路由跳轉及傳參。
給路由規則命名:
routes:[
{
name:'zhuye',
path:/home',
component:Home
},
{
name:'xinwen',
path:'/news',
component: News,
},
{
name :'guanyu',
path:'/about',
component:About}
]
【嵌套路由】
// 創建一個路由器,并暴露出去// 第一步:引入createRouter
import { createRouter, createWebHistory } from 'vue-router'
// 引入路由組件
import Home from '@/views/Home.vue'
import News from '@/views/News.vue'
import About from '@/views/About.vue'
import Detail from '@/views/Detail.vue'// 第二步:創建路由
const router = createRouter({history:createWebHistory(),//路由器的工作模式routes:[{name:'zhuye',path:'/home',component:Home},{name:'xinwen',path:'/news',component:News,children:[{name:'xiangqing',path:'detail',component:Detail}] },{name:'guanyu',path:'/about',component:About},]
})
// 第三步:導出
export default router
<template>
<div class="news"><!-- 導航區 -->
<ul>
<li v-for="item in newList" :key="item.id"><!-- 第一種寫法 --><!-- <RouterLink :to="`/news/detail?id=${item.id}&title=${item.title}&content=${item.content}`">{{item.title}}</RouterLink> -->
</li>
</ul>
<!-- 展示區 --><div class="news-content"><RouterView></RouterView></div>
</div>
</template>
<script setup lang="ts" name="News">
import { reactive } from 'vue';
import { RouterLink, RouterView } from 'vue-router';
const newList=reactive([{id:'1',title:'一種很便宜的藥物',content:'褪黑素'},{id:'2',title:'一種很好吃的水果',content:'芒果'},{id:'3',title:'一種很管報的主食',content:'大米'},{id:'4',title:'一種很催眠的課程',content:'數學'}
])
</script>
<style scoped>
/*新聞*/
.news{padding:0 20px;display:flex;justify-content:space-between;height:100%;
}
.news ul{margin-top:30px;/* list-style:none; */padding-left:10px;
}
.news li::marker{color: #64967E;
}
.news li>a{font-size:18px;line-height:40px;text-decoration:none;color:#64967E;text-shadow:00 1px rgb(0,84,0);
}.news-content {border: 2px solid #333;border-radius: 8px;padding: 15px;margin: 20px;background-color: #f9f9f9;box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}</style>
【路由傳參】
query參數
- 傳遞參數
<template>
<div class="news"><!-- 導航區 -->
<ul>
<li v-for="item in newList" :key="item.id"><!-- 第一種寫法 --><!-- <RouterLink :to="`/news/detail?id=${item.id}&title=${item.title}&content=${item.content}`">{{item.title}}</RouterLink> --><!-- 第二種寫法 --><RouterLink:to="{path:'/news/detail',query:{id:item.id,title:item.title,content:item.content}}">{{item.title}}</RouterLink>
</li>
</ul>
<!-- 展示區 --><div class="news-content"><RouterView></RouterView></div>
</div>
</template>
<script setup lang="ts" name="News">
import { reactive } from 'vue';
import { RouterLink, RouterView } from 'vue-router';
const newList=reactive([{id:'1',title:'一種很便宜的藥物',content:'褪黑素'},{id:'2',title:'一種很好吃的水果',content:'芒果'},{id:'3',title:'一種很管報的主食',content:'大米'},{id:'4',title:'一種很催眠的課程',content:'數學'}
])
</script>
<style scoped>
/*新聞*/
.news{padding:0 20px;display:flex;justify-content:space-between;height:100%;
}
.news ul{margin-top:30px;/* list-style:none; */padding-left:10px;
}
.news li::marker{color: #64967E;
}
.news li>a{font-size:18px;line-height:40px;text-decoration:none;color:#64967E;text-shadow:00 1px rgb(0,84,0);
}.news-content {border: 2px solid #333;border-radius: 8px;padding: 15px;margin: 20px;background-color: #f9f9f9;box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}</style>
- 接收參數
<template><ul class="news-list"><li>編號:{{query.id}}</li><li>標題:{{ query.title}}</li><li>內容:{{ query.content }}</li></ul>
</template>
<script setup lang="ts" name="About">
import { toRefs } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const {query}=toRefs(route)
</script>
params參數
- 傳遞參數
<!--跳轉并攜帶params參數(to的字符串寫法)-->
<RouterLink:to="'/news/detail/g01/新聞001/內容g01~">{{news.title}}</RouterLink>
<!--跳轉并攜帶params參數(to的對象寫法)-->
<RouterLink
:to="{
name:'xiang',//用name跳轉
params:{
id:news.id,
title:news.title,
content:news.title
}
}"
>
{{news.title))
</RouterLink>
- 接收參數:
import {useRoute}from vue-router'
const route useRoute()
//打印params參數
console.log(route.params)
備注1:傳遞
params
參數時,若使用to
的對象寫法,必須使用name
配置項,不能用path
。
備注2:傳遞params
參數時,需要提前在規側中占位。
【路由的props配置】
作用:讓路由組件更方便的收到參數(可以將路由參數作為props
傳給組件)
{
name:'xiang',
path:detail/:id/:title/:content',
component Detail,
//propsi的對象寫法,作用:把對象中的每一組key-value作為props傳給Detail組件
//props:{a:1,b:2,c:3},
//props的布爾值寫法,作用:把收到了每一組params參數,作為props傳給Detail組件
//props:true
//props的函數寫法,作用:把返回的對象中每一組key-value作為props傳給Detail組件
props(route){
return route.query
}
}
【replace屬性】
- 作用:控制路由跳轉時操作瀏覽器歷史記錄的模式。
- 瀏覽器的歷史記錄有兩種寫入方式:分別為
push
和replace
:push
是追加歷史記錄(默認值)replace
是替換當前記錄。
- 開啟
replace
模式:
<RouterLink replace.......>News</RouterLink>
【編程式導航】
路由組件的兩個重要的屬性:$route
和$router
變成了兩個hooks
<template><div class="home"><img src="http://www.atguigu.com/images/index_new/logo.png" alt=""></div>
</template>
<script setup lang="ts" name="Home">
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
onMounted(()=>{setTimeout(()=>{// 跳轉router.push('/news')},2000)
})
</script>
<template>
<div class="news"><!-- 導航區 -->
<ul>
<li v-for="item in newList" :key="item.id"><button @click="showNewsDetail(item)">查看新聞</button><!-- 第二種寫法 --><RouterLink:to="{name:'xiangqing',query:{id:item.id,title:item.title,content:item.content}}">{{item.title}}</RouterLink>
</li>
</ul>
<!-- 展示區 --><div class="news-content"><RouterView></RouterView></div>
</div>
</template>
<script setup lang="ts" name="News">
import { reactive } from 'vue';
import { RouterLink, RouterView, useRouter } from 'vue-router';
const newList=reactive([{id:'1',title:'一種很便宜的藥物',content:'褪黑素'},{id:'2',title:'一種很好吃的水果',content:'芒果'},{id:'3',title:'一種很管報的主食',content:'大米'},{id:'4',title:'一種很催眠的課程',content:'數學'}
])
const router=useRouter();interface NewsInter{id:string,title:string,content:string
}
function showNewsDetail(item:NewsInter){
router.replace({name:"xiangqing",query:{id:item.id,title:item.title,content:item.content}
})
}
</script>
// 創建一個路由器,并暴露出去// 第一步:引入createRouter
import { createRouter, createWebHistory } from 'vue-router'
// 引入路由組件
import About from '@/views/About.vue'
import Detail from '@/views/Detail.vue'
import Home from '@/views/Home.vue'
import News from '@/views/News.vue'// 第二步:創建路由
const router = createRouter({history:createWebHistory(),//路由器的工作模式routes:[{name:'zhuye',path:'/home',component:Home},{name:'xinwen',path:'/news',component:News,children:[{name:'xiangqing',path:'detail',component:Detail,// 第二種寫法:函數寫法,可以自己決定將什么作為props傳給路由組件props(route){return {id:route.query.id,title:route.query.title,content:route.query.content}}}]},{name:'guanyu',path:'/about',component:About},]
})
// 第三步:導出
export default router
pinia
【準備一個效果】
【存儲+讀取數據】
Store
是一個保存:狀態、業務邏輯的實體,每個組件都可以讀取、寫入它。- 它有三個概念:
state
、getter
、action
,相當于組件中的:data
、computed
和methods
。 - 具體編碼:
src/store/count.ts
//引入defineStore用于創建store
import {defineStore}from pinia'
//定義并暴露一個store
export const useCountStore defineStore('count',{
//動作
actions:{},
//狀態
state(){
return
sum:6
}
},
//計算
getters:{}
})
- 具體編碼:
src/store/talk.ts
//引入defineStore用于創建store
import {defineStore}from 'pinia'
//定義并暴露一個store
export const useTalkStore =defineStore('talk,{
//動作
actions:{},
//狀態
state(){
return{
talkList:[
{id:'yuysada01',content:'你今天有點怪,哪里怪?怪好看的!'},
{id:'yuysada02',content:'草莓、藍莓、蔓越莓,你想我了沒?'},
{id:"yuysada83",content:"心里給你留了一塊地,我的死心扇地"}
]
}
},
//計算
getters:{
})
<template><div class="talk"><button @click="getTalk()">獲取一句土味情話</button><ul><li v-for="talk in loveTalkStore.talkList" :key="talk.id">{{ talk.title }}</li></ul></div>
</template><script setup lang="ts" name="LoveTalk">
import axios from 'axios';
import { nanoid } from 'nanoid';
import { reactive } from 'vue';
import { useLoveTalkStore } from '@/store/loveTalk';
const loveTalkStore = useLoveTalkStore();
const talkList = reactive([{id: '1', // 建議統一使用字符串ID,與nanoid生成的ID類型保持一致title: '今天你有點怪,哪里怪?怪好看的!'},{id: '2',title: '草莓、藍莓、蔓越莓,今天想我了沒'},{id: '3',title: '心里給你留了一塊地,我的死心塌地',}
])async function getTalk() {// 請求新的土味情話const { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')const obj = { id: nanoid(), title }// 添加到列表最前面talkList.unshift(obj)
}
【修改數據(三種方式)】
- 第一種修改方式,直接修改
countStore.sum =666
- 第二種修改方式:批量修改
countStore.$patch({ sum:999, school:'atguigu' })
- 第三種修改方式:借助
action
修改(action
中可以編寫一些業務邏輯)
import {defineStore} from pinia
export const useCountStore =defineStore('count',{
actions:{
//加
increment(value number){if (this.sum < 10){//操作countStore中的sumthis.sum +value}
},
【storeToRefs】
- 借助
storeToRefs
將store
中的數據轉為ref
對象,方便在模板中使用。 - 注意:
pinia
提供的storeToRefs
只會將數據做轉換,而Vue
的toRefs
會轉換store
中數據。
<template>
<div class="count">
<h2>當前求和為:{{sum}}</h2>
</div>
</template>
<script setup lang="ts"name="Count">
import {useCountStore} from '@/store/count'
/*引入storeToRefs*/
import {storeToRefs} from pinia'
/*得到countStore*/
const countStore =useCountStore()
/*使用storeToRefs:轉換countStore,隨后解構*/
const {sum}=storeToRefs(countStore)
</script>
【getters】
- 概念:當state中的數據,需要經過處理后再使用時,可以使用getters配置。
- 追加getters配置。
//引入defineStore用于創建store
import {defineStore} from pinia'
//定義并暴露一個store
export const useCountStore =defineStore('count',{
//動作
actions:{
/**********/
},
//狀態
state(){
return
sum:1,
school:'atguigu'
}
},
//計算
getters:{bigSum:state=>state.sum*10,upperSchool(state){return state.school.toUpperCase()}}
})
【$subscribe】
通過store的$subscribe()
方法偵聽state
及其變化
talkStore.$subscribe((mutate,state)=>{
console.log('LoveTalk',mutate,state)
localStorage.setItem('talk',JSON.stringify(talkList.value))
})