Article directory
Preface
提示:这里可以添加本文要记录的大概内容:
The project uses technology stack vue3+vuex+router+ts+element plus
提示:以下是本篇文章正文内容,下面案例可供参考
Create a vite project
npm create vite@latest name //name is the project name
npm create vite@latest name
//根据提示选择
//创建后
cd name
npm i
npm run dev//运行项目
vite.config.ts configuration
Install plugin
Automatically introduce component configuration and references to .env configuration
npm i -d autoprefixer unplugin-auto-import unplugin-vue-components unplugin-vue-components unplugin-icons
import {
defineConfig,loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import autoprefixer from 'autoprefixer'
// https://vitejs.dev/config/
//自动引入element plus
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'//组件引入(包含本地组件)
import {
ElementPlusResolver} from 'unplugin-vue-components/resolvers'
import Icons from 'unplugin-icons/vite'//图标引入
import IconsResolver from 'unplugin-icons/resolver'
//IE和旧版chrome兼容
// import legacyPlugin from '@vitejs/plugin-legacy'
import {
resolve } from "path"
export default (({
mode})=>{
const VITE_ENV: string = loadEnv(mode, process.cwd()).VITE_ENV;
const VITE_APP_BASE_URL: string = loadEnv(mode, process.cwd()).VITE_APP_BASE_URL;
const VITE_APP_BASE_API: string = loadEnv(mode, process.cwd()).VITE_APP_BASE_API;
return defineConfig({
base:'/',
assetsInclude:['**/*.png'],
server: {
open:false,//项目启动时自动打开浏览器
host:true,
hmr:true,//开启热加载
proxy: {
// with options
[VITE_APP_BASE_API]: {
target: VITE_APP_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(VITE_APP_BASE_API, '')
}
}
},
plugins: [
vue(),
AutoImport({
imports:['vue'],
resolvers:[
//自动导入element plus相关函数,如:ElMessage
ElementPlusResolver({
importStyle:'sass'
}),
IconsResolver({
prefix:'Icon'
})
],
}),
Components({
resolvers:[
//自动导入element plus组件
ElementPlusResolver({
importStyle:'sass'
}),
//自动注册图标组件
IconsResolver({
enabledCollections:['ep']
}),
]
}),
Icons({
autoInstall:true
}),
//在plugins配置数组里添加legacy插件
// legacyPlugin({
// targets: ['chrome 52'], // 需要兼容的目标列表,可以设置多个
// additionalLegacyPolyfills: ['regenerator-runtime/runtime'] // 面向IE11时需要此插件
// }),
],
css: {
postcss: {
plugins: [
autoprefixer({
overrideBrowserslist: [
"Android 4.1",
"iOS 7.1",
"Chrome > 31",
"ff > 31",
"ie >= 8",
"last 10 versions", // 所有主流浏览器最近10版本用
],
grid: true,
}),
// postCssPxToRem({
// rootValue: 204, // 设计稿宽度的1/ 10 例如设计稿按照 1920设计 此处就为192
// propList: ["*", "!border"], // 除 border 外所有px 转 rem
// selectorBlackList: [".el-"], // 过滤掉.el-开头的class,不进行rem转换
// })
]
}
},
resolve: {
alias: {
"@": resolve(__dirname, "src"),
"img":resolve(__dirname, "src/assets/"),
'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js',
},
},
build:{
target: "es2015",
outDir:'dist',
assetsDir:"static",
sourcemap: false,
minify: "terser",
chunkSizeWarningLimit: 1000,
cssTarget: "chrome61",
cssCodeSplit: true, // 启用 CSS 代码拆分
assetsInlineLimit:100,//png单独分离 >0.1kb才会分离
terserOptions: {
compress: {
drop_console: true,
// drop_debugger: true,
},
},
rollupOptions: {
output: {
// 指定打包输出的js文件名称
chunkFileNames: "static/js/[name]-[hash].js",
entryFileNames: "static/js/[name]-[hash].js",
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
// assetFileNames: "[ext]/[name]-[hash].[ext]"
//设置css和图片的文件夹名称,但是有弊端,css设置的背景图片访问不到,路径是错误的
//静态资源分拆打包
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
if (id.includes('components')) {
return id.toString().split('components/')[1].split('/')[0].toString();
}
}
}
}
}
})
})
Create src/vite-env.d.ts
解决vue组件引入报红,
/// <reference types="vite/client" />
//解决.vue引入报红线
declare module '*.vue' {
import Vue from '@/vue'
export default Vue
}
interface ImportMetaEnv {
readonly VITE_APP_BASE_URL: string
// 更多环境变量...
}
main.ts configuration
Introducing element plus language configuration, the user page displays a separate configuration folder
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router";
import {createPinia} from "pinia";
//语言配置
import i18n from './lang/index.js'
import store from './store'
import "@/styles/elementplus.scss"
import '@/styles/index.scss' // global css
//用户显示,全局引入
import {admin} from '../public/static/config_menu/admin'
import {operator} from '../public/static/config_menu/operator'
import {user} from '../public/static/config_menu/user'
const app = createApp(App)
app.config.globalProperties.$Config_admin = admin
app.config.globalProperties.$Config_operator = operator
app.config.globalProperties.$Config_user = user
//
app.use(i18n).use(router).use(store).use(createPinia()).mount('#app')
api/request.ts
axios request interception, response interception configuration, and use within axios
import axios from "axios";
var util = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
const service = axios.create({
baseURL:import.meta.env.VITE_APP_BASE_URL,
// timeout: 5000 // request timeout
withCredentials: true,
});
// 发起请求之前的拦截器
service.interceptors.request.use(
config => {
// 如果有token 就携带tokon
console.log(config.headers);
const token = window.localStorage.getItem("Authorization");
if (token) {
config.headers.Authorization = token;
config.headers['Content-Type']='application/x-www-form-urlencoded'
}
return config;
},
error => Promise.reject(error)
);
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data;
if (res.code != 200) {
return ElMessage.error(res.msg)
} else {
return res;
}
},
error => {
return Promise.reject('未连接到服务器:'+error);
}
);
export default service;
Introduce and use
import request from './request'
//ipsec proposal get
export function getikeproposal() {
return request({
url: '路径',
method: 'get'
})
}
lang language
Language profile
import { createI18n } from 'vue-i18n'
import en from './en'
//引入的不同语言文件
const messages = {
en
}
//这个类型可以自己配置,毕竟每个人做的都不一样
const i18n:any =createI18n( {
legacy: false, // 使用 Composition API 模式,则需要将其设置为false
globalInjection: true, //全局生效$t
locale: 'en', // 默认cn翻译
messages //ES6解构
})
export default i18n;
a.ts
English
export default {
config: {
Flush: "Flush",
Refresh: "Refresh",
Information: "Information",
interface: "Interface",
}
}
router
Routing and route interception configuration files
import {createRouter, createWebHashHistory, RouteRecordRaw} from "vue-router"
const routers: Array<RouteRecordRaw> = [
{
path: '/index',
component:()=>import('@/view/contentPage/menuList.vue'),
},
{ // login
path: '/login',
component: () => import('@/view/login.vue'),
},
]
const router = createRouter({
history: createWebHashHistory(),
routes: routers
})
// 导航守卫
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('Authorization')
if(to.path=='/'){
next('/login')
localStorage.removeItem('Authorization')
}else if(to.path=='/index'){
if(token){
next()
}else{
next('/login')
}
}else{
next()
}
})
export default router;
Cookies package
Cookies encapsulation use
import Cookies from 'js-cookie'
export const setCookie = (label: string, value: any, cookieExpires: any) => {
// 名称 保存的值 保存的时间
Cookies.set(label, value, { expires: cookieExpires })
}
export const getCookie = (label:string) => {
const value = Cookies.get(label)
if (value) return value
else return false
}
export const delCookie = (label:string) => {
Cookies.remove(label)
}
Environment configuration
Development and production environment configuration
# .env.development
VITE_ENV = 'development'
VITE_APP_BASE_URL = http://192.168.9.62:8080
VITE_APP_BASE_API = '/api'
# .env.production
VITE_ENV = 'production'
VITE_APP_BASE_URL=http://192.168.0.1:8060
VITE_APP_BASE_API = '/api'
# stage
VITE_ENV = 'staging'
VITE_APP_BASE_URL = http://device.net
VITE_APP_BASE_API = '/'
nodemon.json
Support automatic update after vite.config.ts changes
{
"ignore": ["node_modules", "dist"],
"exec": "vite --mode development",
"watch": ["vite.config.ts"]
}
package.json
Plug-ins used, project running commands
{
"name": "project-name",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --mode development",
"dev:node": "nodemon",
"build": "vue-tsc && vite build --mode production",
"build:stage": "vite build --mode staging",
"preview": "vite preview"
},
"dependencies": {
"@types/js-cookie": "^3.0.3",
"@vueform/slider": "^2.1.7",
"axios": "^1.3.2",
"element-plus": "2.1",
"js-cookie": "^3.0.1",
"nodemon": "^2.0.22",
"pinia": "^2.0.30",
"postcss-pxtorem": "^6.0.0",
"sass": "^1.58.0",
"terser": "^5.16.3",
"vue": "^3.2.45",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.6",
"vue3-slider": "^1.8.0",
"vuex": "^4.0.2"
},
"devDependencies": {
"@types/node": "^18.11.18",
"@vitejs/plugin-legacy": "^4.0.2",
"@vitejs/plugin-vue": "^4.0.0",
"amfe-flexible": "^2.2.1",
"autoprefixer": "^10.4.13",
"typescript": "^4.9.3",
"unplugin-auto-import": "^0.7.2",
"unplugin-element-plus": "^0.7.0",
"unplugin-icons": "^0.15.2",
"unplugin-vue-components": "^0.23.0",
"vite": "^4.1.0",
"vue-tsc": "^1.0.24"
}
}
Summarize
Tip: Here is a summary of the article: This article explains how to introduce router, store, element plus, etc. into the vue3 vite creation project, which can be used for development, as well as basic TS use, and you can read the code yourself.