1.配置路由
新建router文件夹
文件夹内新建routes.ts, index.ts
//routes.ts
import { RouteRecordRaw } from 'vue-router'
export const routes: Array<RouteRecordRaw> = [
{
path: '/',
redirect: '/home',
component: () => import('@/layout/index.vue'),
children: [
{
path: 'home',
component: () => import('@/views/home.vue'),
meta: {
title: '首页',
keepAlive: true
}
},
{
path: 'mine',
component: () => import('@/views/mine.vue'),
meta: {
title: '我的',
keepAlive: true
}
}
]
},
{
path: '/login',
component: () => import('@/views/login.vue'),
meta: {
title: '登录',
keepAlive: true
}
}
]
export default routes
先随便建几个页面一会用
//懒加载形式
compoennt: () => import('xx')
layout文件夹内是导航部分,说句题外话,实际上移动端页面包含底部导航也没有几个。
mata 是路由元信息, 里面可以随便放
这里的title到时候显示在nav-bar上, keepAlive用来配置当前页面是否缓存
//index.ts
import { createRouter, createWebHashHistory } from 'vue-router'
import routes from './routes'
import { useUserStore } from '@/store/modules/user'
//进度条
import NProgress from 'nprogress'
NProgress.configure({ showSpinner: false })
const router = createRouter({
history: createWebHashHistory(),
routes
})
//路由白名单
const whiteList = ['/login']
router.beforeEach(async (to, from, next) => {
NProgress.start()
const userStore = useUserStore()
console.log('userStore.token', userStore.token, to.path);
if (userStore.token) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
next()
NProgress.done()
}
} else {
if (whiteList.includes(to.path)) {
// 白名单
next()
NProgress.done()
} else {
next('/login')
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
export default router
这里添加了路由守卫,因为是移动端,暂时没有加动态路由,后续也许不需要
路由守卫原理也很简单,是就是判断是否符合条件(token)然后跳转到相关页面,注意不要死循环就行
1.2 layout配置
// layout index.vue
<template>
<van-nav-bar :title="$route.meta.title" />
<div class="main-page">
<RouterView v-slot="{ Component }" v-if="$route.meta.keepAlive">
<keep-alive>
<component :is="Component" :key="$route.path" />
</keep-alive>
</RouterView>
<RouterView v-if="!$route.meta.keepAlive" :key="$route.path" />
</div>
<van-tabbar route>
<van-tabbar-item replace to="/home" icon="home-o">首页</van-tabbar-item>
<van-tabbar-item replace to="/mine" icon="friends-o">我的</van-tabbar-item>
</van-tabbar>
</template>
<style scoped lang="scss">
.main-page {
box-sizing: border-box;
height: calc(100vh - 92px);
overflow-y: scroll;
overflow-x: hidden;
padding-left: 30px;
padding-right: 30px;
}
</style>
van-tabbar 直接使用的路由模式
2 配置pinia
pinia是干啥的应该都清楚...
src 下新建store文件夹
//store index.ts
import { createPinia } from 'pinia';
//持久化存储
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
const store = createPinia();
store.use(piniaPluginPersistedstate);
export default store;
模块化配置的话,store文件夹下新增modules文件夹
//user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => {
return {
user_token: ''
}
},
getters: {
token: (state) => state.user_token
},
actions: {
setToken(token: string) {
// 登录接口
return new Promise((resolve, reject) => {
this.user_token = token
resolve(true)
})
}
},
persist: {
key: 'user_token',
// 默认为local
storage: localStorage,
paths: ['user_token']
}
})
这里采用的是模拟从后台获取token,所以搞了一个promise
重点说一下persist
这个是持久化配置,key就是存储的key,storage可以选择sessionStorage或者localStorage
//源码
persist?: boolean | PersistedStateOptions | PersistedStateOptions[];
persist这里可以发挥一个boolean值,也可以返回一个对象,或者一个对象数组
//源码
interface PersistedStateOptions {
/**
* Storage key to use.
* @default $store.id
*/
key?: string;
/**
* Where to store persisted state.
* @default localStorage
*/
storage?: StorageLike;
/**
* Dot-notation paths to partially save state. Saves everything if undefined.
* @default undefined
*/
paths?: Array<string>;
/**
* Customer serializer to serialize/deserialize state.
*/
serializer?: Serializer;
/**
* Hook called before state is hydrated from storage.
* @default null
*/
beforeRestore?: (context: PiniaPluginContext) => void;
/**
* Hook called after state is hydrated from storage.
* @default undefined
*/
afterRestore?: (context: PiniaPluginContext) => void;
/**
* Logs errors in console when enabled.
* @default false
*/
debug?: boolean;
}
在这里actions里有一个setToken方法,按照正常逻辑,应该在登录页面调用
import { useUserStore } from '@/store/modules/user'
import { useRouter } from 'vue-router'
const userStore = useUserStore()
const router = useRouter()
const handleLogin = async () => {
// 实际上这里应该是username与password
let data = await userStore.setToken('token')
if (data) {
router.push('/home')
}
}
具体pinia怎么使用,直接看官方文档,解释的比较清晰,不用看其他人的一堆示例
插一句,css预处理使用的scss