这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
项目介绍
最近两个月完完整整的完成了一个公司大屏展示的项目,从中收获到了许多经验。项目主要涉及到了以下方面:用户中心接入与鉴权、持久化存储、响应式设计、组件化思想与微应用等。
遇到的问题
- 页面权限判断(权限树的持久化存储,
vuex
刷新后状态丢失,需要辅助使用localstorage
) - 打开新标签自动跳转到了登录页(判断了
token
,但是使用了sessionstorage
) - 页面关闭后重新打开没有记录之前访问页(还是持久化存储的问题)
技术栈
- 构建工具 @vue/cli
- 状态管理:vuex
- 路由:vue-router
- UI 框架 view-design
- postcss插件:postcss-px2rem
- css预处理语言:less
- 代码规范:eslint
添加可伸缩布局方案
! function (window) {
/* 设计图文档宽度 */
var docWidth = 1920;
var doc = window.document,
docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
var recalc = (function refreshRem() {
var clientWidth = docEl.getBoundingClientRect().width;
docEl.style.fontSize = Math.max(Math.min(20 * (clientWidth / docWidth), 30), 8.55) * 5 + 'px';
return refreshRem;
})();
/* 添加倍屏标识,安卓倍屏为1 */
docEl.setAttribute('data-dpr', window.navigator.appVersion.match(/iphone/gi) ? window.devicePixelRatio : 1);
if (/iP(hone|od|ad)/.test(window.navigator.userAgent)) {
/* 添加IOS标识 */
doc.documentElement.classList.add('ios');
/* IOS8以上给html添加hairline样式,以便特殊处理 */
if (parseInt(window.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/)[1], 10) >= 8)
doc.documentElement.classList.add('hairline');
}
if (!doc.addEventListener) return;
window.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
}(window);
项目中主要使用了flex布局。由于设计稿是1080 * 1920
的大小,还需要兼容在电脑上显示,而在电脑中显示时除去收藏夹等内容,高度是达不到1080的。这部分主要使用了css中的vh
单位和calc()
方法进行计算。
同时使用postcss,将全局的单位统一成rem。
全局配置
全局配置主要涉及到权限控制,公共样式和公共组件
1. 权限控制分为:
- 登录权限
- 页面权限(菜单权限 + 按钮权限)
- 接口权限
登录权限
登录访问权限控制是对用户的校验。在用户登录成功之后,后台将返回一个token,之后前端每次进行接口请求的时候,都要带上这个token。后台拿到这个token后进行判断,如果此token确实存在并且没有过期,则可以通过访问。如果token不存在或后台判断已过期,则会跳转到登录页面,要求用户重新登录获取token。
首先我们调用登录接口,调用成功后我们能够获取到返回数据中的token
,我们将token
存储到localstorage
中(一定不能使用sessionstorage
, 因为sessionstorage
只能在当前窗口使用,当我们打开新的标签页时会获取不到token,就无法判断是否已经登录)。之后我们在axios
的请求拦截器service.interceptors.request.use
中将token放入到请求头中
thisConfig.headers = {
'Content-Type': 'application/json;charset=utf-8',
Authorization: window.localStorage.getItem('storagetoken'),
};
页面权限:
当我们登录后可以通过接口获取用户角色的权限树,这里我们使用
vuex + localstorage
持久化存储用户权限树。之后我们展示权限树,如果用户通过URL进行强制访问没有权限的页面,在router.beforeEach()
中判断权限,无权限直接跳转到404页面。
菜单白名单配置:
我们可以使用路由的meta属性给页面添加白名单权限,如果meta设置了当前页面为所有人都可以访问的话,就直接跳转,不判断是否有权限
按钮权限:
1.每个模块对应有四种权限,查询(get),添加(post),更新(put),删除(delete)
2.利用十进制和二进制来表示当前模块所拥有的权限。1111(15),转换后的二进制与权限的关系表示:从右至左数(1代表拥有该权限,0代表不拥有),第一位代表查询,第二位代表添加,第三位代表更新,第四位代表删除。如eg:二进制1111(15),代表用于查询,添加,更新,删除四种权限。
3.判断对应模块没有此权限时,移除当前按钮dom元素。
接口权限:
最后再加上请求控制作为最后一道防线,路由可能配置失误,按钮可能忘了加权限,这种时候请求控制可以用来兜底,越权请求将在前端被拦截。
2. 公共样式
公共样式主要涉及到
- 字体,字号
- 系统主要颜色和背景色
- 全局变量
3. 公共组件
设计公共组件需要我们先仔细阅读UI的设计图,从中抽离出合适的公共组件。这些组件可以分为偏逻辑的组件
和偏样式的组件
,我们需要使用经验根据设计图来设计组件。
其实就和抽离代码中的公共部分类似,不能把组件设计的过于详细,这样使用起来特别麻烦,最好是能最大程度的完成一个独立的功能模块。
这部分可以看看这篇文章 现代 Web 开发困境与破局 - 牛岱的文章 - 知乎
结尾
到这里我们就能处理掉上面的主要问题了,主要就是持久化存储和权限判断的问题。除此之外,项目中还有其他的收获,下次再谈。