写这一篇完全是想把自己平时对vue的使用体验与理解看记录下来,如有错误欢迎指正。
1.router的beforeEach与afterEach钩子函数
在开发vue项目时遇到这样两个问题:第一个问题是用户可能从项目的任何一个“页面”进入,当用户未登录时需要跳转到登录页,而未登录信息会通过请求任何一个接口时返回。第二个问题是项目经理要求接入百度统计,用于后台统计数据。我们知道vue为单页面应用,显然不能用常规方法。怎么办呢?router的beforeEach与afterEach钩子函数banb帮我解决了这两个问题。
针对第一个问题我最开始是用axios的拦截器处理的(有关拦截器的可以看这里),用户请求任意一个接口时只要返回未登录就给用户弹框提示并跳转登录页,但有问题,一个组件同时请求多个接口,都会返回该信息,会弹出很多次弹框,另外必须是用户进入了该页面才跳到登录页,太慢,体验感不好。这里用router.beforeEach完美解决。beforeEach是指在跳转之前执行。
针对第二个问题直接贴代码吧
router.afterEach((to, from, next) => {
setTimeout(() => {
let _hmt = _hmt || [];
(function() {
// 每次执行前,先移除上次插入的代码
document.getElementById('baidu_tj') && document.getElementById('baidu_tj').remove();
let hm = document.createElement('script');
hm.src = 'https://hm.baidu.com/hm.js?2b070cffa2082bee253b59a0794132';
let s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();
}, 0);
});
用的是afterEach函数, 在跳转之后执行。为什么要在之后执行,想必应该明白。有些虽然跳转了但并未进来,所以不能计入统计。
具体说下router的生命钩子吧
总体来讲vue里面提供了三大类钩子,两种函数
a、全局钩子
b、某个路由的钩子
c、组件内钩子
两种函数:
a、Vue.beforeEach(function(to,form,next){}) /*在跳转之前执行*/
b.Vue.afterEach(function(to,form))/*在跳转之后判断*/
全局钩子函数
顾名思义,它是对全局有效的一个函数
router.beforeEach((to, from, next) => {
let token = router.app.$storage.fetch("token");
let needAuth = to.matched.some(item => item.meta.login);
if(!token && needAuth) return next({path: "/login"});
next();
});
beforeEach函数有三个参数:
- to:router即将进入的路由对象
- from:当前导航即将离开的路由
- next:Function,进行管道中的一个钩子,如果执行完了,则导航的状态就是 confirmed (确认的);否则为false,终止导航。
afterEach函数不用传next()函数
某个路由的钩子函数
顾名思义,它是写在某个路由里头的函数,本质上跟组件内函数没有区别。
const router = new VueRouter({
routes: [
{
path: '/login',
component: Login,
beforeEnter: (to, from, next) => {
// ...
},
beforeLeave: (to, from, next) => {
// ...
}
}
]
})
路由组件的钩子
注意:这里说的是路由组件!
路由组件 属于 组件,但组件 不等同于 路由组件!所谓的路由组件:直接定义在router中component处的组件。如:
var routes = [
{
path:'/home',
component:home,
name:"home"
}
]
在子组件中调用路由的钩子函数时无效的。
2.对于接口数据的处理看法
受到之前做后端出身的项目经理影响,一般情况下对于后端请求来的接口数据保持不可信任态度。因此我在处理接口数据不是直接拿过来用,那样接口数据一旦出问题,或者字段缺失就会导致页面显示出现问题。有些人认为现在用vue,html里面可以直接针对缺省情况进行处理。但个人不建议,那样对于简单数据可以处理,复杂了就不行了。同时也存在另一个问题,给后来的维护带来麻烦,因为直接使用,接口请求过来的数据相当于黑箱子,里面数据什么结构一概不知。
不说了上代码
API.getOpenCourtList({id}).then(res => {
console.log(res);
if (res.retCode === 0) {
state.openCourtDetailCount = res.retData.count || 0;
let data = res.retData.list;
let openCourtDetail = [];
for (let i = 0; i < data.length; i++) {
let detail = {};
// 序号
detail.num = i + 1;
// 案由
detail.caseReason = data[i].caseReason || '未公开';
// 案号
detail.caseNo = data[i].caseNo || '未公开';
// 原告/上诉人
detail.plaintiffName = [];
for (let k = 0; k < data[i].plaintiff.length; k++) {
detail.plaintiffName.push(data[i].plaintiff[k].name);
}
detail.plaintiffName = detail.plaintiffName.length > 0 ? detail.plaintiffName : ['未公开'];
// 被告/被上诉人
detail.defendant = [];
for (let j = 0; j < data[i].defendant.length; j++) {
detail.defendant.push(data[i].defendant[j].name);
}
detail.defendant = detail.defendant.length > 0 ? detail.defendant : ['未公开'];
// 开庭日期
detail.startDate = data[i].startDate || '未公开';
// 当事人
detail.litigant = data[i].litigant || '未公开';
// 承办部门
detail.contractors = data[i].contractors || '未公开';
// 审判长/主审人
detail.judge = data[i].judge || '未公开';
// 法院
detail.court = data[i].court || '未公开';
// 法庭
detail.courtroom = data[i].courtroom || '未公开';
openCourtDetail.push(detail)
}
console.log(openCourtDetail)
state.openCourtDetail = openCourtDetail;
}
})
看着挺长,但足够一目了然。接口请求过来的数据全部解析一遍,统一做缺省处理。这样处理有人会有每次请求要跑for循环会影响性能。 大家怎么看呢?
3.对于组件封装的看法
对于组件封装个人认为主要有以下几个作用
- 提高开发效率
- 方便重复使用
- 简化调试步骤
- 提升整个项目的可维护性
- 便于协同开发
组件的特点:
a.高内聚性,组建功能必须是完整的,如我要实现下拉菜单功能,那在下拉菜单这个组件中,就把下拉菜单所需要的所有功 能全部实现。
b.低耦合度,通俗点说,代码独立不会和项目中的其他代码发生冲突。在实际工程中,我们经常会涉及到团队协作,传统按 照业务线去编写代码的方式,就很容易相互冲突,所以运用组件化方式就可大大避免这种冲突的存在、每一个组件都有子 集清晰的职责,完整的功能,较低的耦合便于单元测试和重复利用。
有些人会认为只在需要复用功能时才去封装组件,其实为了保证代码的简洁性,我们需要在按页面功能按需封装组件,最好 能确保一个组件中代码不能过多导致不具有可读性。组件的封装会使得部分人觉得太麻烦了,浪费时间。其实好的封装能大 大地减少开发时间。当然也不能过度封装。曾经我就做过将一个页面封装了20多个组件(这里面包括复用的组件),对于我 这种封装狂魔,浏览器不干了。根本跑不动。页面渲染速度极慢。