今天在用Layui的时候,由于需要做三级联动菜单,当我用“Ajax实现三级联动下拉菜单省市区(PHP+JavaScript)原生代码”的时候,却发现:
用了Layui这种前端框架,Layui表单“动态加载select数据时,会导致点击select没有反应或者点击两次才出现下拉列表“的情况。
原因:
我首先是保证我的代码是没有任何错误与BUG的,我已经调试过半天了。
最终才发现我主要的问题还是Layui表单“更新渲染”的问题,是由于逻辑有问题所造成的。
我也去看了一下Layui手册,Layui表单“更新渲染”官方手册内容如下:
有些时候,你的有些表单元素可能是动态插入的。这时 form 模块 的自动化渲染是会对其失效的。虽然我们没有双向绑定机制(因为我们叫经典模块化框架,偷笑.gif) 但没有关系,你只需要执行 form.render(type, filter); 方法即可。
1、第一个参数:type,为表单的 type 类型,可选。默认对全部类型的表单进行一次更新。可局部刷新的 type 如下表:
参数(type)值 描述 select 刷新select选择框渲染 checkbox 刷新checkbox复选框(含开关)渲染 radio 刷新radio单选框框渲染
例如:
form.render(); //更新全部 form.render('select'); //刷新select选择框渲染 //……
2、第二个参数:filter,为 class="layui-form" 所在元素的 lay-filter="" 的值。你可以借助该参数,对表单完成局部更新。
例如:
【HTML】 <div class="layui-form" lay-filter="test1"> … </div> <div class="layui-form" lay-filter="test2"> … </div> 【JavaScript】 form.render(null, 'test1'); //更新 lay-filter="test1" 所在容器内的全部表单状态 form.render('select', 'test2'); //更新 lay-filter="test2" 所在容器内的全部 select 状态 //……
解决方法
知道了原因,也看了手册,解决起来就容易多了,主要的原因就是Layui表单“更新渲染”的问题,以我这里为例子,最最主要的代码就是看:
form.render('select');
如果是ajax的话,请求成功后,得到返回的数据,Layui表单就需要“更新渲染”。
当看了我以前写的代码的时候,发现我的代码逻辑的确是有问题的,以前写的代码,具体可以去看:
Layui select onchange事件 正确使用教程
那里有最完整的代码。
最终,修改后的代码如下:
由于我用的是原生的JavaScript Ajax代码,我之所以出现:Layui表单“动态加载select数据,点击两次才出来”这个问题,无非就是我把 form.render('select'); 位置放错地方了。
因为我忘记了原生的JavaScript Ajax代码并不是按代码顺序从上到下来执行的,它是先ajax请求,成功后,正常返回了数据,再执行相关的JavaScript document渲染代码。
<script>
layui.use(['form', 'layedit', 'laydate'], function(){
var form = layui.form;
form.on('select(Loadprovince)', function(data){
//var val=data.value;
//console.info(val);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if(document.getElementById("city").getAttribute("disabled")){
//console.info(100);
document.getElementById("city").removeAttribute("disabled");
}else{
//console.info(200);
//document.getElementById("city").setAttribute("hidden","hidden");
document.getElementById("county").innerHTML = '<option value="county">县</option>';
document.getElementById("county").setAttribute("disabled","disabled");
}
document.getElementById("city").innerHTML = this.responseText;
form.render('select');
}
};
//获取省地区的ID并ajax传送到服务端,例如:四川省id=5
var data = "province=" + document.getElementById("province").value + "&type=<?php echo $type;?>";
//console.log(data);
xhttp.open("POST", "<?php echo $HOMEURL.$ADMIN_ADDRESS;?>?action=unique-ajax", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(data);
//form.render();
//以前放的位置 form.render('select');
});
form.on('select(Loadcity)', function(data){
//var val=data.value;
//console.info(val);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if(document.getElementById("county").getAttribute("disabled")){
document.getElementById("county").removeAttribute("disabled");
}
document.getElementById("county").innerHTML = this.responseText;
form.render('select');
}
};
var data = "city=" + document.getElementById("city").value + "&type=<?php echo $type;?>";
console.log(data);
xhttp.open("POST", "<?php echo $HOMEURL.$ADMIN_ADDRESS;?>?action=unique-ajax", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(data);
//form.render();
//以前放的位置 form.render('select');
});
}
);
</script>
总结:
如果你是其它的框架,估计还是会遇到:表单“动态加载select数据时,会导致点击select没有反应或者点击两次才出现下拉列表“的情况。
毕竟每个人用的框架不同,代码编程语言也不同。就拿ajax来说,有框架本身支持的语法,也有jquery ajax语法,还有原生的JavaScript ajax语法。虽然说原理都差不多,但是你想兼容就不容易了。
就拿我自己亲身体验来说,我用原生的JavaScript ajax语法还要兼容Layui这种框架,我只能换一种思路去修改。谁知道在Layui框架中,纯原生的JavaScript ajax语法居然没作用!你想不改都不行。
友情提示:
经过长期的测试,Layui里也可以直接写原生的JavaScript ajax代码,是我自己代码写的有问题,才会造成了原生JavaScript Ajax代码不生效,因此大家可以放心的在Layui框架里写纯原生的JavaScript代码。




