目录
- 简介
- 脚手架
- 引入axios
- 引入sass
- 引入element-plus
- vite.config.js
- 路由配置
- 全局状态管理
- 完整main.js
- 组合式API之Setup
简介
vue3:双向绑定改为ES6的Proxy;新的API风格,代码逻辑性更强、更易维护;性能提升,渲染更快、内存更少。
vite:新型前端构建工具,基于原生ES模块,极速启动、快速热更新,更优的开发体验。
以npm install和build过程为例, 之前vue2+webpack的项目在devops的编译环节非常耗时,在2-15min之间均有,vue3+vite的项目基本在1min以内。
脚手架
事先准备
nodejs需要大于16.0版本。
建议先卸载旧有nodejs,再安装nvm,通过nvm安装分别用于vue3项目和vue2项目的nodejs高低版本。
- 创建指令:
npm create vue@latest
- 选项:TypeScript、Vue Router、ESLint 、Prettier (按需即可)
- 运行指令:
npm installnpm run dev
引入axios
npm install axios --save
- 配置文件axios-config.js,统一封装请求
/request/axios-config.jsimport axios from "axios"; import router from "@/router"; import qs from "qs";/* http request**请求拦截器**在发送请求之前进行的一系列处理,根据项目要求自行配置**例如:loading*/ axios.interceptors.request.use((config) => {// 请求响应时间config.timeout = 60 * 60 * 1000;config.headers = {token: sessionStorage.getItem("accessToken"),// "Content-Type": "application/json""Content-Type": "application/x-www-form-urlencoded",};return config;},(error) => {// 对请求错误做处理console.log(error); // for debugreturn Promise.reject(error);} );/* response**响应拦截器**允许在数据返回客户端前,修改响应的数据**返回体中数据:response.data,如果需要全部,则 return response 即可*/ axios.interceptors.response.use((response) => response,(error) => {let message = "";// 处理响应错误if (error && error.response) {const errorResponse = error.response.data;if (errorResponse.msg || errorResponse.message) {message = errorResponse.msg || errorResponse.message;if (message.indexOf("无效token") > -1) {sessionStorage.removeItem("accessToken");sessionStorage.removeItem("userinfo");router.push({ path: "/login" });}}}return Promise.reject(error);} );const fetchPost = (url, params) => {return new Promise((resolve, reject) => {axios.post(url, qs.stringify(params)).then((res) => {resolve(res.data.data);},(err) => {reject(err.data);}).catch((err) => {reject(err.data);});}); };const fetchPut = (url, params) => {return new Promise((resolve, reject) => {axios.put(url, qs.stringify(params)).then((res) => {resolve(res.data.data);}).catch((err) => {reject(err.data);});}); };const fetchDel = (url, params) => {return new Promise((resolve, reject) => {axios.delete(url, {params: qs.stringify(params),}).then((res) => {resolve(res.data.data);}).catch((err) => {reject(err.data);});}); }; const fetchGet = (url, params) => {return new Promise((resolve, reject) => {axios.get(url, {params: qs.stringify(params),}).then((res) => {resolve(res.data.data);}).catch((err) => {reject(err.data);});}); };/*** 不带参数的get请求* @param {*} url*/ const fetchGetNoParam = (url) => {return new Promise((resolve, reject) => {axios.get(url).then((res) => {resolve(res.data.data);}).catch((err) => {reject(err.data);});}); };export default {install: (app) => {app.config.globalProperties["$get"] = fetchGet;app.config.globalProperties["$post"] = fetchPost;app.config.globalProperties["$put"] = fetchPut;app.config.globalProperties["$del"] = fetchDel;app.config.globalProperties["$axios"] = axios;}, };
- main.js引入
import Axios from "@/request/axios-config.js"; const app = createApp(App).use(Axios);
- .vue使用
import { getCurrentInstance } from "vue"; const { proxy } = getCurrentInstance();let data=await proxy.$post("url",{});
引入sass
npm install sass --save -dev
npm install sass-loader --save -dev
- .vue使用:
<style scoped lang="scss"></style>
引入element-plus
npm install element-plus --save
- main.js引入
import "element-plus/dist/index.css"; import ElementPlus from "element-plus"; import zhCn from "element-plus/dist/locale/zh-cn.mjs";const app = createApp(App).use(ElementPlus, {locale: zhCn,});
- 使用见官网
vite.config.js
"@"路径配置及代理配置
import { fileURLToPath, URL } from "node:url";import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],resolve: {alias: {"@": fileURLToPath(new URL("./src", import.meta.url)),},},server: {port: 8081,https: false,proxy: {"/check": {// 后台地址target: "http://127.0.0.1:18892",changeOrigin: true,// pathRewrite: {// "^/check": "",// },},},},
});
路由配置
/router/index.js
import { createRouter, createWebHistory } from "vue-router";const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: "/login",name: "login",component: () => import("../views/LoginView.vue"),},{path: "/",name: "home",component: () => import("../views/HomeView.vue"),children: [{path: "/index",name: "index",component: () => import("../views/Index.vue"),},],},],
});router.beforeEach((to, from) => {if (!sessionStorage.getItem("accessToken") && to.name !== "login") {return { path: "/login" };}return true;
});export default router;
main.js引入
import router from "./router";
const app = createApp(App).use(router);
全局状态管理
/store/store.js
import { reactive } from "vue";export const store = reactive({count: 0,func: () => {...},
});
.vue使用
<template> {{ store.count }}</template><script setup>
import { store } from './store.js'store.func();
</script>
完整main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";import "./assets/main.css";import "element-plus/dist/index.css";
import ElementPlus from "element-plus";
import zhCn from "element-plus/dist/locale/zh-cn.mjs";import Axios from "@/request/axios-config.js";const app = createApp(App).use(router).use(ElementPlus, {locale: zhCn,}).use(Axios);app.mount("#app");
组合式API之Setup
一些常用功能示例
<script lang="ts" setup>
import { reactive, ref, getCurrentInstance, computed, onMounted } from "vue";
import { useRouter, useRoute, RouterView } from "vue-router";
const router = useRouter();
const route = useRoute();
const { proxy } = getCurrentInstance();
import { store } from "@/store/store.js";// 计算属性,获取当前路由名称
const current= computed(() => {return route.name;
});// 钩子函数
// 在组件完成初始渲染并创建 DOM 节点后运行
onMounted(() => {init();
});// 响应式变量声明
const showTable = ref(false);
let tableData = reactive([]); // axios请求及store状态管理
const init= () => {tableData = await proxy.$post("/getResultList", {quarter: store.getQuarter(),year: store.getYear(),});showTable.value = true
};// 路由跳转
const goLogin= () => {router.push({ path: "/login" });
};
- ref:可以是 string、number 或 boolean 这样的原始类型,也可以是对象类型;在js中需要通过
.value
,在template不需要;适合于原始类型和浅层级的对象。 - reactive:只能用于对象类型;不需要
.value
;适合于层级比较深的可变复杂对象。