preface
The company has been using Vue2 to develop the project. At the last meeting, the director said, “Let’s use VUE3 for our next backstage project. I told you when the project was not busy before, I don’t know if you have learned…” “And let me build the whole structure. Emm.. I’m just kidding. I hope you can learn something useful from this article. If you have any questions, please correct them.
Create a project
This demo uses only part of the Vite configuration. To learn more about vite configuration, go to vite Configuration
Initialize the
Demo uses the VUE-TS template, so: NPM init @vitejs/app vite-app –template vue-ts: NPM install, NPM run dev, NPM run dev
Install dependencies
Style preprocessing: NPM install sass
To use the nodejs module: NPM install @types/node -d otherwise:
Make some simple changes
The main modification is the configuration of vite.config.ts.
1. Configure the path alias for the module
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default DefineConfig ({base: '/', // plugins: [vue()], resolve: {alias: {"@": Resolve (__dirname, "SRC"), / / path alias extensions: [' js', 'vue', 'json', 'SCSS' and 'ts',' * '], / / import to omit the extension of the list}}})Copy the code
2. Pack the configuration
Build: {// package configuration assetsDir: './static', // rollupOptions: {input: {// entry file main: Resolve (__dirname, 'index.html'), // other entries // nested: resolve(__dirname, 'xxxx.index')}},Copy the code
3. Local proxy
Server: {host: '0.0.0.0', // Specify the server hostname port: 8084, // specify the server port. Open: false, // Whether the application is automatically opened in the browser when the server starts. The default is false proxy: {'/API: {target: 'do you want the address of the agent, changeOrigin: true, rewrite: (path) = > path. The replace (/ ^ \ / API /,' ')},}},Copy the code
Then change the build command in package.json to: “build”: “vite build”
start
vue-router4.x
NPM install [email protected], let it run first, let’s create a few new folders and files:
- layouts/error.vue
- router/index.ts
- The router/modules/business. Ts / / configure business routing module
- view/business/manage.vue
- view/login/login.vue
Once built, the directory should look like this:
Router /index.ts router/index.ts
#### router/index.ts import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' const routes: Array < RouteRecordRaw > = [{path: "/", redirect: "/ login,"}, / / * * * * * * * * * * login * * * * * * * * * * {path: / login, name: "login", component: () => import("@/view/login/login.vue").catch(() => { }) }, // **********404********** { path: "/:catchAll(.*)", name: '404', component: () => import("@/layouts/error.vue").catch(() => { }) }, ]; Const Router = createRouter({history: createWebHistory(), // routes with history mode,}); export default Router;Copy the code
Introduced in main.ts:
#### main.ts import {createApp} from 'vue' import App from './ app. vue' import Router from './ Router '// import const App = CreateApp (App) app.use(Router) // Use app.mount('# App ')Copy the code
Finally, modify the contents of app.vue:
#### App.vue <template> <router-view></router-view> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ name: 'App', }) </script>Copy the code
I thought it would run without any problems, but it came as a Surprise!Leave it alone. Keep opening itNetwork
The address of the console printed the following thing, good guy ~, did not understand (0.0)!!
The module script is incorrect. This is not mentality?? Then Baidu for nearly half an hour, no fruit ~, and then I would like to be some dependence is not installed or file reference path is wrong? Then open theLocal
As I expected…And then he followed it up and found itnode_modules/vite/dist/client/client.mjs
..mjs
Document mess (vite
Updated again when I wasn’t looking)~
Before the update:
After the update:
Because in the viet-env.d.ts file:
#### vite-env.d.ts <reference types="vite/client" /> // The clientCopy the code
So add.mjs to the list of extension names you want to omit when importing.
extensions: ['.js', '.vue', '.json', '.scss', '.ts', '.mjs', '*'],
Copy the code
There should be no problem running it again.
element-plus
NPM install elemental-plus. Elemental-plus components use English by default. Then we need to configure the relevant language in main.ts.
#### main.ts import ElementPlus from 'element-plus'; import 'element-plus/lib/theme-chalk/index.css'; import locale from 'element-plus/lib/locale/lang/zh-cn'; Use (ElementPlus,{locale})Copy the code
Add reset. SCSS to assets to reset the style.
#### assets/reset.scss body,dl,dd,h1,h2,h3,h4,h5,h6,p,form { margin: 0; } ol,ul { margin: 0; padding: 0; } li { list-style: none } input,button,textarea { padding: 0; */ table {/* set border collapse for table */ border collapse: */ table {/* set border collapse for table * collapse; /* Set spacing between table borders */ border-spacing: 0px; } /* a {text-decoration: none; } a:hover { text-decoration: none; } individual browser compatible for semantic labels / * * / header section, footer, value, nav, main, article, figure {display: block; } h1, h2, h3, h4, h5, and h6, em, I, b, cite {/ * font style bold * / not the font - weight: normal; font-style: normal; } a,input,button {/* clear click shadow */ -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body * {/* Select text Settings */ -weibkit-user-select: none; /* Disable text scaling */ -webkit-text-size-adjust: 100%; } dl,dd,h1,h2,h3,h4,h5,h6,p,div,li,ul,ol{ box-sizing: border-box; }Copy the code
If in useElement font icon
When, misfortune appearedThe fonts icon
Do not display, or display the box case. You can put filesnode_modules/element-plus/lib/theme-chalk/fonts
Under the.ttf
,.woff
Copy to SRC/Assets 在diystyle.scss
Handles the font icon in themain.ts
The introduction of:
#### diystyle.scs @font-face { font-family: 'element-icons'; src: url("./fonts/element-icons.woff") format("woff"), url("./fonts/element-icons.ttf") format("truetype"); font-weight: normal; font-display: "auto"; font-style: normal; } [class^="el-icon-"], [class*=" el-icon-"] { font-family: 'element-icons' ! important; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; vertical-align: baseline; display: inline-block; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #### main.ts import '@/assets/diystyle.scss';Copy the code
vuex4.x
Run: NPM install [email protected], create a new directory under SRC:
- Store /modules/menu.ts // is used to simulate the menu data returned by the back-end interface
- store/getters.ts
- store/index.ts
To emulate a menu in store/modules/menu.ts:
#### store/modules/menu.ts interface MENU { name: string; path: string; icon? : string; children? : MENU[]; // Define menus with 1} interface STATE {menus: Array<MENU>; // Define array type 2} const state: state = {menus: [{name: "business", path: "/business", icon: "el-icon-s-shop", children: [{name: "business management", path: "/ business/businessManage," icon: ", "},],}},] const mutations = {SET_MENU: (the state: any, data: any) => { state.menu = data } } const action = {} export default { namespace: true, state, mutations, action }Copy the code
Store/getters. Ts for:
#### store/getters.ts
const getters = {
menus: (state: any) => state.menu.menus,
}
export default getters
Copy the code
Store /index.ts introduces modules to modules:
#### store/index.ts import { createStore } from 'vuex' import getters from './getters' interface MODULES { [key: string]: any; } const modulesList = require.context("./modules", false, /\.ts$/); const modules: MODULES = {} modulesList.keys().forEach((modulePath:any) => { const moduleName: String = modulePath. Replace (/ ^ \ \ / (. *) \ \ w + $/, '$1') / / filename const value: Any = modulesList(modulePath) // Take the content of the file modules[moduleName] = value.default // assign}) const Store = createStore({modules, getters }) export default StoreCopy the code
A meal operation.. It turned out to be a tragedy…
And then went to Baidu for a long time, the result isvite
Can’t userequire
, oh my God! I want toImport multiple modules from the file systemHow to do? I did not give up and went to the document, found what I want (-_-)..
It really proves that saying…
I’m wrong, I’ll change, I’ll change it right away.
#### store/index.ts import { createStore } from 'vuex' import getters from './getters' interface MODULES { [key: string]: any; } // const modulesList = require.context("./modules", false, /\.ts$/); const modulesList = import.meta.globEager("./modules/*.ts") const modules: MODULES = {} for (const key in modulesList) { const moduleName: String = key. Replace (/ ^ \. / / modules / / (. *) \ \ w + $/, '$1') / / filename const value: Any = modulesList[key] // Fetch the content of the file modules[moduleName] = value.default // Assign a value} // modulesList.keys().forEach((modulePath:any) => { // const moduleName: String = modulePath. Replace (/ ^ \ \ / (. *) \ \ w + $/, '$1') / / in the file name / / const value: Any = modulesList(modulePath) // modules[moduleName] = value.default // assignment //}) const Store = createStore({modulesPath = modulePath) modules, getters }) export default StoreCopy the code
Well, with all the preparation above, I must write something to reflect it (manual dog head). The structure of the entire page should look like this.
After the overall layout of the interface is planned, the next step is to “assemble” the link, (@_@)~ create several files:
- Layouts /main.vue // Overall layout
- Layouts/components/crumbs. Vue / / bread crumbs
- Layouts/components/header. Vue / / head
- Layouts /Interface // Is a directory that houses modules’ interfaces.
- / / SRC/common/beforRouter ts as a simple route to intercept
Route interception uses the beforeEach navigation hook, which is easy to implement and can be introduced in main.ts:
#### common/beforRouter. Ts import Router from '@/ Router '// Intercepting Router. BeforeEach ((to: any, form: any, next: any) => { if (to.path === '/login') { next(); } else { if (localStorage.getItem('token')) { next() } else { next({ path: '/login' }) } } }) #### main.ts import './common/beforRouter'Copy the code
Let’s go on to improve the class capacity of the login page:
#### view/login/login.vue <template> <div class="login"> <div class="forms"> <div class="title" Width ="80px"> <el-form-item label=" "Class ="is-required" >< el-input V-model ="user" size="small" placeholder=" @keyup.enter="goIndex" ></el-input> </el-form-item> <el-form-item label=" n Code: "Class ="is-required" > <el-input V-model =" PWD" size="small" placeholder=" please input password "show-password@keyup. enter="goIndex" ></ el-form-item> </el-form-item label=" "Class ="is-required" > <el-input V-model ="verCode" size="small" placeholder=" @keyup.enter="goIndex" style="width:50%" ></el-input> <div class="code"> <verificationCode :identify-code="code" /> </div> </el-form-item> </el-form> <div class="btn"> <el-button style="width:100%;" Size ="small" type="primary" @click="goIndex" > </el-button> </div> </div> </template> <script lang="ts"> // Reactive: the realization method of the responsive data / / toRefs: the object of multiple attributes into responsive data / / getCurrentInstance: access to the current instance / / onMounted: {reactive, toRefs, getCurrentInstance, onMounted} from "vue"; import { useRouter } from "vue-router"; import { useStore } from "vuex"; import { ElMessage } from "element-plus"; import "./interface/Login"; / / the interface defined before the introduction of the import verificationCode from "@ / components/verificationCode. Vue"; Export default {name: "Login", components: {verificationCode,}, setup() {const _this: any = getCurrentInstance(); Const store = useStore<any>(); // use vuex const menus = store.state.menu. Menus; Const data: LoginData = reactive({user: "admin", // PWD: "123456", // password verCode: Router: useRouter(), // goIndex: () => {if (! Data.user) {ElMessage({message: "Please enter user name ~", type: "warning", duration: 2000,}); return false; } if (! Data.pwd) {ElMessage({message: "Please enter password ~", type: "warning", duration: 2000,}); return false; } if (! Data.vercode) {ElMessage({message: "Please enter verification code ~", type: "warning", duration: 2000,}); return false; } if (data.verCode ! = data.code) {ElMessage({message: "verification code error ~", type: "warning", duration: 2000,}); return false; } the if (data. User = = = "admin" & & data. PWD = = = "123456") {/ / simulation login const menuList: string | null = JSON. The stringify (menus); localStorage.setItem("menuList", menuList); localStorage.setItem("token", "456456456456456"); localStorage.setItem("userName", "admin"); data.router.push({ path: "/business" }); } else {ElMessage({message: "user name or password error ~", type: "warning", duration: 2000,}); return false; Rand (min: number, Max: number) {return math.floor (math.random () * (max-min)) + min; // Rand (min: number, Max: number) {return math.floor (math.random () * (max-min)) + min; }, // Update the captcode updateCode() {data.code = String(data.rand(1000, 9999)); //4 bit verification code},}); onMounted(() => { data.updateCode(); }); const refData = toRefs(data); return { ... refData, }; }}; </script>Copy the code
I won’t talk about the style here, but go straight to the picture above:
After entering the verification code to log in, you can see, combined with the previous things, you can see a general outline:
axios
NPM install axios install axios, create a few new files under SRC, again using the idea of importing multiple modules from the file system:
- API /modules/admin.ts // stores interface functions
- API/apilist.ts // imports modules files as modules
- API /axios.ts // Simple AXIos encapsulation
- API /url.ts // The interface address of the runtime environment –> baseURL
The logic in apilist.ts is basically the same as when using vuex.
#### API/apilist. ts const req = import.meta. GlobEager ("./modules/*.ts") // Define an API object interface ApiObj {[key: string]: any; } const api: ApiObj = {} for (const key in req) { const name: String = key. Replace (/ ^ \. / / modules / / (. *) \ \ w + $/, '$1') / / filename const value: Any = req[key] // Fetch the content of the file API [name] = value.default // Assignment} const API = API export default API #### API /modules/admin.ts import { AxiosPromise } from "axios"; import http from ".. /axios"; // encapsulate from API /axios.ts const admin ={userLogin(params: any): AxiosPromise<any> {return HTTP ({url: "/auth-service/common/login", // method: "POST", data:params,}); } } export default admin;Copy the code
Then mount the API globally:
# # # # main. Ts import API from ". / API/apiList "/ / mount app. Config. GlobalProperties. = $API APICopy the code
To use in view/login/login.vue:
#### view/login/login.vue import { getCurrentInstance } from "vue"; export default { setup() { const _this: any = getCurrentInstance(); Const API: any = _this.ctx.$API; Api.admin.userlogin (obj). Then ((res: any) => {..... }); }}Copy the code
The end of the
Now the company’s PC side project is based on this template to change, you can modify according to their business needs oh ~~ demo address: gitee.com/Srimr/vite-… References:
- Vue3 Chinese document
- Vite Chinese document
- Element Plus
- TypeScript