一、vue-router v4.x
1、安装
yarn add vue-router@next
@next代表最新的版本
2、路由配置
在src目录下,新建router/index.ts,具体配置如下
import {RouteRecordRaw,createRouter,createWebHashHistory} from 'vue-router'
const routes:Array<RouteRecordRaw> = [
{
path: '/login',
component: () => import('../views/Login.vue')
},
{
path: '/register',
component: () => import('../views/Register.vue')
},
{
path: '/',
component: () => import('../views/Home.vue')
}
]
const router=createRouter({
routes,
history:createWebHashHistory()
})
export default router
必须在main.ts引入后挂载
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
const app=createApp(App)
app.use(router)
app.mount('#app')
3、路由跳转
路由跳转有两种方式
-
router-link,超链接的方式来跳转
-
通过useRouter这个hook来进行跳转
<template>
<div>
<h1>登录</h1>
<a href="#" @click="goRegister">没有账号,请注册</a>
</div>
</template>
<script lang='ts' setup>
import { reactive,ref} from 'vue'
import {useRouter} from 'vue-router'
const router=useRouter()
const goRegister=(e:MouseEvent)=>{
e.preventDefault()
router.push({
path:'/register'
})
}
</script>
4、路由传参
4.1、params参数
-
配置
const routes:Array<RouteRecordRaw>=[
{
path:'/newsDetail/:id',
component:()=>import('../views/NewsDetail.vue')
}
]
-
传参
<template>
<div>
<h3>新闻列表</h3>
<router-link to="/newsDetail/12">乌四地全票通过入俄!梅德韦杰夫:欢迎回家</router-link><br>
<router-link to="/newsDetail/13">美国副总统哈里斯遭遇车祸</router-link>
</div>
</template>
-
接收参数
<script lang='ts' setup>
import { reactive,ref,onMounted} from 'vue'
import {useRoute} from 'vue-router'
const route=useRoute()
onMounted(()=>{
console.log(route.params.id);
})
</script>
4.2、query参数
-
配置
const routes:Array<RouteRecordRaw>=[
{
path:'/newsDetail',
component:()=>import('../views/NewsDetail.vue')
}
]
-
传参
方式一:使用
<router-link>
标签形式进行跳转并且使用?
的方式进行传递参数
<router-link to="/newsDetail?id=23">首页</router-link>
方式二:使用router.push
方式进行跳转并且使用query
属性方式进行传参
<template>
<div>
<h3>新闻列表</h3>
<a href="#" @click="skip($event,12)">乌四地全票通过入俄!梅德韦杰夫:欢迎回家</a><br>
<a href="#" @click="skip($event,13)">美国副总统哈里斯遭遇车祸</a>
</div>
</template>
<script lang='ts' setup>
import { reactive,ref} from 'vue'
import {useRouter} from 'vue-router'
const router=useRouter()
const skip=(e:MouseEvent,id:number)=>{
e.preventDefault()
router.push({
path:`/newsDetail`,
query:{id}
})
}
</script>
-
接收参数
<script lang='ts' setup>
import { reactive,ref,onMounted} from 'vue'
import {useRoute} from 'vue-router'
const route=useRoute()
onMounted(()=>{
console.log(route.query.id);
})
</script>
二、vuex v4.x
官网地址:开始 | Vuex
1、安装
yarn add vuex@next
2、配置
-
在src/store/index.ts创建store实例
import {createStore} from 'vuex'
const store=createStore({
state(){
return{
count:0
}
}
})
export default store
-
在main.js中挂载store
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
const app=createApp(App)
app.use(store)
app.mount('#app')
3、State
<template>
<h1>计数器:{{store.state.count}}</h1>
</template>
<script>
import {useStore} from 'vuex'
export default {
setup(){
const store=useStore()
return {store}
}
}
</script>
4、Mutation
Counter.vue组件
<template>
<h1>计数器:{{store.state.count}}</h1>
<button @click="increment">+</button>
</template>
<script>
import {useStore} from 'vuex'
export default {
setup(){
const store=useStore()
const increment=()=>{
store.commit('increment') //store.commit("方法名字")
}
return {store,increment}
}
}
</script>
store/index.js
import {createStore} from 'vuex'
interface State{
count:number
}
const store=createStore({
state(){
return{
count:0
}
},
mutations:{
increment(state:State){
state.count++
}
}
})
export default store
5、actions
触发action异步任务时携带参数
import {createStore} from 'vuex'
const store=createStore({
state(){
return{
count:1
}
},
mutations:{
increment(state:State,n:number){
state.count+=n
}
},
actions:{
incrementAsync(context:ActionContext<State,any>,n:number){
setTimeout(() => {
context.commit('increment',n)
}, 2000);
}
}
})
export default store
组件中使用store.dispatch()派发异步任务
import {useStore} from 'vuex'
export default {
setup(){
const store=useStore()
const increment=()=>{
store.dispatch('incrementAsync',3)
}
return {store,increment}
}
}
</script>
6、vuex模块化
6.1、创建modules目录
可以根据项目中数据的分类,来将仓库拆分成多个模块。通常我们会在src/store
目录中,创建一个modules
目录,用来存放所有的模块文件。
6.2、配置模块
每一个仓库模块中,都需要暴露一个对象出去,同时,需要设置一个属性
import {ActionContext} from 'vuex'
interface State{
count:number
}
export default{
namespaced:true,
state(){
return{
count:1
}
},
mutations:{
increment(state:State,n:number){
state.count+=n
}
},
actions:{
incrementAsync(context:ActionContext<State,any>,n:number){
setTimeout(() => {
context.commit('increment',n)
}, 2000);
}
}
}
6.3、引入模块
模块配置完成之后,需要在主仓库src/store/index.js
文件中引入模块
import {createStore} from 'vuex'
import counter from './modules/counter'
const store=createStore({
state(){
},
mutations:{
},
actions:{
},
modules:{
counter
}
})
export default store
6.4、组件操作模块
<template>
<h1>计数器:{{store.state.counter.count}}</h1> <!--store.state.模块名.变量名-->
<button @click="increment">+</button>
</template>
<script>
import {useStore} from 'vuex'
export default {
setup(){
const store=useStore()
const increment=()=>{
//store.dispatch("模块名/actions对应方法",参数)
store.dispatch('counter/incrementAsync',3)
}
return {store,increment}
}
}
</script>
6.5、辅助函数方式
<template>
<div>
<h1>计数器</h1>
<div>{{count}}</div>
<button @click="increment(2)">+</button>
</div>
</template>
<script lang='ts'>
import {createNamespacedHelpers} from 'vuex'
const {mapState,mapActions}=createNamespacedHelpers('couter')
import {computed} from 'vue'
export default{
computed:{
...mapState(['count'])
},
methods:{
...mapActions({increment:'incrementAsync'})
}
}
</script>
<style lang='scss' scoped>
</style>
三、pinia
1、概念
官网地址:Pinia | The intuitive store for Vue.js
Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。实际上,pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名pinia,而没有取名Vuex,所以大家可以直接将pinia比作为Vue3的Vuex
2、为什么要使用pinia
-
pinia中只有state、getter、action,抛弃了Vuex中的Mutation,Vuex中mutation一直都不太受小伙伴们的待见,pinia直接抛弃它了,这无疑减少了我们工作量。
-
pinia中action支持同步和异步,Vuex不支持
-
良好的Typescript支持,毕竟我们Vue3都推荐使用TS来编写,这个时候使用pinia就非常合适了
-
pinia分模块不需要modules
-
体积非常小,只有1KB左右。
3、安装和配置
在终端执行如下命令进行安装
yarn add pinia
在src/main.ts中引入
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
const pinia=createPinia()
const app=createApp(App)
app.use(pinia)
app.mount('#app')
4、快速入门
-
在src/store/counter.ts定义store
import {defineStore} from 'pinia'
const useCounterStore =defineStore('counter',{
state:()=>{
return{
count:0
}
},
getters:{
doubleCount:state=>state.count*2
},
actions:{
increment(){
this.count++
}
}
})
export default useCounterStore
-
在组件中使用操作store
<template>
<div>
<h2>{{count}}</h2>
<button @click="increment">+</button>
</div>
</template>
<script lang='ts'>
import useCounterStore from './store/counter'
import {storeToRefs} from 'pinia'
export default{
setup(){
const store=useCounterStore()
const {count}=storeToRefs(store)
const {increment}=store
return{
count,
increment
}
}
}
</script>
5、使用
import {defineStore} from 'pinia'
interface IState{
name:string,
age:number,
job:string
}
const useUsersStore=defineStore('users',{
state:():IState=>{
return{
name:'张三丰',
age: 120,
job: '掌门'
}
},
getters:{
getName:(state):string=>state.name,
getAge:(state):number=>state.age,
getJob:(state):string=>state.job,
getUserInfo:(state):string=>`姓名:${state.name}\t年龄:${state.age}\t职业:{state.job}`
},
actions:{
modifyUserInfo(name:string,age:number,job:string){
this.name=name
this.age=age
this.job=job
}
}
})
export default useUsersStore
组件中使用store
<template>
<div>
<h1>用户信息</h1>
<div>姓名:{{name}}</div>
<div>年龄:{{age}}</div>
<div>职业:{{job}}</div>
<button @click="modifyUserInfo">修改用户信息</button>
<button @click="resetUserInfo">重置用户信息</button>
<button @click="patchUserInfo">批量修改</button>
</div>
</template>
<script lang='ts'>
import useUsersStore from './store/users'
import {storeToRefs} from 'pinia'
export default{
setup(){
const store=useUsersStore()
const {name,age,job}=storeToRefs(store)
const modifyUserInfo=():void=>{
store.modifyUserInfo('杨逍',20,'明教左使')
}
const resetUserInfo=():void=>{
store.$reset()
}
const patchUserInfo=():void=>{
store.$patch({
name:'周芷若',
age:21
})
}
return {
name,age,job,
modifyUserInfo,
resetUserInfo,
patchUserInfo
}
}
}
</script>
<style lang='scss' scoped>
</style>
6、持久化
-
下载安装
yarn add pinia-plugin-persist
-
修改之前的目录结构
在src/store/index.ts
import {createPinia} from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
const store=createPinia()
store.use(piniaPluginPersist)
export default store
修改main.ts文件
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
const app=createApp(App)
app.use(store)
app.mount('#app')
-
在相应的模块中开启持久化
import {defineStore} from 'pinia'
const useUsersStore=defineStore('users',{
state:():=>{
},
getters:{
},
actions:{
},
persist:{
enabled:true
}
})
export default useUsersStore
默认情况下,pinia持久化的数据存储在sessionStorage中,如果要存储到localStorage中,设置如下
-
设置到localstorage中
import {defineStore} from 'pinia'
const useUsersStore=defineStore('users',{
state:():=>{
},
getters:{
},
actions:{
},
persist:{
enabled:true,
strategies:[
{
key:'my_user',
storage:localStorage
}
]
}
})
export default useUsersStore
默认所有的state都会进行缓存,你能够通过paths指定要持久化的字段,其余的则不持久化
import {defineStore} from 'pinia'
const useUsersStore=defineStore('users',{
state:():=>{
},
getters:{
},
actions:{
},
persist:{
enabled:true,
strategies:[
{
key:'my_user',
storage:localStorage,
paths:['name','job']
}
]
}
})
export default useUsersStore