Description:
Before, I built the background management system of Vue3 from zero to one in a project. When I wrote this paper, I wanted to use the current version, but as a result, I encountered many compatibility problems with plug-in versions. Remembering the pit I stepped on before, I gave up the idea because of the limited time and level.
This article uses node version 14.16.1. If you have a similar version of Node, try compatibility or use NVM to install it.
1. Vite creates a project
Speaking of Vite, if you are fed up with webpack startup service 40S +, hot update 6s+, be sure to have a look at Vite, really very fragrant!
Here, I also use Vite for project creation, and the documentation provides examples that can be used
yarn create vite my-vue-app --template vue
Copy the code
For Vite+Vue project creation, there are also several template presets provided below, since I’m using TS, the command I’m using here is
yarn create vite my-vue-app --template vue-ts
Copy the code
Then go to the directory, yarn installs dependencies, and Yarn Dev starts the service
Note: Because Vite keeps updating versioning issues, if you create a project using the above command, it will not be consistent with the code on the branch. Project Address
2. Integrate JEST unit tests
1. Install the jest
Yarn add [email protected] - DCopy the code
2. Create the first test
Create the tests folder in the root directory, and create an internal unit folder to store the unit test file. In the Unit folder, write our first test file index.spec.js
test('1+1=2',() => {
expect(1+1).toBe(2)
})
Copy the code
Configure commands in package.json
"scripts": {
"test-unit":"jest"
}
Copy the code
Run YARN test-unit and the first test case passes
3. Add the automatic prompt plug-in
There are no code hints when writing test cases above, which makes it very inefficient, so install @types/jest to implement code hints
Yarn add @ types/[email protected] - DCopy the code
4. Support the import
Next we’ll write a test file foo.js in the Unit folder
export default function (){
return 'this is foo'
}
Copy the code
Modified index. Spec. Js
import foo from './foo.js'
test('1+1=2',() => {
expect(1+1).toBe(2);
})
test('foo',() => {
expect(foo()).toBe('this is foo')
})
Copy the code
An error occurred when yarn test-unit was executed again. Procedure
You will find that Jest does not recognize the import syntax because jest is based on the Node environment, so you need to convert the import syntax into a syntax that NodeJS can recognize
Create jest. Config.js in the root directory for jEST configuration
Module. exports = {// converters transform: {// jest parses js through babel-jest "^.+\\.jsx? $": "babel-jest" } };Copy the code
Install Babel – jest
Yarn add [email protected] - DCopy the code
Because Babel is used, you also need to create the Babel configuration in the root directory babel.config.js
Module. exports = {presets: [[// install the official preset plugin "@babel/preset-env", // specify the target of the resolution is the native Node version {targets: {node: "current" } } ], ], };Copy the code
Install @ Babel/preset – env
Yarn add @ Babel/[email protected] - DCopy the code
Run yarn test-unit again and the test passes
5. Support.vue files
Create foo. vue under SRC/Componens
<template>
<div>
Foo
</div>
</template>
Copy the code
Modified index. Spec. Js
import foo from './foo.js' import Foo from '.. /.. /src/components/Foo.vue 'test('1+1=2',() => { expect(1+1).toBe(2); }) test('foo',() => { expect(foo()).toBe('this is foo') }) test('Foo',() => { console.log('Foo',Foo) })Copy the code
After yarn test-unit is executed, an error occurs. The syntax of the VUE cannot be parsed
Here we need to add rules to parse.vue files in jest. Config. js
Module. exports = {// converters transform: {// jest parses js through babel-jest "^.+\\.jsx? $", "Babel - jest", / / jest vue of time through the vue - jest parse "^. + \ \. Vue $"," vue - jest "}};Copy the code
Install the vue – jest
yarn add vue-jest@next -D
Copy the code
The yarn test-unit test fails again because the TS-Jest dependency is missing
3
Install the ts – a jest
Yarn add [email protected] - DCopy the code
Run yarn test-unit again and the test succeeds
6. Install Vue Test Utils
Vue Test UtilsVue unit test library Vue unit test library Vue unit test library Vue unit test library Vue unit test library
yarn add @vue/test-utils@next -D
Copy the code
Modified index. Spec. Js
import foo from './foo.js' import {mount} from '@vue/test-utils' import Foo from '.. /.. /src/components/Foo.vue 'test('1+1=2',() => { expect(1+1).toBe(2); }) test('foo',() => { expect(foo()).toBe('this is foo') }) test('Foo',() => { console.log('Foo',Foo) console.log('mount',mount(Foo)) })Copy the code
The yarn test-unit test succeeds. Procedure
7. Support for ts
If you change the js test file to.ts and yarn test-unit, you must add converter configuration in jest. Config. js as before
Module. exports = {// converters transform: {// jest parses js through babel-jest "^.+\\.jsx? $", "Babel - jest", / / jest vue of time through the vue - jest parse "^. + \ \. Vue $"," vue - jest, "/ / jest ts by ts - jest parse" ^. + \ \. TSX? $": "ts-jest" } };Copy the code
Ts-jest has been installed before, so there is no need to repeat the installation
Modify the babel.config.js configuration
Module. exports = {presets: [[// install the official preset plugin "@babel/preset-env", // specify the target of the resolution is the native Node version {targets: {node: "current" } } ], "@babel/preset-typescript" ] };Copy the code
Install @ Babel/preset – typescript
Yarn add @ Babel/[email protected] - DCopy the code
Run yarn test-unit test. Pass the Project Address test.
3. Integrate Cypress E2E tests
1. Install the Cypress
Yarn add [email protected] - DCopy the code
Package. json Command “test-e2e”:”cypress open “and run it
The first time we perform initialization, we will create a cypress folder in the root directory, there will be cypress-related files, after initialization will automatically open a window
So there will be a popup box that we can choose which CI environment we want to use Cypress in, but we don’t need it here, so we can just turn it off, okay
In the upper right corner, you can switch to the relevant document of the browser running the test environment
Here are all the test cases, clicking on which opens in the browser to test against the script
2. Adjust the directory
In our project, we wanted everything related to tests to be placed in the Tests folder, so we created the e2E folder under tests and copied all the files from the root directory cypress
Yarn test-e2e: Cypress checks whether there is a Cypress folder in the root directory every time. If there is no cypress folder, you need to modify the configuration in cypress.json
{
"pluginsFile":"tests/e2e/plugins/index.js"
}
Copy the code
Then modify the configuration documentation in plugins/index.js
module.exports = (on, config) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config return // fixtures path fixturesFolder: "tests/e2e/fixtures", // fixtures: "Tests /e2e/specs", // screenshotsFolder path to save screenshots from the cy.screenshotsFolder () command or if a test fails during Cypress: VideosFolder: "Tests /e2e/videos", // The path of the files loaded before loading the test files. This file is compiled and bundled. (by false disabled) supportFile: "tests/e2e/support/index. The js"}); }Copy the code
Note that the previous Integration folder has been renamed to Specs
Perform yarn test – e2e
The following pop-up window appears
The Cypress folder is not created in the root directory
3. Support for ts
First, change all.js files in the e2e folder to.ts
Then modify the configuration in e2e/plugins/index.ts
module.exports = (on: any, config: Cypress.PluginConfig) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress Config return Object. Assign ({}, config, {// fixtures path fixturesFolder: Fixtures: "Tests /e2e/fixtures", // Fixtures: "Tests /e2e/specs", // screenshotsFolder path to save screenshots from the cy.screenshotsFolder () command or if a test fails during Cypress: VideosFolder: "Tests /e2e/videos", // The path of the files loaded before loading the test files. This file is compiled and bundled. (by false disabled) supportFile: "tests/e2e/support/index. The ts",}); };Copy the code
Modify the configuration in cypress.json
{
"pluginsFile":"tests/e2e/plugins//index.ts"
}
Copy the code
Clear the sample test files under tests/e2e/specs and create index.spec.ts
describe("index", () => {
it("button click", () => {
cy.visit("http://localhost:3000/");
cy.get("button").click();
});
});
Copy the code
Run yarn test-e2e. The following window pops up:
Click on index.spec.js and Cypress will open the configured browser and execute the test script for us
You can see that the button click has been triggered because the red value at the top changes from 0 to 1 and the button Click test case in index.spec.ts is prompted to pass on the left
4. Solve the problem of JEST test coverage of E2E
If yarn test-unit is executed, an error message is displayed
At this point, we find that executing the Jest unit test also executes the cyress test file, changes the jest.config.js configuration, and specifies the test script matching rules
Module. exports = {// converters transform: {// jest parses js through babel-jest "^.+\\.jsx? $", "Babel - jest", / / jest vue of time through the vue - jest parse "^. + \ \. Vue $"," vue - jest, "/ / jest ts by ts - jest parse" ^. + \ \. TSX? $", "ts - jest"}, / / configure the test script file matching rules testMatch: [" * * / tests/unit /? (*) + (spec). [jt] s? (x) "],};Copy the code
Run yarn test-unit yarn test-e2e in sequence. The discovery succeeds
5. Integrate Jest & Cypress tests
Package. json Command “test”:” NPM run test-unit && NPM run test-e2e” and run the command
You can see in the terminal that the JEST test has passed and the Cypress window has opened, at which point we want the Cypress test to be running on the terminal as well.
Cypress provides another command to perform tests, cypress run, which we add to package.json
“Test-e2e-ci “:”cypress run” and run it. The cypress test can be performed on the terminal
"test":"npm run test-unit && npm run test-e2e-ci"
Copy the code
Run yarn test. Both jest and Cypress can be completed on the terminal
6. Disable video generation by Cypress
When we performed cypress tests on the terminal, we found a video folder in the Tests /e2e folder containing an index.sepc.ts.mp4 file. When we opened it, we found that the video was a screen recording of the test process. In this case, we don’t need the.mp4 file. It takes up memory and increases test time
{
"pluginsFile":"tests/e2e/plugins/index.ts",
"video":false
}
Copy the code
At this point, the integrated Cypress E2E test is complete. Project Address
4. Integration eslint
1. Install ESLint and its dependencies
Yarn add [email protected] [email protected] @vue/[email protected] @typescript-eslint/[email protected] @ typescript - eslint/[email protected] - DCopy the code
eslint
Without further ado, our target, code inspection tool
eslint-plugin-vue
The official ESLint plugin for vue.js provides support for Vue code in.js files
@vue/eslint-config-typescript
Support for writing TS code in Vue components
@typescript-eslint/parser
A TS parser for ESLint
@typescript-eslint/eslint-plugin
The ESLint plugin for TS
Next create an.eslintrc file in the root directory for the ESLint configuration
{// Specify the current directory as the root directory "root": true, // environment configuration item "env": {// Whether browser environment "browser": true, // Whether node environment "node": True, // ES2021 supports "ES2021 ": true}, // introduces configuration item "extends": [ // vue3 "plugin:vue/vue3-recommended", // eslint "eslint:recommended", / / the vue typescript "@ vue/typescript/it"], / / parser configuration "parserOptions" : {/ / to use grammar ECMAScript version "ecmaVersion" : 2021}}Copy the code
Configure the eslint command in package.json for scripts
"lint":"eslint --ext .ts,vue src/**"
Copy the code
Check all.ts,.vue files in SRC directory
In this case, run yarn lint
You’ll notice that there are some warnings and errors
Let’s add one more command here
"lint:fix":"eslint --ext .ts,vue src/** --fix"
Copy the code
Fix will help us automatically fix some of the warnings
After running YARN Lint :fix, all warnings disappear except one error
For images that do not have a parser configured, you can configure the.eslintignore file in the root directory to make esLint ignore certain files or directories
node_modules
dist
src/assets
index.html
Copy the code
Run yarn Lint :fix again and the discovery can pass
2. Integrated lint – staged
Git staging: git staging: git staging: git staging: git staging: git staging: git staging: git staging: git staging
Lint-passage and Yorkie are required here, using passage passage
Yarn add [email protected] [email protected] -dCopy the code
To install, you need to do some configuration in package.json
"gitHooks": {
"pre-commit": "lint-staged"},
"lint-staged": {
"*.{ts,vue}": "eslint --fix"
}
Copy the code
This configuration will call Lint-staged, which will perform eslint –fix on all.ts,.vue files before committing
App.vue: HelloWorld app.vue: HelloWorld app.vue: HelloWorld app.vue: HelloWorld app.vue: HelloWorld app.vue
It indicates that the verification we configured has taken effect. Project Address
5. Integrated Prettier
Prettier helps us beautify and unify our code, so we integrate it here too.
Installing Prettier and related dependencies
Yarn add [email protected] [email protected] @vue/[email protected] -dCopy the code
eslint-plugin-prettier
Support for Prettier to work in ESLint
@vue/eslint-config-prettier
Supports partial conflicts between esLint code verification rules and Prettier code verification rules
The configuration is added to the.eslintrc file
{// Specify the current directory as the root directory "root": true, // environment configuration item "env": {// Whether browser environment "browser": true, // Whether node environment "node": True, // ES2021 supports "ES2021 ": true}, // introduces configuration item "extends": [ // vue3 "plugin:vue/vue3-recommended", // eslint "eslint:recommended", // vue typescript "@vue/typescript/recommended", "@vue/prettier", "@vue/prettier/@typescript-eslint" ], // Parser configuration "parserOptions": {// to use the ECMAScript syntax version "ecmaVersion": 2021}}Copy the code
The NPX prettier -w -u command is used.
-w: Edit files in-place. (Beware!) Edit files in place. (Beware!)
-u: Ignore unknown files. Ignore unknown files.
. Specify the current path
Prettier formatting some files, opening changes to app.vue
Prettier automatically modifies newlines, Spaces, double quotes and so on according to prettier’s rules
You can then document Prettier by creating an.prettierrc file in the root directory
{whether ending semicolon "semi": true, whether single quotation mark "singleQuote": false}Copy the code
If prettier was removed from a file, NPX prettier -w-u. Prettier would add a semicolon at the end of a line
Finally, prettier was integrated into Lint-staged and package.json was modified for ease of use
"lint-staged": {
"*.{ts,vue}": "eslint --fix",
"*": "prettier -w -u"
}
Copy the code
By then, the project integration prettier was complete. Project Address
6. Integrate COMMIT Message verification
The specification of the Commit Message is also important for the team. A specification of the Commit message will make it very clear when we look back at git history, and here we are using uVU’s approach in VUE
This method relies on the Yorkie library, which we installed when we integrated Lint-staged and will not repeat here.
Configuration package. Json gitHooks
"gitHooks": {
"commit-msg":"node scripts/verify-commit-msg.js",
"pre-commit": "lint-staged"
}
Copy the code
Scripts /verify-commit-msg.js
The verify-commit-msg.js file can be copied directly from your vUE project.
The general logic of this file is to read the commit message in the Git file through the FS module and verify it through the re.
If the verification fails, an error message is displayed and git commit is blocked
One possible problem here is that ESLint will issue a warning when copying verify-commit-msg.js to the file
Require statement not part of import statement.
Copy the code
You can disable the verification by configuring the following rules in.eslintrc
"rules":{
"@typescript-eslint/no-var-requires": 0
}
Copy the code
The chalk library is used in verify-commit-msg.js, and chalk provides the function of setting console colors in the terminal
Install chalk yarn add chalk -d
Git commit -m “test” can intercept a commit mesage that does not meet the requirement
I am running Windows 10 and found chalk is not in effect, so I need to add the second line of code below in verify-commit-msg.js
Git commit -m “test” is used to test chalk
At this point, the commit- MSG integration is complete. Project Address
7. Add test to gitHooks
Above we added jest unit tests and Cypress e2E tests and integrated them, but generally we don’t want to execute the tests manually every time we commit code, we want to automate the tests to ensure that the code pushed to Git is correct. We do this by adding Git hooks to package.json
"gitHooks": {
"commit-msg": "node scripts/verify-commit-msg.js",
"pre-commit": "lint-staged",
"pre-push": "npm run test"
}
Copy the code
This is set to run the test command before git push, where we configured the jest and cypress tests so that the test script is run before git push
This step is relatively simple, and the code is merged into the branch that integrates the commit- MSG step. Project Address
8. Configure the alias path alias
The purpose of a path alias is to simplify operations to a specified path by specifying symbols.
1. Configuration vite. Config. Js
For example, helloworld.vue is used in views/ home. vue
import HelloWorld from ".. /components/HelloWorld.vue";Copy the code
If level deep some, such as working in the views/Goods/List/index. The vue, just need to
import HelloWorld from ".. /.. /.. /components/HelloWorld.vue";Copy the code
As you can see, this is cumbersome, and if the location of the helloWorld.vue file changes, all the helloWorld.vue incoming code is cumbersome to modify. To solve this problem, Vite also provides a method to configure the alias. Modify vite.config.js as follows:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
"@": resolve("./src")
},
},
plugins: [
vue()
]
})
Copy the code
Here we have set the @ symbol to point to the./ SRC directory. In the future, no matter in which file, use the following code to import
Helloworld.vue, file location changes, can also be unified replacement
import HelloWorld from "@/components/HelloWorld.vue";
Copy the code
The location of the file has changed, and there is no need to adjust it, which is a great convenience for us.
But we’re not done here. When introducing code, you can see that vscode has a path prompt when we write./, but when we write @/, there is no path prompt, so we need to do some configuration for ts.
2. Configure the TS to support aliases
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client", "jest", "node"],
"baseUrl":"./",
"paths":{
"@/*":["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
Copy the code
BaseUrl: Specifies the current directory
Paths is our alias configuration, which means the same as the configuration in vite.config.js, go back to the.vue file again, use @alias to introduce HelloWorld
3. Configure jEST to support aliases
Next we try to use alias in jest unit tests, modifying tests/unit/index.spec.ts
import foo from "./foo";
import { mount } from "@vue/test-utils";
import Foo from "@/components/Foo.vue";
test("1+1=2", () => {
expect(1 + 1).toBe(2);
});
test("foo", () => {
expect(foo()).toBe("this is foo");
});
test("Foo", () => {
console.log("Foo", Foo);
console.log("mount", mount(Foo));
});
Copy the code
Vscode will give us an error message after the modification
Then we try to execute YARN test-unit
Jest does not recognize @path alias, so we need to modify jest. Config.js
Module. exports = {// converters transform: {// jest parses js through babel-jest "^.+\\.jsx? $", "Babel - jest", / / jest vue of time through the vue - jest parse "^. + \ \. Vue $"," vue - jest, "/ / jest ts by ts - jest parse" ^. + \ \. TSX? $", "ts - jest"}, / / configure the test script file matching rules testMatch: [" * * / tests/unit /? (*) + (spec). [jt] s? "(x)], / / configuration path alias moduleNameMapper: { "^@/(.*)$": "<rootDir>/src/$1" } };Copy the code
Then run yarn test-unit again and the test succeeds. Project Address
9. Integrate Vue Router
Vue Router is the official route to Vue. Js
yarn add vue-router@next
Copy the code
Create a router folder in SRC and write index.ts
import { createRouter, createWebHashHistory } from "vue-router"; export const routes = [ { path: "/", redirect: "/home" },{ path: "/home", name: "Home", component: () => import("@/views/Home.vue") },{ path: "/login", name: "Login", component: () => import("@/views/Login.vue") },{ path: "/404", name: "404", hidden: true, meta: { notNeedAuth: true }, component: () = > import (" @ / views / 404. Vue ")}, / / match all path used vue2 * vue3 / : pathMatch (. *) or / : catchAll (. *) {path: "/:catchAll(.*)", redirect: "/404" } ]; Const router = createRouter({history: createWebHashHistory(), routes}); export default router;Copy the code
Here are the basic usage, do not repeat, see the documentation.
Modify the App. Vue
<template>
<router-view>
</router-view>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Copy the code
Create views/Home. Vue
<template> <div> <p>This is Home</p> <img alt="Vue logo" src="@/assets/logo.png" /> <HelloWorld msg="Hello Vite + Vue 3 + TypeScript" /> </div> </template> <script lang="ts"> import { defineComponent } from "vue"; import HelloWorld from "@/components/HelloWorld.vue"; export default defineComponent({ name: "Home", components: { HelloWorld }, setup() { return {}; }}); </script>Copy the code
Create views/Login. Vue
<template> <div>This is Login</div> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ name: "Login", setup() { return {}; }}); </script>Copy the code
Main. ts Imports the Vue router
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router/index";
createApp(App).use(router).mount("#app");
Copy the code
At this point, vue Router integration is complete. Project Address
10. Integrated Vuex
Vuex is a state management mode + library developed specifically for vue.js applications. It uses centralized storage to manage the state of all the components of the application, and the corresponding rules to ensure that the state changes in a predictable way, directly installed.
yarn add vuex@next
Copy the code
Create a store folder in SRC. For example, create a user module.
src/store/index.ts
import { createStore } from "vuex";
import getters from "./getters";
import user from "./modules/user";
const modules = { user,};
const store = createStore({ modules, getters,});
export default store;
Copy the code
src/store/modules/user.ts
export default {
namespaced: true,
state: {
userInfo: {
userId:"001",
name: "wzy"
}
},
mutations: {
},
actions: {
}
};
Copy the code
src/store/getters.ts
type state = { user: { userInfo: { name: string; token: string; avatar: string; roles: string[]; }; }}; export default { userInfo: (state: state) => state.user.userInfo };Copy the code
The main ts introduced vuex
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router/index";
import store from "./store/index";
createApp(App)
.use(store)
.use(router)
.mount("#app");
Copy the code
SRC/views/Home. Use vue
<template> <div> <p>This is Home</p> <img alt="Vue logo" src="@/assets/logo.png" /> <HelloWorld msg="Hello Vite + Vue 3 + TypeScript" /> <p>Name: {{ userInfo.name }}</p> </div> </template> <script lang="ts"> import { defineComponent } from "vue"; import { useStore } from "vuex"; import HelloWorld from "@/components/HelloWorld.vue"; export default defineComponent({ name: "Home", components: {HelloWorld}, setup() {// Get typed store const store = useStore(); Const userInfo = store.getters. UserInfo; return { userInfo }; } }) </script>Copy the code
At this point, vuEX integration is complete. Project Address
11. Integration Element3
Element3, a Vue 3.0-based desktop component library for developers, designers, and product managers. The installation
yarn add element3
Copy the code
Element3 is introduced in main.ts
Some components are imported on demand
import { createApp } from "vue"; import App from "./App.vue"; import router from "./router/index"; import store from "./store/index"; // Element3 style file import "Element3 /lib/theme-chalk/index.css"; import { ElIcon, ElButton, ElForm, ElFormItem, ElInput } from "element3"; createApp(App) .use(store) .use(router) .use(ElIcon) .use(ElButton) .use(ElForm) .use(ElFormItem) .use(ElInput) .mount("#app");Copy the code
Modify the SRC/views/Login. Vue
<template> <div class="login_main" @keyup.enter="login"> <! </h3> <el-form ref="form" :model="param" :rules="rules"> <el-form-item prop="name"> <el-input V-model ="param.name" prefix-icon="el-icon-user" placeholder=" account "> </el-input> </el-form-item> <el-form-item prop="password"> <el-input v-model="param.password" prefix-icon="el-icon-lock" Placeholder =" password "show-password autocomplete ></el-input> </el-form-item> <el-button class="w_100" type="primary" </el-button> </el-form> </div> </div> </template> <script lang="ts"> import {defineComponent, ref, reactive } from "vue"; Export default defineComponent({name: "Login", setup() {// form const form = ref(null); Const param = reactive({name: "", password: "",}); // Form validation rule const rules = reactive({name: [{required: true, message: "please input the account ", trigger: "blur"},], password: [{required: true, message: "Please input password ", trigger: "blur"}],}); // Password form type const passInputType = ref("password"); // Change password form type const changeInputType = (val: string) => {passinputType. value = val; }; Const login = () => {form.value.validate((valid: Boolean) => {if (valid) {console.log("login validates!") ); } else { return false; }}); }; return { form, param, rules, passInputType, changeInputType, login, }; }}); </script> <style scoped> .login_main { display: flex; align-items: center; justify-content: center; } .content { width: 500px; } </style>Copy the code
The modified login page is as follows:
At this point, element3 integration is complete. Project Address
12. Integrate Axios + MockJS + sass
1. The integrated axios
An HTTP library is definitely needed for projects involving front-end and back-end interactions, and here we integrate the most commonly used axiOS
yarn add axios
Copy the code
Create an utils folder under SRC to hold our utility methods
Write Request. ts to wrap axios
import axios from "axios"; import { Message } from "element3"; // Create an axios instance const service = axios.create({baseURL: import.meta.env.BASE_URL, timeout: 10000}); / / request interceptor service. Interceptors. Request. Use ((config) = > {return config. }, (error) => { return Promise.reject(error); }); / / response interceptor service. Interceptors. Response. Use ((response: any) = > {const res = response. The data; if (res.header.code ! == 0) { Message.error(res.header.msg || "Error"); return Promise.reject( new Error(res.header.msg || "Error")); } return res; }, (error) => { Message.error("request error"); return Promise.reject(error); }); / encapsulated interface request method * * * * @ param url domain name after the need to supplement the interface address * @ param method interface request way * @ param data d * / request data body type method = | "get" | | "get" "delete" | "DELETE" | "head" | "HEAD" | "options" | "OPTIONS" | "post" | "POST" | "put" | "PUT" | "patch" | "PATCH" | "purge" | "PURGE" | "link" | "LINK" | "unlink" | "UNLINK"; const request = ( url: string, method: Method, data: Record<string, unknown> ) => { return service({ url, method, data, }); }; export default request;Copy the code
Create an API folder under SRC to store all interface request methods
SRC/API create user. Ts write user related interface request
import request from ".. /utils/request"; type Method = | "get" | "GET" | "delete" | "DELETE" | "head" | "HEAD" | "options" | "OPTIONS" | "post" | "POST" | "put" | "PUT" | "patch" | "PATCH" | "purge" | "PURGE" | "link" | "LINK" | "unlink" | "UNLINK"; const curryRequest = ( url: string, method: Method, data? : Record<string, unknown> | any ) => { return request( `/module/user/${url}`, method, data ) }; Export function apiLogin(data: {name: string; password: string; }): PromiseLike<any> { return curryRequest("login", "post", data); }Copy the code
Put the login operation in store/modules/user.ts actions, and improve mutations
import { apiLogin } from "@/api/user"; type userInfo = { userId: string; name: string; }; type state = { userInfo: userInfo; }; type context = { state: Record<string, unknown>; mutations: Record<string, unknown>; actions: Record<string, unknown>; dispatch: any; commit: any; }; type loginData = { name: string; password: string; }; export default { namespaced: true, state: { userInfo: { userId: "", name: "" }, }, mutations: SET_USERINFO(state:state,val:userInfo){state.userInfo = val; }}, actions: {// login({commit}: context, data: LoginData) {return new Promise((resolve) => {apiLogin(data). Then (async (res) => {commit("SET_USERINFO", { userId: res.body.userId, name: res.body.name, }); resolve("success"); })})}}}Copy the code
Update the Login. Vue
<template> <div class="login_main" @keyup.enter="login"> <! </h3> <el-form ref="form" :model="param" :rules="rules"> <el-form-item prop="name"> <el-input V-model ="param.name" prefix-icon="el-icon-user" placeholder=" account "> </el-input> </el-form-item> <el-form-item prop="password"> <el-input v-model="param.password" prefix-icon="el-icon-lock" Placeholder =" password "show-password autocomplete ></el-input> </el-form-item> <el-button class="w_100" type="primary" </el-button> </el-form> </div> </div> </template> <script lang="ts"> import {defineComponent, ref, reactive } from "vue"; import { useStore } from "vuex"; import { useRouter } from "vue-router"; Export default defineComponent({name: "Login", setup() {// sotre instance const store = useStore(); // route instance const router = useRouter(); // form const form = ref(null); Const param = reactive({name: "", password: "",}); // Form validation rule const rules = reactive({name: [{required: true, message: "please input the account ", trigger: "blur"},], password: [{required: true, message: "Please input password ", trigger: "blur"}],}); // Password form type const passInputType = ref("password"); // Change password form type const changeInputType = (val: string) => {passinputType. value = val; }; // const login = () => {form.value.validate((valid: boolean) => { if (valid) { store.dispatch("user/login", param).then(() => { router.push({ name: "Home" }); }); } else { return false; }}); }; return { form, param, rules, passInputType, changeInputType, login, }; } }) </script> <style scoped> .login_main { display: flex; align-items: center; justify-content: center; } .content { width: 500px; } </style>Copy the code
I generally recommend router.push({name: “Home”}) for route jump, because the name defined by each route does not change, but the path may be adjusted. In this way, the problem of modifying the corresponding route operation after the path change is avoided
At this point, the request-related logic is written, but when we build the framework, the background is usually in the initial stage, and the interface is not ready, so mockJS is needed to help us simulate the interface request
2. Integrated mockjs
Install mockjs
Yarn add [email protected]Copy the code
Install vite – plugin – the mock
Yarn add [email protected] - DCopy the code
Modify viet.config. js to introduce mockjs
import { UserConfigExport, ConfigEnv,loadEnv } from "vite"; import vue from "@vitejs/plugin-vue"; import { resolve } from "path"; import { viteMockServe } from "vite-plugin-mock"; export default ({ command, mode }: ConfigEnv): UserConfigExport => { const plugins = [vue()]; const env = loadEnv(mode, process.cwd()); If (mode === "development") {plugins.push(viteMockServe({mockPath: "mock", localEnabled: command === "serve" }) ); } return { resolve: { alias: { "@": resolve("./src") }, }, plugins } };Copy the code
Create the mock folder in the root directory of your project and create user.ts to write the user-related mock interface
export default [ { url: `/module/user/login`, method: "post", response: (req) => { return { header: { code: 0, msg: "OK,"}, body: {userId: "001", name: ` ${the req. Body. The name} xiaoming `}}}}];Copy the code
Open the login page, enter account 1 and password 1, and click Login
The console can see that the request was successfully initiated and the response received, and the page jumps to Home and gets userInfo
3. The integrated sass
Related documents Install sASS
yarn add sass -D
Copy the code
Modify the SRC /views/ login. vue style test
<style lang="scss" scoped>
$bg: #364d81;
.login_main {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: $bg;
.content {
width: 500px;
.title {
color: #fff;
}
}}
</style>
Copy the code
At this point, the sASS integration is complete.
4. Jest unit tests do not support import.meta.env
We thought we were done here, but when we unit tested SRC /utils/request.ts
tests/unit/request.spec.ts
import request from "@/utils/request";
test("request", () => {
expect(request).not.toBeNull();
expect(request).not.toBeUndefined();
});
Copy the code
Jest error found
Here before we tsconfig. Js is configured in the “module” : “esnext”, in fact, the problem is the current ts – no jest library to import. The meta. Do support env, it adopted the following methods
Modify the vite. Config. Js
import { UserConfigExport, ConfigEnv,loadEnv } from "vite"; import vue from "@vitejs/plugin-vue"; import { resolve } from "path"; import { viteMockServe } from "vite-plugin-mock"; export default ({ command, mode }: ConfigEnv): UserConfigExport => { const plugins = [vue()]; const env = loadEnv(mode, process.cwd()); If (mode === "development") {plugins.push(viteMockServe({mockPath: "mock", localEnabled: Command === "serve"}))} const envWithProcessPrefix = object.entries (env).reduce( (prev, [key, val]) => { return { ... Prev, / / environment variable to add process. The env [" process. The env. "+ key] : `" ${val} "`}; }, {}); return { base: "./", resolve: { alias: { "@": resolve("./src"), }, }, plugins, define: envWithProcessPrefix, }};Copy the code
Save the environment-specific variables you get in process.env and expose them externally
Modify the request. Ts
import axios from "axios"; import { Message } from "element3"; // Create an axios instance const service = axios.create({baseURL: process.env.VITE_BASE_URL, timeout: 10000});Copy the code
BaseURL uses variables under process.env
Run yarn test-unit. The test succeeds.
At this point, the integration with Axios + MockJS +sass is complete. Project Address
End
At this point, this article is over, the follow-up will build background management system on this basis, interested in the point of attention!
If you have any questions or suggestions about this article, please leave a comment!