使用 vite 创建项目
指令:npm init vite@latest
1. 安装router
指令:npm install vue-router@4
配置:
import { createRouter, createWebHashHistory } from 'vue-router'
import { routes } from './router'
export const router = createRouter({
history: createWebHashHistory(),
routes
})
import { RouteRecordRaw } from 'vue-router'
export const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'layout',
component: () => import('../views/LayoutPage.vue')
}
]
2. 安装pinia
指令:npm install pinia
import { toRaw } from "vue";
import { createPinia, PiniaPluginContext } from "pinia";
const pinia = createPinia();
type Options = {
key?: string;
};
const _piniaKey: string = "key";
const setStorage = (key: string, value: any) => {
localStorage.setItem(key, JSON.stringify(value));
};
const getStorage = (key: string) => {
return localStorage.getItem(key)
? JSON.parse(localStorage.getItem(key) as string)
: {};
};
const piniaPlugin = (options: Options) => {
return (context: PiniaPluginContext) => {
const { store } = context;
const data = getStorage(`${options?.key ?? _piniaKey}-${store.$id}`);
store.$subscribe(() => {
setStorage(
`${options?.key ?? _piniaKey}-${store.$id}`,
toRaw(store.$state)
);
});
return {
...data,
};
};
};
pinia.use(
piniaPlugin({
key: "pinia",
})
);
export { pinia };
* 注意点
结合全局路由守卫使用,否则只在第一次加载页面或刷新页面触发store.$subscribe()
router.beforeEach((to) => {
const store = userStore()
if (to.name !== 'login' && to.name !== 'register' && store.user.token === ''){
router.replace({name: 'login'})
return false
} else {
return true
}
})
3. 安装scss
指令:npm install --save-dev sass
4. 安装JSX/tsx插件
指令:npm install @vitejs/plugin-vue-jsx -D
5. eslint配置
地址:https:
6. vite.config.ts配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import eslintPlugin from 'vite-plugin-eslint'
export default defineConfig({
plugins: [
vue(),
vueJsx(),
eslintPlugin({
// include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue']
include: ['src/**/*.ts', 'src/**/*.d.ts', 'src/**/*.tsx', 'src/**/*.vue'],
}),
],
resolve: {
alias: {
'@': '/src',
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `
@import '@/assets/scss/variables.scss';
@import '@/assets/scss/mixins.scss';
`,
},
},
},
server: {
port: 3000,
strictPort: true, // 设为true时若端口已被占用则会直接退出,而不是尝试下一个可用端口
https: '',
open: false,
proxy: {
'/api': {
//以 ^ 开头,将会被解释为正则,如:'^/fallback/.*'
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
configure: (proxy, options) => {
},
},
},
},
})
7. request.js工具封装
import axios from "axios";
import qs from "qs";
const request = (url, method = 'get', data = {}, config = {}) => {
axios.defaults.baseURL = import.meta.env.VITE_APP_BASE_API;
data = qs.stringify(data, {indices: false});
let axiosConfig = {
url,
method: method.toLocaleLowerCase(),
timeout: 60000,
withCredentials: true,
}
if (['post'].includes(method.toLocaleLowerCase())) {
axiosConfig['data'] = data
}
if (['get', 'put', 'delete'].includes(method.toLocaleLowerCase())) {
axiosConfig['params'] = data
}
if (config instanceof Object) {
for (let key in config) {
axiosConfig[key] = config[key];
}
}
return axios(axiosConfig).then(res => res.data)
}
axios.interceptors.request.use(
(res) => {
res.headers.post["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8";
return res;
},
(error) => {
return Promise.reject(error);
}
);
axios.interceptors.response.use(res => res, error => Promise.reject(error));
export default request;