Vite2 come
Vite1 is not available yet, Vite2 has been updated with a new plugin architecture, a silky development experience, and a perfect combination of Vue3. In the first round of 2021, the village head plans to open the front end learning journey with Vite2+Vue3 as the theme.
2021 learn vite first
In this paper, the target
vite2
Change analysis- Common tasks in a project
vite2+vue3
practice
Create the Vite2 project
Gossip needless to say, below we table a table of heroes Vite2
Use NPM:
$ npm init @vitejs/app
Copy the code
Specify the project name and template as prompted, or directly
$ npm init @vitejs/app my-vue-app --template vue Copy the code
Vite2 major changes
I have marked the ones that had a big impact on our previous projects:
- Configuration options change:
Vue-specific options
, Create options, CSS options, JSX options, etc Alias behavior change
: No longer required/
Beginning or endingVue support
Through:@vitejs/plugin-vuePlug-in support- The React to support
- HMR API changes
- List format changes
Plug-in API redesign
Vue support
Vue integration is also implemented through plug-ins, just like any other framework:
SFC definitions use setup script by default.
The alias definition
No longer need to add/before and after aliases like vite1, this and Webpack project configuration can be consistent for portability.
import path from 'path'
export default {
alias: {
"@": path.resolve(__dirname, "src"),
"comps": path.resolve(__dirname, "src/components"),}}Copy the code
Try it in app.vue
<script setup>
import HelloWorld from 'comps/HelloWorld.vue'
</script>
Copy the code
Plug-in API redesign
The main change in Vite2 is the plugin architecture, which is more standardized and extensible. The Vite2 plugin API extends from the Rollup plugin architecture, so it is compatible with existing Rollup plugins. The Vite plugin can also be developed and created at the same time.
I will have a separate panel discussion on plug-in writing, welcome to follow me.
Vue3 Jsx support
Vue3 JSX support requires the introduction of plugins: @vitejs/ plugin-vuE-jsx
$ npm i @vitejs/plugin-vue-jsx -D
Copy the code
Register the plugin, vite.config.js
import vueJsx from "@vitejs/plugin-vue-jsx";
export default {
plugins: [vue(), vueJsx()],
}
Copy the code
Usage also has requirements, revamp app.vue
<! -- 1. mark JSX --> <script setup lang=" JSX "> import {defineComponent} from "vue"; import HelloWorld from "comps/HelloWorld.vue"; import logo from "./assets/logo.png" // 2. Define components with defineComponent and export Default defineComponent({render: () => ( <> <img alt="Vue logo" src={logo} /> <HelloWorld msg="Hello Vue 3 + Vite" /> </> ), }); </script>Copy the code
Mock plug-in application
Vite2 has been refactored from vite-plugin-Mock.
Installing a plug-in
npm i mockjs -S
Copy the code
npm i vite-plugin-mock cross-env -D
Copy the code
The configuration, vite. Config. Js
import { viteMockServe } from 'vite-plugin-mock'
export default {
plugins: [ viteMockServe({ supportTs: false}})]Copy the code
Set the environment variable, package.json
{
"scripts": {
"dev": "cross-env NODE_ENV=development vite"."build": "vite build"}},Copy the code
Project Infrastructure
routing
Install the vue – the router 4. X
npm i vue-router@next -S
Copy the code
Route configuration, router/index.js
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory(),
routes: [{path: '/'.component: () = > import('views/home.vue')}});export default router
Copy the code
Introduction, main. Js
import router from "@/router";
createApp(App).use(router).mount("#app");
Copy the code
Don’t forget to create home.vue and modify app.vue
Routing usage changes slightly in video tutorials
State management
Install vuex 4. X
npm i vuex@next -S
Copy the code
Store configuration, Store /index.js
import {createStore} from 'vuex';
export const store = createStore({
state: {
couter: 0}});Copy the code
Introduction, main. Js
import store from "@/store";
createApp(App).use(store).mount("#app");
Copy the code
Usage is basically the same as before, video tutorial
Style organization
Install the sass
npm i sass -D
Copy the code
The styles directory holds various styles
Index.scss organizes these styles as an exit, while writing some global styles
Finally import in main.js
import "styles/index.scss";
Copy the code
Note that the styles alias is added in viet.config. js
UI library
Use our own element3 from the flower hill team.
Chinese document
The installation
npm i element3 -S
Copy the code
Full introduction, main.js
import element3 from "element3";
import "element3/lib/theme-chalk/index.css";
createApp(App).use(element3)
Copy the code
Import main.js on demand
import "element3/lib/theme-chalk/button.css";
import { ElButton } from "element3"
createApp(App).use(ElButton)
Copy the code
Better to extract as plugins, plugins/element3.js
// complete introduction
import element3 from "element3";
import "element3/lib/theme-chalk/index.css";
// Import on demand
// import { ElButton } from "element3";
// import "element3/lib/theme-chalk/button.css";
export default function (app) {
// complete introduction
app.use(element3)
// Import on demand
// app.use(ElButton);
}
Copy the code
test
<el-button>my button</el-button>
Copy the code
Basic layout
We need a basic layout page for our application, similar to the following, and each page will be parent page:
Layout page, Layout /index.vue
<template> <div class="app-wrapper"> <! - the sidebar - > < div class = "sidebar - container" > < / div > <! Content container --> <div class="main-container"> <! -- Top navigation bar --> <navbar /> <! < AppMain /> </div> </div> </template> <script setup> import AppMain from "./ Components/appmain.vue "; import Navbar from "./components/Navbar.vue"; </script> <style lang="scss" scoped> @import ".. /styles/mixin.scss"; .app-wrapper { @include clearfix; position: relative; height: 100%; width: 100%; } </style>Copy the code
Don’t forget to create appmain. vue and navbar. vue
Route configuration, router/index.js
{
path: "/".component: Layout,
children: [{path: "".component: () = > import('views/home.vue'),
name: "Home".meta: { title: "Home page".icon: "el-icon-s-home"}},],},Copy the code
Dynamic navigation
The side navigation
Dynamically generate side navigation menus from routing tables.
First create a Sidebar component. The configuration in the recursive output routes is a multi-level menu, Layout /Sidebar/index.vue
<template>
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="false"
:active-text-color="variables.menuActiveText"
mode="vertical"
>
<sidebar-item
v-for="route in routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</el-scrollbar>
</template>
<script setup>
import SidebarItem from "./SidebarItem.vue";
import { computed } from "vue";
import { useRoute } from "vue-router";
import { routes } from "@/router";
import variables from "styles/variables.module.scss";
const activeMenu = computed(() => {
const route = useRoute();
const { meta, path } = route;
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
});
</script>
Copy the code
Note: The sass file export variable resolution requires CSS Module, so the variables file should have a module infix.
Add related styles:
styles/variables.module.scss
styles/sidebar.scss
styles/index.scss
The introduction of
Create sideBarItem. vue component to resolve whether the current route is a navigation link or a parent menu:
Bread crumbs
Breadcrumbs can be dynamically generated by routing the match array.
Bread crumbs components, layouts/components/Breadcrumb. Vue
<template> <el-breadcrumb class="app-breadcrumb" separator="/"> <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path"> <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect" >{{ item.meta.title }}</span> <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> </el-breadcrumb-item> </el-breadcrumb> </template> <script setup> import { compile } from "path-to-regexp"; import { reactive, ref, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; const levelList = ref(null); const router = useRouter(); const route = useRoute(); const getBreadcrumb = () => { let matched = route.matched.filter((item) => item.meta && item.meta.title); const first = matched[0]; if (first.path ! = = = "/") {matched [{path: "/ home", meta: {title: "home page"}}]. Concat (matched); } levelList.value = matched.filter( (item) => item.meta && item.meta.title && item.meta.breadcrumb ! == false ); } const pathCompile = (path) => { var toPath = compile(path); return toPath(route.params); } const handleLink = (item) => { const { redirect, path } = item; if (redirect) { router.push(redirect); return; } router.push(pathCompile(path)); } getBreadcrumb(); watch(route, getBreadcrumb) </script> <style lang="scss" scoped> .app-breadcrumb.el-breadcrumb { display: inline-block; font-size: 14px; line-height: 50px; margin-left: 8px; .no-redirect { color: #97a8be; cursor: text; } } </style>Copy the code
Don’t forget to add dependencies: path-to-regexp
Note: Vue-Router4 no longer uses path-to-regexp to resolve dynamic paths, so this needs to be improved.
Data encapsulation
Unified encapsulation of data request services helps to solve the following problems:
- Unified configuration request
- Requests and responses are processed in a unified manner
Preparations:
-
Install axios:
npm i axios -S Copy the code
-
Add the configuration file:.env.development
VITE_BASE_API=/api Copy the code
Request encapsulation, utils/request.js
import axios from "axios";
import { Message, Msgbox } from "element3";
// Create an axios instance
const service = axios.create({
// Prefix the request address with baseURL
baseURL: import.meta.env.VITE_BASE_API,
// Cookies are carried when sending a cross-domain request
// withCredentials: true,
timeout: 5000});// Request interception
service.interceptors.request.use(
(config) = > {
// Emulated the specified request token
config.headers["X-Token"] = "my token";
return config;
},
(error) = > {
// Unified handling of request errors
console.log(error); // for debug
return Promise.reject(error); });// Response interceptor
service.interceptors.response.use(
/** * The response can be processed by the status code, which can be modified according to the situation
(response) = > {
const res = response.data;
// If the status code is not 20000, an error is considered
if(res.code ! = =20000) {
Message.error({
message: res.message || "Error".duration: 5 * 1000});// 50008: invalid token; 50012: Other clients are logged in; 50014: Token expired;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// Log in again
Msgbox.confirm("You have logged out. Please log in again."."Confirm", {
confirmButtonText: "Log in again".cancelButtonText: "Cancel".type: "warning",
}).then(() = > {
store.dispatch("user/resetToken").then(() = > {
location.reload();
});
});
}
return Promise.reject(new Error(res.message || "Error"));
} else {
returnres; }},(error) = > {
console.log("err" + error); // for debug
Message({
message: error.message,
type: "error".duration: 5 * 1000});return Promise.reject(error); });export default service;
Copy the code
The business process
Structured data presentation
El-table was used to display structured data, and el-Pagination was used for data pagination.
The file structure is as follows: list.vue displays the list, edit.vue and create.vue edit or create, internally reuse detail.vue processing, model is responsible for data business processing.
Data display in list.vue
<el-table v-loading="loading" :data="list"> <el-table-column label="ID" prop="id"></el-table-column> <el-table-column </el-table-column> <el-table-column label=" age" prop="age"></el-table-column> </el-table>Copy the code
The acquisition logic of list and loading data can be extracted from userModel.js using compsition-API
export function useList() {
// List data
const state = reactive({
loading: true.// Load status
list: [].// List data
});
// Get the list
function getList() {
state.loading = true;
return request({
url: "/getUsers".method: "get",
}).then(({ data, total }) = > {
// Set the list data
state.list = data;
}).finally(() = > {
state.loading = false;
});
}
// Obtain data for the first time
getList();
return { state, getList };
}
Copy the code
Used in the list. The vue
import { useList } from "./model/userModel";
Copy the code
const { state, getList } = useList();
Copy the code
Paging, list.vue
<pagination
:total="total"
v-model:page="listQuery.page"
v-model:limit="listQuery.limit"
@pagination="getList"
></pagination>
Copy the code
The data is also processed in the userModel
const state = reactive({
total: 0./ / the total number of article
listQuery: {// paging query parameters
page: 1.// Current page number
limit: 5.// Number of entries per page}});Copy the code
request({
url: "/getUsers".method: "get".params: state.listQuery, // Add paging parameters to the query
})
Copy the code
Form processing
User data is added and edited using El-Form
This can be handled by a component detail.vue, the only difference being whether information is retrieved and backfilled into the form at initialization.
<el-form ref="form" :model="model" :rules="rules">
<el-form-item prop="name" label="Username">
<el-input v-model="model.name"></el-input>
</el-form-item>
<el-form-item prop="age" label="User age">
<el-input v-model.number="model.age"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="submitForm" type="primary">submit</el-button>
</el-form-item>
</el-form>
Copy the code
Data processing can also be extracted into userModel for processing.
export function useItem(isEdit, id) {
const model = ref(Object.assign({}, defaultData));
// During initialization, isEdit determines whether the details need to be retrieved
onMounted(() = > {
if (isEdit && id) {
// Get details
request({
url: "/getUser".method: "get".params: { id },
}).then(({ data }) = >{ model.value = data; }); }});return { model };
}
Copy the code
Supporting video demonstration
I have specially recorded a set of video to demonstrate all the operations in this article. If you like to watch the video, you can follow the following steps: “Prepare for 2021” Vite2 + Vue3 project best practices
Production is not easy, for a 3, not too much attention! ?
Accompanying source code handout
Welcome to pay attention to the public number “village head learning front”
Follow-up Creation Plan
The most important update to Vite2 is the plugin system, which I plan to make later, including but not limited to the following:
- Vite2 working mechanism analysis
- Vite2 plug-in mechanism analysis
- Vite2 plug-in to write actual combat
Let’s give it a thumbs up and bookmark it for future study.
Support the village chief
So much for the vitE2 project practice, this article has been tortured for a long time, stepped on a lot of pits, lost a few hair, friends point a thumbs up 👍 to encourage, ok?
My recent article (thanks for your encouragement and support 🌹🌹🌹) :
- 🔥 Prepare for 2021: Vite engineering practice, suggested collection 857 likes
- 🔥 Another night, this composition-API still feel short 217 upvotes
- 🔥 to win vue3 you need to be prepared for this 76 likes
- 🔥 Lightning five whip: Deep analysis of Composition API Principle 54 thumbs