最近做一个CMS管理系统,采用前后端分离模式。由于前端开发人员排不开期,所以只好我们PHP自己写页面。对于我这样一个连Jqery都不会写的初级码农,突然要求用vue写页面,着实困难不小。一脸懵逼…两脸懵逼…虽然写起来磕磕绊绊,但最后还是如期完工了。至此,我总结了两点,先说重要的。新接触任何一个事物,心态要摆正,一定不能产生抵触心理。再然后是充分理解新事物的核心理念,vue的核心是数据双向绑定。

到最后,功能虽然实现了,但小问题还有很多。这里就说说ElementUI日期组件的的坑以及解决方法。关于问题描述,已经有人提出issue,详情可以参考这个issue

这里再描述下问题是怎么产生的和如何解决的。Date对象使用UTC时间,比北京时间慢8小时。ElementUI的日期组件会在展示的时候自动将UTC时间转成本地时间,但model仍是UTC时间。可以脑补一副撕逼画面:运营找开发说,我特么的明明选择了这个活动的上线时间是2018年1月1日08时00分00秒,现在都特么中午了,怎么还没自动上线?然后,后端开发查查数据库发现这个活动的实际开始时间是2018年1月1日16时00分00秒。后端找前端问,是不是你给我传错时间了……

现在问题就出在这慢了的8小时。如果前端是个可爱的小妹妹,她会求后端开发在保存到数据库之前处理一下她传过来的这个时间。后端开发乐呵呵地去改了。如果前端是个满脸胡子的大老爷们儿……老爷们儿心里说一句妈卖批,然后自己改。满脸胡子的前端一边写如下代码一边心里说,多大点事儿啊!老子分分钟搞定。

1
2
3
4
5
6
let date = this.createDate;
date = [
[date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-'),
[date.getHours(), date.getMinutes(), date.getSeconds()].join(':')
].join(' ').replace(/(?=\b\d\b)/g, '0');
this.createDate = date;

上边代码能把UTC时间处理成北京时间,但也把时间对象变成了时间字符串。看起来没毛病,但其实有毛病,在vue里就会有毛病。我们假设this.createDate是日期控件绑定的值,起初它是一个对象,在传给后端之前做了时区转换,这个绑定的值也从对象变成了字符串。双向绑定、双向绑定、双向绑定,所以转换之后的this.createDate已经不是对象了。当再次提交表单就会提示找不到getFullYear这个方法。

解决这个问题其实非常简单,我们不要直接改变绑定的这个日期控件的值。在传给后端之前,新定义一个变量let dateTemp,把双向绑定的this.createDate赋值给新定义变量。然后转换dateTemp为正确时区。

有添加的地方就有编辑,所以在获取数据之后先要把时间字符串转换成对象,然后再赋值给绑定的this.createDate。即:

1
this.createDate = new Date(Date.parse(timestamp.replace(/-/g, "/")))