发布时间:2024-06-01 19:01
2021第一更是尤大的Vite2
,全新插件架构,丝滑的开发体验,和Vue3
的完美结合。 2021年第一弹,村长将以Vite2+Vue3为主题开启大家的前端学习之旅。
“我自己是一名从事了6年web前端开发的老程序员(我的微信:webxxq),今年年初我花了一个月整理了一份最适合2021年自学的web前端全套培训教程(视频+源码+笔记+项目实战),从最基础的HTML+CSS+JS到移动端HTML5以及各种框架和新技术都有整理,打包给每一位前端小伙伴,这里是前端学习者聚集地,欢迎初学和进阶中的小伙伴(所有前端教程关注我的微信公众号:web前端学习圈,关注后回复“web”即可领取)。
vue3+vite2项目中常见任务实践:
闲言碎语不必说,下面我们表一表好汉vite2
使用npm:
$ npm init @vitejs/app
复制代码
按提示指定项目名称和模板,或直接指定
$ npm init @vitejs/app my-vue-app --template vue 复制代码
vue特有选项
、创建选项、css选项、jsx选项等、别名行为变化:不再要求/开头或结尾Vue支持
Vue的整合也通过插件实现,和其他框架一视同仁:
SFC定义默认使用setup script
,语法比较激进,但更简洁,好评!
别名定义
不再需要像vite1
一样在别名前后加上/
,这和webpack
项目配置可以保持一致便于移植,好评!
import path from \'path\'
export default {
alias: {
\"@\": path.resolve(__dirname, \"src\"),
\"comps\": path.resolve(__dirname, \"src/components\"),
},
}
复制代码
App.vue
里面用一下试试
复制代码
插件API重新设计
Vite2
主要变化在插件体系,这样更标准化、易扩展。Vite2
插件API扩展自Rollup
插件体系,因此能兼容现存的Rollup
插件,编写的Vite插件也可以同时运行于开发和创建,好评!
插件编写我会另开专题讨论,欢迎大家关注我。
Vue3 Jsx支持
vue3
中jsx
支持需要引入插件:@vitejs/plugin-vue-jsx
$ npm i @vitejs/plugin-vue-jsx -D
复制代码
注册插件,vite.config.js
import vueJsx from \"@vitejs/plugin-vue-jsx\";
export default {
plugins: [vue(), vueJsx()],
}
复制代码
用法也有要求,改造一下App.vue
复制代码
Mock插件应用
之前给大家介绍的vite-plugin-mock已经重构支持了Vite2。
安装插件
npm i mockjs -S
复制代码
npm i vite-plugin-mock cross-env -D
复制代码
配置,vite.config.js
import { viteMockServe } from \'vite-plugin-mock\'
export default {
plugins: [ viteMockServe({ supportTs: false }) ]
}
复制代码
设置环境变量,package.json
{
\"scripts\": {
\"dev\": \"cross-env NODE_ENV=development vite\",
\"build\": \"vite build\"
},
}
基础配置、样式处理、lint、测试、打包发布等参见我上一篇文章:vite工程化实践
路由
安装vue-router 4.x
npm i vue-router@next -S
复制代码
路由配置,router/index.js
import { createRouter, createWebHashHistory } from \'vue-router\';
const router = createRouter({
history: createWebHashHistory(),
routes: [
{ path: \'/\', component: () => import(\'views/home.vue\') }
]
});
export default router
复制代码
引入,main.js
import router from \"@/router\";
createApp(App).use(router).mount(\"#app\");
复制代码
别忘了创建
home.vue
并修改App.vue
路由用法略有变化,村长的视频教程
状态管理
安装vuex 4.x
npm i vuex@next -S
复制代码
Store配置,store/index.js
import {createStore} from \'vuex\';
export default createStore({
state: {
couter: 0
}
});
复制代码
引入,main.js
import store from \"@/store\";
createApp(App).use(store).mount(\"#app\");
复制代码
用法和以前基本一样,村长的视频教程
样式组织
安装sass
npm i sass -D
复制代码
styles
目录保存各种样式
index.scss
作为出口组织这些样式,同时编写一些全局样式
最后在main.js
导入
import \"styles/index.scss\";
复制代码
注意在
vite.config.js
添加styles
别名
UI库
就用我们花果山团队自家的element3。
中文文档
安装
npm i element3 -S
复制代码
完整引入,main.js
import element3 from \"element3\";
import \"element3/lib/theme-chalk/index.css\";
createApp(App).use(element3)
复制代码
按需引入,main.js
import \"element3/lib/theme-chalk/button.css\";
import { ElButton } from \"element3\"
createApp(App).use(ElButton)
复制代码
抽取成插件会更好,plugins/element3.js
// 完整引入
import element3 from \"element3\";
import \"element3/lib/theme-chalk/index.css\";
// 按需引入
// import { ElButton } from \"element3\";
// import \"element3/lib/theme-chalk/button.css\";
export default function (app) {
// 完整引入
app.use(element3)
// 按需引入
// app.use(ElButton);
}
测试
my button
复制代码
基础布局
我们应用需要一个基本布局页,类似下图,将来每个页面以布局页为父页面即可:
布局页面,layout/index.vue
复制代码
别忘了创建
AppMain.vue
和Navbar.vue
路由配置,router/index.js
{
path: \"/\",
component: Layout,
children: [
{
path: \"\",
component: () => import(\'views/home.vue\'),
name: \"Home\",
meta: { title: \"首页\", icon: \"el-icon-s-home\" },
},
],
},
复制代码
动态导航
侧边导航
根据路由表动态生成侧边导航菜单。
首先创建侧边栏组件,递归输出routes
中的配置为多级菜单,layout/Sidebar/index.vue
复制代码
注意:
sass
文件导出变量解析需要用到css module
,因此variables
文件要加上module
中缀。
添加相关样式:
styles/variables.module.scss
styles/sidebar.scss
styles/index.scss
中引入创建SidebarItem.vue
组件,解析当前路由是导航链接还是父菜单:
面包屑
通过路由匹配数组可以动态生成面包屑。
面包屑组件,layouts/components/Breadcrumb.vue
{{ item.meta.title }}
{{ item.meta.title }}
复制代码
别忘了添加依赖:
path-to-regexp
注意:
vue-router4
已经不再使用path-to-regexp
解析动态path
,因此这里后续还需要改进。
数据封装
统一封装数据请求服务,有利于解决一下问题:
准备工作:
安装axios
:
npm i axios -S
复制代码
添加配置文件:.env.development
VITE_BASE_API=/api
复制代码
请求封装,utils/request.js
import axios from \"axios\";
import { Message, Msgbox } from \"element3\";
// 创建axios实例
const service = axios.create({
// 在请求地址前面加上baseURL
baseURL: import.meta.env.VITE_BASE_API,
// 当发送跨域请求时携带cookie
// withCredentials: true,
timeout: 5000,
});
// 请求拦截
service.interceptors.request.use(
(config) => {
// 模拟指定请求令牌
config.headers[\"X-Token\"] = \"my token\";
return config;
},
(error) => {
// 请求错误的统一处理
console.log(error); // for debug
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
/**
* 通过判断状态码统一处理响应,根据情况修改
* 同时也可以通过HTTP状态码判断请求结果
*/
(response) => {
const res = response.data;
// 如果状态码不是20000则认为有错误
if (res.code !== 20000) {
Message.error({
message: res.message || \"Error\",
duration: 5 * 1000,
});
// 50008: 非法令牌; 50012: 其他客户端已登入; 50014: 令牌过期;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// 重新登录
Msgbox.confirm(\"您已登出, 请重新登录\", \"确认\", {
confirmButtonText: \"重新登录\",
cancelButtonText: \"取消\",
type: \"warning\",
}).then(() => {
store.dispatch(\"user/resetToken\").then(() => {
location.reload();
});
});
}
return Promise.reject(new Error(res.message || \"Error\"));
} else {
return res;
}
},
(error) => {
console.log(\"err\" + error); // for debug
Message({
message: error.message,
type: \"error\",
duration: 5 * 1000,
});
return Promise.reject(error);
}
);
export default service;
复制代码
结构化数据展示
使用el-table
展示结构化数据,配合el-pagination
做数据分页。
文件组织结构如下:list.vue
展示列表,edit.vue
和create.vue
编辑或创建,内部复用detail.vue
处理,model
中负责数据业务处理。
list.vue
中的数据展示
复制代码
list
和loading
数据的获取逻辑,可以使用compsition-api
提取到userModel.js
export function useList() {
// 列表数据
const state = reactive({
loading: true, // 加载状态
list: [], // 列表数据
});
// 获取列表
function getList() {
state.loading = true;
return request({
url: \"/getUsers\",
method: \"get\",
}).then(({ data, total }) => {
// 设置列表数据
state.list = data;
}).finally(() => {
state.loading = false;
});
}
// 首次获取数据
getList();
return { state, getList };
}
复制代码
list.vue
中使用
import { useList } from \"./model/userModel\";
复制代码
const { state, getList } = useList();
复制代码
分页处理,list.vue
复制代码
数据也在userModel
中处理
const state = reactive({
total: 0, // 总条数
listQuery: {// 分页查询参数
page: 1, // 当前页码
limit: 5, // 每页条数
},
});
复制代码
request({
url: \"/getUsers\",
method: \"get\",
params: state.listQuery, // 在查询中加入分页参数
})
表单处理
用户数据新增、编辑使用el-form
处理
可用一个组件detail.vue
来处理,区别仅在于初始化时是否获取信息回填到表单。
提交
复制代码
数据处理同样可以提取到userModel
中处理。
export function useItem(isEdit, id) {
const model = ref(Object.assign({}, defaultData));
// 初始化时,根据isEdit判定是否需要获取详情
onMounted(() => {
if (isEdit && id) {
// 获取详情
request({
url: \"/getUser\",
method: \"get\",
params: { id },
}).then(({ data }) => {
model.value = data;
});
}
});
return { model };
}
复制代码
本文配套演示视频,喜欢看视频的小伙伴看这里: 「备战2021」Vite2 + Vue3项目最佳实践
本文相关源码点这里