路由动画的封装
Vue 路由过渡动画是对 Vue 程序一种快速简便的增加个性化效果的的方法。
可以让你在程序的不同页面之间增加平滑的动画和过渡。
如果使用得当,可以使你的程序显得更加专业,从而增强用户体验。
页面切换的动画时间的同时,下一个页面初始化也在进行了,对用户体验来说,可以有效避免下一个页面的加载dom,初始化页面的时间。
封装思路
- 使用transition方式给根路由设置全局动画
- 给router的路径设置meta的level层级
- 在入口页面的setup 中,在路由守卫中,根据level的大小,设置相应的动画
- 定义相应的动画类样式
代码
css写出动画效果
根组件 App.vue,监听路由的变化
如果to索引大于from索引,使用前进的动画,反之使用后退的动画
level 可以使用数字,也可以字母,也可以数字加字母,能体现大小关系即可
export default { setup() { const router = useRouter() //默认值 const state = reactive({ transitionName: 'slide-left' }) router.beforeEach((to, from) => { if (to.meta.level > from.meta.level) { state.transitionName = 'slide-left'// 向左滑动 } else if (to.meta.level < from.meta.level) { // 由次级到主级 state.transitionName = 'slide-right'// 向右滑动 } else { state.transitionName = ''// 同级无过渡效果 } }) return { ...toRefs(state) } } }
效果展示
对比不加动画的,效果还是非常好的
修改动画样式
一个项目里使用的肯定是一个动画,目前我在项目中默认使用的左滑,右滑。
可以根据业务需要,和自己的喜好,去使用更多的动画效果。
可参考大佬写的过渡效果,有兴趣可以再研究研究
axios 二次封装
封装目的
- 降低心智负担
- 减少冗余代码
- 使用更加高效
封装效果
下图是封装前后的使用代码对比
我们在业务调用中,省略了showLoading这个过程,不关心业务code和msg,可以直接获取data进行处理,省略了显示错误信息的过程,所以代码量大大减小。
- 封装后
- 封装前
通用能力
这里说明一下我封装时候的思路和想法
首先列一下我想要这个通用请求能达到什么样的效果
1.正常请求基础的配置,比如超时配置,baseUrl,跨域携带cookie等等
2.响应拦截处理
- 请求成功,业务状态码成功,直接解析接口中的data,不用一层一层再去取code,判断,拿结果
- 请求成功,业务状态码不成功,可以选择自己处理特殊状态码,也可以选择全局 message 提示服务端的报错,业务开发中,大部分都是直接提示服务端报错,但是也有需要前端处理状态码的逻辑
- 请求失败,全局messagege 提示报错
- 统一的特殊请求码处理,或者状态码做特殊逻辑,比如丢失登陆态,请求参数有误等等
3.全局统一的loading配置
- 默认开启,可配置关闭
- 统一管理,业务中不用再去关心这个逻辑
代码实现
基础类型
config 是传入参数
baseURL
是请求地址timeOut
是请求超时时间slientError
是我自定义的值,拿到的结果非成功的请求时,这个参数控制,要不要直接message 服务端返回的错误,一般都是直接返回,所以默认值时falseloading
是我自定义的值,用来控制,调用接口是需不需要展示loading,业务开发中大部分都需要展示loading提示用户,防止用户多次点击,少部分场景不想让用户感知在调用接口,需要关闭,所以默认值我定义了true
type TAxiosOption = { baseURL: string timeout: number slientError: boolean loading: boolean } const config:TAxiosOption = { baseURL: process.env.VUE_APP_ACTIVITY_SERVER_TARGET, timeout: process.env.VUE_APP_API_TIMEOUT, slientError: false, loading: true } class Request { instance:AxiosInstance constructor(config: TAxiosOption) { this.instance = axios.create(config) this.instance.interceptors.request.use(data=>{ return data }) this.instance.interceptors.response.use(data=>{ return data }) } get<T, U>(url: string, data?: U, config = {}): Promise<T> { return this.instance.get(url, { params: data, ...config }) } post<T, U>(url: string, data?: U, config = {}): Promise<T> { return this.instance.post(url, data, config) } } export default new Request(config)
api 管理
我们在调用的时候,可以在post/get
的第三个参数中,传入自己需要的配置
如果不传全部走默认值
slientError: true
表示业务中自己处理异常,网路库不message异常
需要我们在业务中的catch 中 就可以拿到 接口返回的所有信息,去做相应的处理
loading: true
表示展示loading
import request1 from '@/common/axios/request1' // 查询拉新活动规则 export function queryInviteActivityRule(params) { return request1.post('/kyf-activity-api/activity/queryInviteActivityRule', params, { slientError: true, loading: true }) }
全局统一loading处理
在请求拦截器中 执行addLoading
在响应拦截器中 执行cacelLoaing
保证全局无论多少接口调用,requestNum参数 控制都只有一个loading
目前的shoowLoading 引用的是vant 组件,也可以根据自己业务需要去自定义loading组件
let requestNum = 0 const addLoading = () => { // 增加loading 如果pending请求数量等于1,弹出loading, 防止重复弹出 requestNum++ if (requestNum === 1) showLoading() } const cancelLoading = () => { // 取消loading 如果pending请求数量等于0,关闭loading requestNum-- if (requestNum === 0) hideLoading() }
响应拦截器
拦截器的代码可以直接去看我的源代码
在src/common/axios/request.ts
中
主要就是在响应拦截器中对返回值做了处理,如果成功,直接返回结果,不成功,返回接口全部内容
this.instance.interceptors.response.use( (responseData: MyAxiosResponse) => { const status = responseData.status const res = responseData.data const { data, code } = res const { loading = true } = responseData.config if (loading) cancelLoading() // 如果调用其他中台,此处需要单独对code做转化 if (status === 200 && code === '000001') { return Promise.resolve(data || res || {}) } else { // 此处可以处理其他特殊的业务逻辑 // 比如丢失登陆态,传参数有误等逻辑 if (responseData.config.slientError) { return Promise.reject(res) } showErrorInfo(res.msg) return Promise.reject(res) } }, (error:any) => { const { loading = true } = error.config if (loading) cancelLoading() let errMsg if (error && error.response) { if (error.response.status >= 500 && error.response.status <= 599) { errMsg = '服务器繁忙,请稍后重试' } else if (error.response.status === 404) { errMsg = '服务不存在' } else { errMsg = '网络繁忙,请稍后重试' } } else { errMsg = '( ⊙ o ⊙ )啊!网络不太顺畅哦~' } if (error.config.slientError) { return Promise.reject(error) } else { showErrorInfo(errMsg) } return Promise.reject(errMsg) } )
请求拦截器
请求拦截器中一般注入token,我的代码中暂时没有做处理
less sass的优化处理
背景
我们使用less sass 主要是为了使用他们提供的变量,函数等特性。 如果不进行配置,只在入口文件引入,在各个子页面里是无法直接使用,如果使用,还需要再次引用 这个对使用者非常不友好。
官方方案
对sass 文件 可以在loaderOptions 增加 additionalData选项
但是对于less 文件的处理非常不友好,需要一个个去定义变量,因此我了舍弃官方的less处理方案
module.exports = { css: { loaderOptions: { // 给 sass-loader 传递选项 sass: { // @/ 是 src/ 的别名 // 所以这里假设你有 `src/variables.sass` 这个文件 // 注意:在 sass-loader v8 中,这个选项名是 "prependData" additionalData: `@import "~@/variables.sass"` }, // 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效 // 因为 `scss` 语法在内部也是由 sass-loader 处理的 // 但是在配置 `prependData` 选项的时候 // `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号 // 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置 scss: { additionalData: `@import "~@/variables.scss";` }, // 给 less-loader 传递 Less.js 相关选项 less:{ // http://lesscss.org/usage/#less-options-strict-units `Global Variables` // `primary` is global variables fields name globalVars: { primary: '#fff' } } } } }
单独处理less
安装style-resources-loader
在vue.config.js
新增配置
对如果使用了less,预先引入我们基础less文件
pluginOptions: { 'style-resources-loader': { preProcessor: 'less', patterns: [ path.resolve(__dirname, './src/common/style/base.less')] } }
总结
三个预处理器的全局引入方案,可以参考这个文章
CSS 预编译语言 变量全局引用方式 vue-cli@3.0 stylus/sass/less 使用方法
一般来说,一个项目使用一个css 预处理器,less 或者sass,因为我极其不适应 stylus的无括号缩进模式,所以就里没有说stylus
只要在webpack 引入了就不用再全局再次引入了,但是我始终觉得这种业务代码不应该出现在webpack中,这种方式大大增加了开发者的心智负担,也是现在脚手架设计不合理的地方,希望未来能有更好的解决方案!
至于为什么,在入口文件引入了,不配置的话,还不能使用less,或者sass的。这个深层原因,我猜测和vue的框架设计有关,有兴趣可以深入研究
viewport 适配方案
postcss-px-to-viewport是一款 postcss 插件,用于将单位转化为 vw, 现在很多浏览器对vw的支持都很好,适配首选方案。
PostCSS 配置
下面提供了一份基本的 postcss 配置,可以在此配置的基础上根据项目需求进行修改
// postcss.config.js const path = require('path') module.exports = ({ file }) => { const designWidth = file.includes(path.join('node_modules', 'vant')) ? 375 : 750 return { plugins: { autoprefixer: {}, 'postcss-px-to-viewport': { // 要转化的单位 unitToConvert: 'px', // 视口的宽度 viewportWidth: designWidth, // 保留几位小数 unitPrecision: 3, // 哪些属性需要修改 propList: ['*'], // 预期单位 viewportUnit: 'vw', // 字体单位 fontViewportUnit: 'vw', // 最小转化单位 minPixelValue: 1, // 媒体查询里面的单位要不要转化 mediaQuery: true, // 替换包含vw单位的 replace: true, // 排除转化文件 exclude: [], // 添加横向转化值 landscape: false, // 横向采用的单位 landscapeUnit: 'vw', // 横屏的视口宽度 landscapeWidth: false } } } }
autoprefixer
如果要配置目标浏览器,可使用 package.json 的 browserslist 字段
你只使用无前缀的 CSS 规则即可
对比rem
下面这个是rem 适配方案肯定会有的代码
const deviceWidth = document.documentElement.clientWidth || document.body.clientWidth; document.querySelector('html').style.fontSize = deviceWidth / 7.5 + 'px';
弊端:
- px和rem 需要一个计算比例系数,开发时需要计算,后来又提出 px-to-rem不如直接在代码中写px直观高效。
- rem是相对于html元素字体单位的一个相对单位,从本质上来说,它属于一个字体单位,用字体单位来布局,并不是太合适。
兼容第三方UI库
vant团队的是根据375px的设计稿去做的,理想视口宽度为375px。
如果读取的是vant相关的文件,viewportWidth就设为375,如果是其他的文件,我们就按照我们UI的宽度来设置viewportWidth,即750
目前网上没有找到完全正确的例子,博客错误的demo相互抄袭,我在做代码验证时走了很多弯路,现在下面这行代码肯定是可行的。
// 核心代码就这么一行 const designWidth = file.includes(path.join('node_modules', 'vant')) ? 375 : 750
下面是没有配置之前引入vant 的cell 组件,整个缩小了
配置之后,样式恢复正常
配置多环境变量
命令
package.json 里的scripts 配置build
"build:test": "vue-cli-service build --mode test", "build:online": "vue-cli-service build --mode online
可以根据自己业务情况去实际扩展
环境变量
目录下3个环境变量文件
- .env
- .env.test
- .env.online
分别对应,通用的环境变量,测试环境变量,线上环境变量
获取时,无论什么命令都会优先获取 .env 里的环境变量,再根据不同命令,执行不同的环境变量文件,遇到相同的环境变量会进行覆盖
目前我对主要定义的几个环境变量进行说明
# 是否是线上版本 VUE_APP_ONLINE_ENV=false # 环境 NODE_ENV=development # 请求超时时间 VUE_APP_API_TIMEOUT=30000 # public-path VUE_APP_PUBLIC_PATH=/ # 请求后端地址 VUE_APP_ACTIVITY_SERVER_TARGET = xxx
兼容性处理方案
可选链操作符和空值合并操作符的兼容处理
我们判断嵌套对象属性是否存在时,常常会用到链式操作符 ?. ,是一个非常好用的语法糖
高版本api,需要加babel插件,转化成es5
我们对babel.config.js 进行了单独配置
同理空值合并操作符也是如此
注释里已经很清晰了
module.exports = { presets: ['@vue/cli-plugin-babel/preset'], plugins: [ // 空值合并操作符号 ?? '@babel/plugin-proposal-nullish-coalescing-operator', // 可选链 ?. '@babel/plugin-proposal-optional-chaining', //vant 按需引入 [ 'import', { libraryName: 'vant', libraryDirectory: 'es', style: true }, 'vant' ] ] }
transpileDependencies
默认情况下 babel-loader 会忽略所有 node_modules 中的文件。你可以启用本选项,以避免构建后的代码中出现未转译的第三方依赖。
不过,对所有的依赖都进行转译可能会降低构建速度。如果对构建性能有所顾虑,你可以只转译部分特定的依赖:给本选项传一个数组,列出需要转译的第三方包包名或正则表达式即可。
上面这种方式会影响项目构建速度和部署包大小,不能把module中所有包都放进去
明确哪个包有转义问题,可以用这种方式babel 重新编译
目前已知需要这样的做的库,有一个加解密库CryptoJS当前项目并没有使用
transpileDependencies:['crypto-js']
vConsole.js的兼容处理
vConsole是一个轻量、可拓展、针对手机网页的前端开发者调试面板。
当我们直接inpmort 引入时,在低版本手机上,在安卓5.0手机上直接白屏,这个函数库使用了一些高版本语法,没有进行转义
因为vconsole 存在引用第三包的情况,无法确定范围,因此没有采用 transpileDependencies方案
推荐引入链接方式引入,不推荐直接import
可以直接在入口,根据环境变量,测试环境自动加载一个转义后的js文件
<script> var WEB_ENV = '<%= VUE_APP_ONLINE_ENV %>' // 根据环境变量引入VConsole(判断非生产环境) if (!JSON.parse(WEB_ENV)) { var scriptEl = document.createElement('script') scriptEl.src = '<%= BASE_URL %>vConsole.js' scriptEl.async = true document.head.appendChild(scriptEl) scriptEl.onload = function () { window.vConsole = new VConsole() } } </script>
其他
入口加载动画
没有挂在dom 时,先加载loading动画,也可以加载svg,JSON格式动画,或者骨架屏,持续优化用户体验
<div id="app"> <img class="no-app-img-loading" src="data:image/gif;base64,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" alt=""> </div>
总结
脚手架这个东西,本质是工具,工具应该是拿来即用,应该助力开发,不应该成为学习的负担。
目前前端打包工具webpack,vite等等,框架迭代升级快速,vite 我暂时没有研究,但是webpack 从3到5,三个版本,能明显感受的是,配置在简单化,学习成本在降低,很多业内大量使用的通用配置,已经成为官方的默认配置。可能官方也意识到配置复杂性的这个问题,在慢慢做改进。
但是webpack生态没有跟上,vue-cli 也是基于webpack5 之上封装一层,我在做这个vue-template项目时去查阅webpack的文档,资料不是很多,最佳实践不多,也能理解,这种优秀的实践一般都是公司内部使用,不会往外分享传播。
vue3 +vue-cli4 + webpack5 + 多入口打包 + 自动生成项目模版 + pinia + 数据持久化 + 路由动画 + axios二次封装 + less sass 变量函数处理 +viewport 适配方案等等
这个二次封装的框架,融合了我工作以来的经验和实践,平时学习到的优秀的类库,以及和大家交流中发现的问题和解决方案,还是遗留了很多我暂时找不到解决方案的问题,后续看精力和兴趣,如果愿意的话,都能一一攻克。
目前来说,是能够支持移动端的大多数业务,也希望能够帮助到大家业务开发!
后期规划
- 路由配置history,目前使用history 无法访问二级页面,等待后期研究ngnix
- 统一的格式控制管理,能够适用于webstrom 和 vscode
- 多入口时选择编译单个入口文件
- 整个项目cli化,可以像vue-cli那样,直接一行命令下载下来
- 增量编译,随着项目变大,每次发布把所有项目都打包一遍是不现实的,能否有一个方案只编译有修改部分,这样编译效率大大提高
- common 基础方法库 打包封装
- 使用vite搭建组件库componet
如果屏幕前的你读完了,相信也读了很久,有问题,有疑问的地方,欢迎留言,欢迎去git联系我,我们一起交流!点个赞就更好了。 源代码地址:github.com/Yinzhuo1997…