Vite3.0+Vue3+TypeScript+Pinia+Vant搭建移动端项目
1、项目初始化
按步骤提示创建项目
1.使用vite-cli命令创建项目
yarn create vite
2.输入项目名称
success Installed "create-vite@3.0.0" with binaries:
- create-vite
- cva
? Project name: » vite-project
3.选择项目使用的框架,在这里我们选择使用vue,默认是vue3
? Select a framework: » - Use arrow-keys. Return to submit.
vanilla
> vue
react
preact
lit
svelte
4.项目是否使用TypeScript
? Select a variant: » - Use arrow-keys. Return to submit.
vue
> vue-ts
5.进入项目,下载包,启动项目
cd vite-vue3-ts-pinia
yarn
yarn dev
2.初始配置的调整
1.下载@types/node
//node.js本身并不支持typescript,所以直接在typescript项目里使用是不行的
yarn add @types/node
2.vite.config.ts文件
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
base: './',// vite打包的前端项目默认只能通过根目录访问项目,比如http://localost:3000/,如果加上一个路径在进行访问会导致资源文件访问404,所以需要设置base路径
plugins: [
vue(),
],
resolve: {
// 设置路径简写
alias: {
'@': path.resolve(__dirname, './src'),
}
},
server: {
port: 80, //启动端口
host: '0.0.0.0',
open: '/',
// 设置 https 代理
proxy: {
'/api': {
target: 'address',
changeOrigin: true,
rewrite: (path: string) => path.replace(/^/api/, ''),
},
},
},
build: {
// 提高超大静态资源警告门槛 默认500kb,修改为1500kb
chunkSizeWarningLimit: 1500,
// 清除console和debugger
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
rollupOptions: {
output: {
//对静态文件进行打包处理(文件分类)
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
}
},
outDir:'打包后输出文件位置',
}
}
});
3.Pinia
1.下载pinia
yarn add pinia
2.使用 官方文档:链接
1.src/store 目录并在其下面创建 index.ts,导出 store
import { createPinia } from 'pinia'
const store = createPinia()
export default store
2.在 main.ts 中引入并使用
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
// 创建vue实例
const app = createApp(App)
// 挂载pinia
app.use(store)
// 挂载实例
app.mount('#app');
3.定义State: 在 src/store 下面创建一个 user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore({
id: 'user', // id必填,且需要唯一
state: () => {
return {
name: '张三'
}
},
actions: {
updateName(name) {
this.name = name
}
}
})
4.获取State: 在 src/components/usePinia.vue 中使用
<template>
<div>{{ userStore.name }}</div>
</template>
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
</script>
5.修改State:
// 1. 直接修改 state (不建议)
userStore.name = '李四'
// 2. 通过 actions 去修改
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
userStore.updateName('李四')
</script>
4.vue-router4
1.下载
yarn add vue-router
2.使用
1.在src/router路径下创建router.ts并到导出router
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'home',
meta: {
title: '首页',
keepAlive: true,
intercept: false, // 校验登录
},
component: () => import('../views/home/index.vue'),
},
{
path: '/my',
name: 'my',
meta: {
title: '我的',
keepAlive: true,
intercept: false,
},
component: () => import('../views/my/index.vue'),
},
{
path: '/my/setup',
name: 'setup',
meta: {
title: '设置',
keepAlive: true,
intercept: false,
},
component: () => import('../views/my/setUp.vue'),
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
2.在main.ts中引入并使用
import { createApp } from 'vue';
import App from './App.vue';
import router from '@/router/router';
const app = createApp(App);
app.use(router);
app.mount('#app');
3.路由拦截
src下创建permission文件,内容如下:
import router from "@/router/router"
import { useUserInfo } from "@/store"
router.beforeEach((to: any, from: any, next: any) => {
const userInfo = useUserInfo()
const token = userInfo.token ?? false
const url = to.path
// 1.已登录 去登录页->跳转首页
if (token && url === '/login') {
next('/')
}
// 2.已登录 去其他页面->放行
if (token && url !== '/login') {
next()
}
// 3.未登录且intercept为true->跳转登录页
if (!token && to.meta?.intercept) {
next('/login')
}
// 4.未登录且intercept为false->放行
if (!token && !to.meta?.intercept) {
next()
}
})
在main.ts中引入
import './permission'
5.vant 官方文档:链接
1.下载vant本体
yarn add vant
2.下载按需引入插件
yarn add unplugin-vue-components -D
3.配置插件,vite.config.ts文件中配置
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [
vue(),
Components({
resolvers: [VantResolver()],
}),
],
}
})
4.tip
Vant 中有个别组件是以函数的形式提供的,包括 Toast,Dialog,Notify 和 ImagePreview 组件。在使用函数组件时,unplugin-vue-components 无法自动引入对应的样式,因此需要手动引入样式。
main.ts
import 'vant/es/toast/style';
import 'vant/es/dialog/style';
import 'vant/es/notify/style';
import 'vant/es/image-preview/style';
6.移动端rem适配
1.下载
yarn add postcss-pxtorem amfe-flexible
2.vite.config.ts文件中使用
import { defineConfig, loadEnv } from 'vite';
import postCssPxToRem from 'postcss-pxtorem'
// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
...
css: {
postcss: {
plugins: [
postCssPxToRem({
// vant组件的兼容处理
rootValue({ file }) {
return file.indexOf('vant') !== -1 ? 37.5 : 72;
},
propList: ['*'],
selectorBlackList: ['van']
})
]
}
},
...
}
});
3.main.ts中使用
import "amfe-flexible";//引入rem
7.axios
1.下载
yarn add axios
2.使用
1.src/utils/axios.ts
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios';
const service = axios.create({
// 本地开发时使用proxy代理接口
baseURL: import.meta.env.VITE_MODE === "development" ? '/api' : import.meta.env.VITE_AXIOS_URL,
timeout: 10000
}); // Request interceptors
service.interceptors.request.use(
(config: AxiosRequestConfig) => {
// do something
return config;
},
(error: any) => {
Promise.reject(error);
}
); // Response interceptors
service.interceptors.response.use(
(response: AxiosResponse) => {
// do something
return Promise.resolve(response)
},
(error: any) => {
// do something
return Promise.reject(error);
}
);
export default service;
2.src/api/login.ts
import request from '@/utils/axios';
/**
* @description: 账号登录
* @param {string} username 账户
* @param {string} password 密码
* @return {*}
*/
export const sign_in = (username: string, password: string) => {
return request.get('/', { username, password });
}
\