Use of vue vite to create projects (using technology stack vue3+vuex+router+ts+element plus)


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.

Guess you like

Origin blog.csdn.net/yang20000222/article/details/130917251