引言
我看了这里好像还没有这方面的,大部分都是TS,如何你还没熟悉TS呢?怎么办。。。。。,还能怎么办,赶紧去把自己卷洗(我内心:卷不动了)。。。。哈哈哈哈😂。
这里面有几个大坑。。。。。稳稳的被我踩了
我们下面做了什么:
使用vite 从零构建vue3的一个项目模版用eslint 做代码规范化用githook 来限制代码,如果不规范,不给commitvite 配置UI库按需自动引入(相关其他的配置)pinia 和 vuex哪个好,以及pinia的使用
接下来,为了让大家更好理解本项目工程化的思路,本文会按照以下关键词去逐步研读(看项目代码可跳过前4步) :
script setup
<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。
搞个简单demo对比script-setup和script区别:
// 单文件组件script-setup编写模式
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
复制代码
// 普通script编写模式
<script>
import { ref } from 'vue'
export default {
setup(props) {
const count = ref(0)
// 暴露给 template
return {
count
}
}
}
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
复制代码
上述例子可以看出,script-setup弱化了vue模板式编程体验,也使得代码更简洁,开发者只需要引入正确的hooks后,把逻辑写在script内就足以。
本项目所有组件都采用这种开发模式,相比于普通的 <script> 语法,vue官方肯定了它的优势:
- 更少的样板内容,更简洁的代码。
- 能够使用纯 Typescript 声明 props 和抛出事件。
- 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
- 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)
最后笔者认为,从某方面讲Vue3是一次vue-hooks的革命,通过compositionApi的引用使组件写法更轻便简洁;而script-setup正好使得这种体验更加彻底,使单文件组件写法更接近函数式编程,在react和vue之间无缝切换。
Vite
Vite是一种新型前端构建工具,能够显著提升前端开发体验。比起webpack,vite还是有它很独特的优势,这里推荐一篇文章《Vite 的好与坏》给大家参考下。
项目为什么选vite代替webpack,结合社区和个人考虑,有几点:(具体就不展开,推文已经分析的很细致了)
- Vite更加轻量,并且构建速度足够快
webpack是使用nodejs去实现,而viite使用 esbuild 预构建依赖。Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快不是一个数量级。 - Vue官方出品,对vue项目兼容性不错
- 发展势头迅猛,未来可期
当然事物都有两面性的,至目前为止,vite也有不少缺陷,例如:生态没有webpack成熟、生产环境下隐藏的不稳定因素等都是它如今要面临的问题。
但是,心怀梦想敢于向前,没有新势力的诞生,哪里来的技术发展?相比之下,vite更像一个青年,并逐步前行。
Pinia
Pinia 是 Vue.js 的轻量级状态管理库,最近很受欢迎。它使用 Vue 3 中的新反应系统来构建一个直观且完全类型化的状态管理库。
比起Vuex,Pinia具备以下优点:
- 完整的 TypeScript 支持:与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
- 极其轻巧(体积约 1KB)
- store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction 辅助函数,这在 Vuex 中很常见
- 支持多个Store
- 支持 Vue devtools、SSR 和 webpack 代码拆分 关于Pinia的进阶使用,笔者额外开了一篇专文介绍,有兴趣可以阅览:《Pinia进阶:优雅的setup(函数式)写法+封装到你的企业项目》\
工程化搭建
言归正传,我们通过以上技术,整合到一个项目中去。一般用于企业级生产的项目,要具备以下能力:
- 容错性、可拓展性强
- 组件高内聚,减少模块之间耦合度
- 清晰的项目执行总线,方便增加插槽逻辑
- 高度抽象的全局方法
- 资源压缩+性能优化等
对照这些指标,我们来逐步搭建一个初步的工程框架。
备注:关于vue3语法、pinia使用等编程知识不会在这里细述了,大家可以到网上检索或者直接在项目里面寻找。
1. 技术栈
编程: Vue3.x + Jypescript
构建工具:Vite
路由 | 状态管理:vue-router + Pinia
UI Vant:vant
2. 工程结构
其中,src/utils里面放置全局方法,供整个工程范围的文件调用,当然工程初始化的事件总线也放在这里「下面会细述」。src/types和src/constants分别存放项目的类型定义和常量,以页面结构来划分目录。
3. 工程配置
搭建Vite + Vue项目
#npm 6.x
npm init vite@latest my-vue-app --template vue
#npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue
#yarn
yarn create vite my-vue-app --template vue
#pnpm
pnpm create vite my-vue-app -- --template vue
4. 代码规范 配置
npm i eslint eslint-plugin-vue -D
- package.json
"scripts":{
"lint:create": "eslint --init",
"lint": "eslint src/**/*.{js,vue} --fix ",
}
-
npm run lint:create -
按照提示。
注意事项
1、在项目根目录会生成.eslintrc.cjs文件.
2、npm run lint会报错,因为vite 生成的 的package.json 文件里面type=module,这样js文件的模式是es模式。解决如下:把.eslintrc.js改成.eslintrc.cjs
5.限制开发者代码规范,才可以commit code
你团队的成员就是把不规范的代码都提交了,你是想锤他了,你out shitp 了 🐻 der,我们可以限制必须规范代码才可以commit
1、npm i lint-staged -D
2、在package.json 文件里面加
"lint-staged": {
"*.{js,jsx,vue}": [
"npm run lint",
"git add"
]
}
"gitHooks": {
"pre-commit": "lint-staged"
},
6. 配置vite.config.js
1、安装文件path 对象 ,用来重写src 别名。 在es 里面用的是 path-browserify
npm i path-browserify -D
2、安装 自动按需加载插件unplugin-vue-components
npm i unplugin-vue-components -D
3、vite 文件配置如下:(可以根据需要不同的UI框架来使用)
import { defineConfig } from 'vite';
import path from 'path-browserify'; //vite 写法 esm 模式
import vue from '@vitejs/plugin-vue';
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [VantResolver()], // 按需加载vant 组件
}),,
],
base: './',
// // 静态资源服务的文件夹,默认public
publicDir: 'public',
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
},
},
css: {
// 引入 autoprefixer
postcss: {
plugins: [
// require('autoprefixer')
]
},
// 引入全局 scss
preprocessorOptions: {
scss: {
additionalData: "@import './src/assets/styles/common.scss';"
}
}
},
server: {
// 服务器主机名,如果允许外部访问,可设置为"0.0.0.0"
host: '192.168.1.0',
port: 8000, // 服务器端口号
open: false, // 是否自动打开浏览器
// 代理
proxy: {
'/api': {
target: 'http://xxx.xxx.xx',
changeOrigin: false
}
}
}
});
4、使用组件
完成以上两步,就可以直接在模板中使用 Vant 组件了,unplugin-vue-components 会解析模板并自动注册对应的组件。
<template>
<van-button type="primary" />
</template>
5、 引入函数组件的样式
Vant 中有个别组件是以函数的形式提供的,包括 Toast,Dialog,Notify 和 ImagePreview 组件。在使用函数组件时,unplugin-vue-components 无法自动引入对应的样式,因此需要手动引入样式。
import { Toast } from 'vant';
import 'vant/es/toast/style';
// Dialog
import { Dialog } from 'vant';
import 'vant/es/dialog/style';
// Notify
import { Notify } from 'vant';
import 'vant/es/notify/style';
// ImagePreview
import { ImagePreview } from 'vant';
import 'vant/es/image-preview/style';
7.批量导入路由文件
1、需求我们经常需要批量导入一些文件,做动态批量导入资源
2、vue2 之前就是用了webpack 的require.content来处理
在vite中批量导入 import { createRouter, createWebHashHistory } from 'vue-router' let metaRouters = import.meta.glob('../pages/*/route.js', { eager: true })
import { createRouter, createWebHashHistory } from 'vue-router'
let metaRouters = import.meta.glob('../pages/*/route.js', { eager: true })
let allrouter = []
Object.keys(metaRouters).forEach( item => {
metaRouters[item].default.forEach(item => {
allrouter.push(item)
})
})
const Router = createRouter({
history: createWebHashHistory(),
routes: allrouter,
})
export default Router
注意import.meta.glob('../pages/*/route.js', { eager: true })如果没设置eager: true就是异步导入,这样没拿到就无法生成路由,配置就是同步一次性导入,类似require.content
结束语:前端技术真他么多。。。。。。。。。。。。。,躺平了