UNIBEST 使用
修改配置文件
找到 env>.env 文件
js
VITE_APP_TITLE = 'unibest' // title
VITE_APP_PORT = 9000 // 端口号
VITE_UNI_APPID = 'H57F2ACE4' // uni-app appid
VITE_WX_APPID = 'xxxxx' // 微信小程序appid
# h5部署网站的base,配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE=/ // 路径前缀
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run' // 数据请求地址
VITE_UPLOAD_BASEURL = 'https://ukw0y1.laf.run/upload' // 数据上传地址
# h5是否需要配置代理
VITE_APP_PROXY=false
VITE_APP_PROXY_PREFIX = '/api' // 代理前缀增加分包配置
- 找到 vite.config.ts 文件
修改里面的 subPackages 目录
js
UniPages({
exclude: ['**/components/**/**.*'],
routeBlockLang: 'json5', // 虽然设了默认值,但是vue文件还是要加上 lang="json5", 这样才能很好地格式化
// homePage 通过 vue 文件的 route-block 的type="home"来设定
// pages 目录为 src/pages,分包目录不能配置在pages目录下
subPackages: ['src/pages-sub', 'src/pages-sub2'], // 是个数组,可以配置多个,但是不能为pages里面的目录
dts: 'src/types/uni-pages.d.ts',
}),- 在 pages 目录下创建 pages-sub 和 pages-sub2 目录
里面新建文件夹然后在新建 index.vue 文件
页面里面
组件部分要是组件名同文件名.可以不用引入直接使用(自动引入)
钩子函数可以直接用
默认支持 scss 插件
路由配置
routeblock
- 每个页面的开头都要加上 route-block
js
<route lang="json5" type="page">
{
layout: 'demo',
style: {
navigationStyle: 'custom',
navigationBarTitleText:'首页',
},
needLogin: true,
others: '哈哈哈哈',
}
</route>
<template>
xxxxxxxx
</template>layout: 'demo' 是指使用哪个 layout,在 layouts 目录下
style: 是指当前页面的样式,可以配置 navigationBarTitleText,navigationStyle,backgroundColor 等
needLogin: 是否需要登录(写了这个属性路由验证那里就需要 token 验证)
others: 其他配置(随意)
路由拦截
- 第一步 先创建好pages/login/index.vue页面
vue
<script lang="ts" setup>
definePage({
style: {
navigationBarTitleText: "登录页面",
},
});
function settoken() {
uni.setStorageSync("token", { username: "张三", password: "12345" });
// 如果有 redirect 参数,跳回原页面
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1] as {
options?: Record<string, string>;
};
const redirect = currentPage.options?.redirect;
uni.reLaunch({
url: redirect ? decodeURIComponent(redirect) : "/pages/index/index",
});
}
</script>
<template>
<view class="mt-10 text-center text-green-500">
<button @click="settoken">登录</button>
</view>
</template>- 第二步 改路由拦截器(核心)
把 src/router/interceptor.ts 改成这样:
ts
/**
* 路由拦截,通常也是登录拦截
*/
import { getTabbarRedirectPath, tabbarStore } from "@/tabbar/store";
import { getLastPage, parseUrlToObj } from "@/utils/index";
import { useTokenStore } from "@/store/token";
export const FG_LOG_ENABLE = false;
// 登录页路径
const LOGIN_PAGE = "/pages/login/index";
// 不需要登录就能进的页面(白名单),至少要包含登录页本身,否则死循环
const NO_NEED_LOGIN_LIST = [LOGIN_PAGE];
export const navigateToInterceptor = {
invoke({ url, query }: { url: string; query?: Record<string, string> }) {
if (url === undefined) {
return;
}
let { path, query: _query } = parseUrlToObj(url);
const myQuery = { ..._query, ...query };
// 处理相对路径(原有逻辑)
if (!path.startsWith("/")) {
const currentPath = getLastPage()?.route || "";
const normalizedCurrentPath = currentPath.startsWith("/")
? currentPath
: `/${currentPath}`;
const baseDir = normalizedCurrentPath.substring(
0,
normalizedCurrentPath.lastIndexOf("/"),
);
path = `${baseDir}/${path}`;
}
// ===== 新增:登录校验 =====
// 目标页不在白名单,且本地没有 token,就拦到登录页
if (!NO_NEED_LOGIN_LIST.includes(path)) {
const token = uni.getStorageSync("token");
if (!token) {
uni.reLaunch({
url: `${LOGIN_PAGE}?redirect=${encodeURIComponent(url)}`,
});
return false; // 返回 false 表示阻止这次跳转
}
}
// ===== 新增结束 =====
// 原有:tabbar 角色越权兜底
const redirectPath = getTabbarRedirectPath(path);
if (redirectPath) {
uni.reLaunch({ url: redirectPath });
return false;
}
// 原有:修正 tabbar 高亮
tabbarStore.setAutoCurIdx(path);
},
};
export const routeInterceptor = {
install() {
uni.addInterceptor("navigateTo", navigateToInterceptor);
uni.addInterceptor("reLaunch", navigateToInterceptor);
uni.addInterceptor("redirectTo", navigateToInterceptor);
uni.addInterceptor("switchTab", navigateToInterceptor);
},
};- 第三步 处理首页拦不到的问题
仅仅在首页(src/pages/index/index.vue)的 onShow 里加:
ts
import { onShow } from "@dcloudio/uni-app";
onShow(() => {
const token = uni.getStorageSync("token");
if (!token) {
uni.reLaunch({ url: "/pages/login/index" });
}
});退出登录的地方:
uni.removeStorageSync('token')。除了首页其他页面需要登录验证
html
<script lang="ts" setup>
definePage({
style: {
navigationBarTitleText: "我的",
},
needLogin: true,
});
</script>Store
举例 在 store 文件夹下面
- 新增一个 count.ts
js
import { defineStore } from "pinia";
import { ref } from "vue";
export const useCountStore = defineStore(
"countnum",
() => {
const countnumInfo = ref(0);
const setCountnumInfo = (val: number) => {
countnumInfo.value = val;
};
const clearCountnumInfo = () => {
countnumInfo.value = 0;
};
return {
countnumInfo,
setCountnumInfo,
clearCountnumInfo,
};
},
{
persist: true,
}
);- 在 store 里面引入模块
js
import { createPinia } from "pinia";
import { createPersistedState } from "pinia-plugin-persistedstate"; // 数据持久化
const store = createPinia();
store.use(
createPersistedState({
storage: {
getItem: uni.getStorageSync,
setItem: uni.setStorageSync,
},
}),
);
export default store;
// 模块统一导出
export * from "./user";
export * from "./count";- 使用
js
<route lang="json5" type="page">
{
layout: 'demo',
style: {
navigationStyle: 'custom',
navigationBarTitleText: '首页',
},
needLogin: true,
others: '哈哈哈哈',
}
</route>
<template>
<view>我自己的页面</view>
<wd-icon name="add-circle" class="text-green" color="red" size="32"></wd-icon>
<view class="text-green">{{ store.countnumInfo }}</view>
<wd-button type="success" @click="createadd">点击改变</wd-button>
<wd-button type="success" @click="delall">点击删除</wd-button>
<button @click="gotourl">点击跳转</button>
</template>
<script setup lang="ts">
import { useCountStore } from '@/store'
const store = useCountStore()
onLoad((option) => {
console.log(option)
uni.hideTabBar({
animation: false,
})
})
const createadd = () => {
store.setCountnumInfo(15)
}
const delall = () => {
store.clearCountnumInfo()
}
const gotourl = () => {
uni.switchTab({
url: '/pages/index/index?id=16',
})
}
</script>
<style lang="scss" scoped></style>自定义 tabbar
找到 src>pages.config.ts 文件
- list 里面写你自己的要定义的 tabbar
js
tabBar: {
custon: true,
color: '#999999',
selectedColor: '#018d71',
backgroundColor: '#F8F8F8',
borderStyle: 'black',
height: '50px',
fontSize: '10px',
iconWidth: '24px',
spacing: '3px',
list: [
{
pagePath: 'pages/index/index',
text: '首页',
},
{
pagePath: 'pages/about/about',
text: '关于',
},
{
pagePath: 'pages/me/index',
text: '听风',
},
],
},- 自己在 components>新建一个 CustomTabBar.vue 文件
js
<template>
<wd-tabbar v-model="tabbar" @change="changeItem" fixed>
<wd-tabbar-item title="首页" icon="home" :value="1"></wd-tabbar-item>
<wd-tabbar-item title="关于" icon="cart" :value="2"></wd-tabbar-item>
<wd-tabbar-item title="我的" icon="user" :value="3"></wd-tabbar-item>
</wd-tabbar>
</template>
<script setup>
const tabbar = ref(0)
const changeItem = (index) => {
tabbar.value = index.value
console.log('点击了', index)
if (index.value == 0) {
uni.switchTab({
url: '/pages/index/index',
})
}
if (index.value == 1) {
uni.switchTab({
url: '/pages/about/about',
})
}
if (index.value == 2) {
uni.switchTab({
url: '/pages/me/index',
})
}
}
</script>
<style lang="scss" scoped></style>- 在 list 那几个路径的页面里面引用,并且把原生隐藏
js
onLoad((options) => {
uni.hideTabBar({
animation: false,
});
});