【分享】PJAX模式下使用Laydate时间组件二次渲染问题解决方案

JBolt极速开发平台里的自动化时间组件,用的是laydate.js,在layui里可以使用,在非layui里也可以独立版使用。

这里我使用的是独立版。

遇到的问题

和前面我分享的PJAX下的UEditor和Webcam组件,都是出现二次渲染的问题。

第二次执行laydate.render的时候,组件失效,不报错,也不显示了!

【分享】Pjax模式下集成一个同时支持IE和Chrome的webcam组件

【分享】PJAX模式下使用UEditor如何避免二次加载页面初始化失败?

laydate的调用方式如下:

image.png

针对一个输入框元素,给一个ID就行了,自动完成了初始化和事件绑定,这里我设置的是click的时候,触发渲染时间组件的弹出,默认不写就是focus的时候。

image.png

点击输入框,正常弹出了。

那么,二次渲染怎么重现这个问题呢?

pjax加载的,只要打开新页面,然后浏览器返回到本界面,就完成了二次调用laydate.render,这样bug就复现了!

如何处理?

我们现在分析一下这个bug出现的原因:

首先,我们来看第一次渲染之后,组件和页面里都有什么变化?

1、input组件本身变化

从下图可以看出,经过laydate的render之后,在全局laydate给input组件初始化,增加了一个属性lay-key="1" 有具体的赋值,而且重新刷新页面之后,这个值还是lay-key="1”说明这个值是一个渲染顺序。页面上其他的input经过laydate渲染后也有了相应的值。

image.png


那么这个值有何用?正是下面要说的第二个变化:

2、页面底部动态增加元素,id与lay-key对应。

image.png

image.png


好了,经过页面代码的分析我们就知道,laydate.render执行后呢,页面的元素都有了绑定和变化。

lay-key和弹出层都是对应的。而且手动点击左侧导航去切换页面,在点击laydate的demo页面进来,这种主动触发加载的行为,是没有问题的,而且laydate组件的渲染lay-key的顺序是继续增加的,同样第一个input组件,在首次render的时候给的lay-key="1",再次主动触发加载页面,相当于是全新加载的页面,laydate把它当做是全新组件渲染,会给自身队列中继续累加数量。

这个可以看一下,点击进入几次之后的lay-key="23"

image.png


但是PJAX技术是类似浏览器自身缓存了加载的界面的状态,当使用浏览器返回按钮返回到本页面的时候,并不是去后台重新加载渲染的本页面,而是拿到的缓存,组件因为已经被渲染过了,自身的lay-key="1"还存在呢,laydate自己也懵逼了,一看有值就不重新绑定渲染了。


这就是,pjax下浏览器返回已经渲染过的界面后,laydate.render二次渲染失效的根本原因。


那么,怎么办呢?

这个要么是Layui作者修复这个问题,能针对这种PJAX加载和回退浏览器重新渲染的问题做处理,要么就按照我的方案,搞之。

我的方案是:

主动给它把lay-key去了,让它再次懵逼,一看没有lay-key那么好吧,重新render一次。

具体就是,在laydate.render之前判断是否已经有了lay-key 有就去掉。

image.png

一行代码,搞定之。

哈哈哈哈哈哈哈~~



问题咨询,加我微信:

image.png



评论区

JFinal

2019-11-02 15:23

jfinal 学院后台是基于 layui 做的了? 我记得以前是 bootstrap

山东小木

2019-11-02 15:42

@JFinal 一直是Bootstrap 但是需要一些三方组件集成 有的使用了layui中的独立组件 比如laydate组件