blog项目前台展示——查询数据库中的文章类型并展示时出现的bug
1 正常演示
2 用jquery查询数据库并添加到页面后
3 相关代码
<script src="/static/jquery-2.1.4.js"></script>
<script src="/static/layui/layui.js"></script>
<script src="/static/js/yss/gloable.js"></script>
<script src="/static/js/plugins/nprogress.js"></script>
<script>NProgress.start();</script>
<script src="/static/js/yss/article.js"></script>
$.post(
'/blog?method=selectBlogType',
function (result) {
if (result.code === 0) {
console.log(result.data);
var i = 2;
$(result.data).each(function (){
console.log(this.name);
var html = '';
/*<li data-index="3"><a href="/Blog/Article/2/" onClick="selectByType('1')">HTML5&CSS3</a></li>*/
html += '<li data-index="'+ i +'"><a href="javascript:void(0)" οnclick="selectByType('+ this.id +', null)">' + this.name +'</a></li>';
$('#category').append(html);
i++;
});
}
},
'json'
)
其余部分:
layui.use(['form'], function(){
var form = layui.form;
// 搜索提交
form.on('submit(submitSearch)', function(data){
var field = data.field; // 获得表单字段JSON格式
//console.log(field);//title
selectByType(null, field.title);
return false; // 阻止默认 form 跳转
});
});
function selectByType(typeId, title) {
$.post(//抽取成方法 直接放到function里边就行
'/blog?method=selectByType',
{'typeId': typeId,'title': title},
function (result) {
if(result.code === 0) {
$('#LAY_bloglist').empty();
$(result.data).each(function (){
//js切割日期并展示
var html = '';
html += '<section class="article-item zoomIn article">';
html += ' <div class="fc-flag">置顶</div>';
html += ' <h5 class="title">';
html += ' <span class="fc-blue">【原创】</span>';
html += ' <a href="read.html">'+this.title+'</a>';
html += ' </h5>';
html += ' <div class="time">';
html += ' <span class="day">21</span>';
html += ' <span class="month fs-18">1<span class="fs-14">月</span></span>';
html += ' <span class="year fs-18 ml10">'+ this.createTime +'</span>';
html += ' </div>';
html += ' <div class="content" style="height: 180px; overflow:hidden">';
html += ' <a href="read.html" class="cover img-light">';
html += ' <img src="/pic/'+ this.image +'">';
html += ' </a>';
html += ' '+ this.content +'';
html += ' </div>';
html += ' <div class="read-more">';
html += ' <a href="read.html" class="fc-black f-fwb">继续阅读</a>';
html += ' </div>';
html += ' <aside class="f-oh footer">';
html += ' <div class="f-fl tags">';
html += ' <span class="fa fa-tags fs-16"></span>';
html += ' <a class="tag">ASP.NET MVC</a>';
html += ' </div>';
html += ' <div class="f-fr">';
html += ' <span class="read">';
html += ' <i class="fa fa-eye fs-16"></i>';
html += ' <i class="num">57</i>';
html += ' </span>';
html += ' <span class="ml20">';
html += ' <i class="fa fa-comments fs-16"></i>';
html += ' <a href="javascript:void(0)" class="num fc-grey">1</a>';
html += ' </span>';
html += ' </div>';
html += ' </aside>';
html += '</section>';
$('#LAY_bloglist').append(html);
})
}
},
'json'
);
}
4 原因分析
4.1 用jquery添加的新节点没有绑定相应的事件监听器
这是我用火狐浏览器才发现的(就是那个event
),其他浏览器没有明显地显示事件监听器
4.2 因为layui本身就用到了jquery,所以再导入jquery并使用产生了一些冲突(具体是啥没分析出来,控制变量法得知是有问题的)
5 解决措施
针对4.1
让我想到了后台管理界面的权限管理展示逻辑也是查询后再生成的
,也是用的layui,但它却正常带有事件监听器,正常显示
回顾了下代码发现是将查询到的数据放到了session(域对象)中,然后用JSTL的foreach进行遍历生成的,而不是用jquery
servlet:
jsp(html):
所以我也修改了这个前台的类型展示逻辑:查询出博客类型后放到session
中然后用JSTL
来遍历(试了下request
好像不行?)
servlet:
private void selectBlogType(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("BlogController.selectBlogType");
List<Type> types = blogService.selectBlogType();
System.out.println(types);
HttpSession session = req.getSession();
session.setAttribute("types", types);
//toJSON(resp, Result.ok("查询成功", types));
toJSON(resp, Result.ok("查询成功",types));
}
jsp(html):
<ul class="category mt20" id="category">
<li data-index="0" class="slider"></li>
<li data-index="1"><a href="javascript:void(0)" onclick="tools.selectByType(null)">全部文章</a></li>
<c:forEach items="${types}" var="type" varStatus="st">
<li data-index="${st.count+1}"><a href="javascript:void(0)" onclick="tools.selectByType(${type.id},null)">${type.name}</a></li>
</c:forEach>
</ul>
这样改之后还是不行,主要原因就是4.2
针对4.2
不再单独引入jquery,直接在layui.use中调用jquery,使用layui自带的jquery。
这就需要把所有的jquery相关的操作全都放进layui.use,这就导致了另一个问题:
a标签的onclick绑定的方法也在layui.use里边,如何调用layui.use()作用域里的方法?
使用layui,动态生成的标签加onclick点击事件,终于找到一个能用的方法了,可以获取当前元素
如何调用layui.use()作用域里的方法
我采用了第二篇博客的方法,很管用!
jsp(js):
layui.use(['form', 'jquery'], function(){
var form = layui.form;
var $ = layui.$ //重点处
var _tools = {
selectByType: function (typeId, title) {
$.post(//抽取成方法 直接放到function里边就行
'/blog?method=selectByType',
{'typeId': typeId,'title': title},
function (result) {
if(result.code === 0) {
$('#LAY_bloglist').empty();
$(result.data).each(function (){
//js切割日期并展示
var html = '';
html += '<section class="article-item zoomIn article">';
html += ' <div class="fc-flag">置顶</div>';
html += ' <h5 class="title">';
html += ' <span class="fc-blue">【原创】</span>';
html += ' <a href="read.html">'+this.title+'</a>';
html += ' </h5>';
html += ' <div class="time">';
html += ' <span class="day">21</span>';
html += ' <span class="month fs-18">1<span class="fs-14">月</span></span>';
html += ' <span class="year fs-18 ml10">'+ this.createTime +'</span>';
html += ' </div>';
html += ' <div class="content" style="height: 180px; overflow:hidden">';
html += ' <a href="read.html" class="cover img-light">';
html += ' <img src="/pic/'+ this.image +'">';
html += ' </a>';
html += ' '+ this.content +'';
html += ' </div>';
html += ' <div class="read-more">';
html += ' <a href="read.html" class="fc-black f-fwb">继续阅读</a>';
html += ' </div>';
html += ' <aside class="f-oh footer">';
html += ' <div class="f-fl tags">';
html += ' <span class="fa fa-tags fs-16"></span>';
html += ' <a class="tag">ASP.NET MVC</a>';
html += ' </div>';
html += ' <div class="f-fr">';
html += ' <span class="read">';
html += ' <i class="fa fa-eye fs-16"></i>';
html += ' <i class="num">57</i>';
html += ' </span>';
html += ' <span class="ml20">';
html += ' <i class="fa fa-comments fs-16"></i>';
html += ' <a href="javascript:void(0)" class="num fc-grey">1</a>';
html += ' </span>';
html += ' </div>';
html += ' </aside>';
html += '</section>';
$('#LAY_bloglist').append(html);
})
}
},
'json'
);
},
}
window.tools = _tools;
_tools.selectByType(null, null);
/*$.post(
'/blog?method=selectBlogType',
function (result) {
/!*if (result.code === 0) {
console.log(result.data);
var i = 2;
$(result.data).each(function (){
console.log(this.name);
var html = '';
/!*<li data-index="3"><a href="/Blog/Article/2/" onClick="selectByType('1')">HTML5&CSS3</a></li>*!/
html += '<li data-index="'+ i +'"><a href="javascript:void(0)" οnclick="tools.selectByType('+ this.id +', null)">' + this.name +'</a></li>';
$('#category').append(html);
i++;
});
}*!/
},
'json'
)*/
// 搜索提交
form.on('submit(submitSearch)', function(data){
var field = data.field; // 获得表单字段JSON格式
//console.log(field);//title
_tools.selectByType(null, field.title);
return false; // 阻止默认 form 跳转
});
});
jsp(html):
<ul class="category mt20" id="category">
<li data-index="0" class="slider"></li>
<li data-index="1"><a href="javascript:void(0)" onclick="tools.selectByType(null)">全部文章</a></li>
<c:forEach items="${types}" var="type" varStatus="st">
<li data-index="${st.count+1}"><a href="javascript:void(0)" onclick="tools.selectByType(${type.id},null)">${type.name}</a></li>
</c:forEach>
</ul>
查询文章类型并放到session的操作我放到了上一个页面,如果放在这个页面的话,第一次加载时JSTL没法取到session中的内容,需要刷新一次才能显示出来,感觉不太好。
为了保持一致性,还是使用了layui里边的jquery,并且加了个查询反馈弹窗(拖会儿时间,保证跳转到页面时session中已经有内容了)
index.jsp:
js代码:
layui.use(['layer', 'jquery'],function (){
var layer = layui.layer;
var $ = layui.$ //重点处
$('#selectBlogType').on('click', function (){
$.post(
'/blog?method=selectBlogType',
function (result) {
if (result.code === 0) {
layer.msg(
result.msg,
{icon: 1, time: 1000},
function() {// msg消失之后触发的函数
location.href = '/page/list';
}
);
}
},
'json'
)
})
})
html代码:
<li><a href="javascript:void(0)" id="selectBlogType">博客列表</a></li>
6 结果展示
7 其他参考
jsp中使用c:forEach标签自动添加序号
基础知识回顾:
layui发送ajax请求post
Layui中jquery的使用方式
拓展——jquery事件委托:
jQuery-给ul添加了li之后,添加的li并没有绑定点击监听怎么办?
jQuery学习:事件委托–新添加的元素没有监听
JS事件监听与事件委托(前端小白必学)