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
npm install
npm run dev
npm install axios --save
import 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 debug
return 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;
},
};
import Axios from "@/request/axios-config.js";
const app = createApp(App)
.use(Axios);
import { getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
let data=await proxy.$post("url",{});
npm install sass --save -dev
npm install sass-loader --save -dev
npm install element-plus --save
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,
});
"@"路径配置及代理配置
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>
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");
一些常用功能示例
<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" });
};
.value
,在template不需要;适合于原始类型和浅层级的对象。 .value
;适合于层级比较深的可变复杂对象。