视频
一、本节简介
上节我们把知识体系列表获取下来了,这节我们来看看知识体系点击条目进入详情功能,点击效果大概可以以下三种方式实现
- html 中添加 onclick 方法
- 使用 bui 数据驱动的 b-click
- 使用 bui 的事件委托
跳转的话就是 bui 的路由机制就可以了,我们逐一来看看
二、点击事件
1、html 标签中添加 onclick 方法
直接在 knowledte.js 的知识体系列表中的模版字符串中「二级分类标签整个条目」添加一个 onclick 方法并把当前的索引传递过去,在路由中要使用
<li onclick="showDetail(${index})"style="display: flex;justify-content: space-between;align-items: center;padding:10px;">
<ul style="display:flex;flex-wrap: wrap;">
${el.children.map((child,childIndex)=>
`${childIndex < 6? `<li style="padding:5px">
<div style="padding:5px;border:1px solid red;background:#eee;">
<span>${child.name}</span>
</div>
</li>`:""}`
).join('')}
</ul>
<i class="icon-listright">
</i>
</li>`
而后在 builist 的组件外定义一个 showDetail 方法,方便测试我简单的打一个 log,输出当前条目的索引
function showDetail(index){
console.log(index)
}
运行起来点击条目看效果,在 chrome 的 console 中查看
很不幸报错了,说方法未定义,我们明明定义了一个 showDetail 方法,为何提示未定义「WTF」?为什么呢?其实这就涉及到 js 作用域的问题「此处是方法的作用域」
简单来说就是 onclick 只能调用自身代码块中的方法或是全局方法,这块涉及到方法声明和方法表达式之间的关系,具体可以查看这里,这么说还有点抽象那直接上个代码来说明一下问题
<script type="text/javascript">
function test(params) {
console.log(params)
var test2 = function(){
console.log('test2')
}
}
</script>
<button onclick="test2()">click</button>
这样直接调用 test2 是调用不了的,因为 test2 是公共方法 test 内部的,只有 test 能调用,别的调用不了会提示方法未定义,我们的情况和这个类似,如何解决呢?
我们直接写在标签中,或是直接把 showDetail 挂到 window 对象上把它变成全局方法即可
方式一:在 script 标签中写方法
<script>
function showDetail(index){
console.log(index)
}
<\/script>
<li onclick="showDetail(${index})"style="display: flex;justify-content: space-between;align-items: center;padding:10px;">
<ul style="display:flex;flex-wrap: wrap;">
${el.children.map((child,childIndex)=>
`${childIndex < 6? `<li style="padding:5px">
<div style="padding:5px;border:1px solid red;background:#eee;">
<span>${child.name}</span>
</div>
</li>`:""}`
).join('')}
</ul>
<i class="icon-listright">
</i>
</li>`
方式二:定义全局方法
// 把 showDetail 变成全局方法
window.showDetail = function(index){
console.log(index)
}
这样就解决了方法未定义的问题,其实上面两种方法最终都是把方法挂到 window 上面形成全局方法了
这种做好不太好,为啥呢?动不动把一个方法搞成全局的失去灵活性,下面我们来看看 bui 事件驱动中如何做
2、bui 事件驱动点击事件
完过 vue 的朋友玩 bui 的事件驱动那就是菜两者 api 几乎一样,我们直接来使,使用 bui-store 来快速创建事件驱动的代码片断
// 初始化数据行为存储
var bs = bui.store({
scope: "page",
data: {
// 声明数据
datas: []
},
methods: {
showDetail:function(index,e) {
console.log(index);
console.log(e);
// 这里处理跳转逻辑
}
},
watch: {},
computed: {},
templates: {},
mounted: function() {
// 数据解析后执行
// 列表控件 js 初始化:
var that = this ;
var uiList = bui.list({
id: "#knowledge-list",
url: baseUrl + "/tree/json",
pageSize: 5,
data: {},
//如果分页的字段名不一样,通过field重新定义
field: {
page: "page",
size: "pageSize",
data: "data"
},
callback: function(e) {},
template: function(data) {
that.datas = data;
var html = "";
data.map(function(el, index) {
// console.log(el.name)
html += `
<li class="bui-btn-title">
${el.name}
</li>
<li b-click="page.showDetail(${index})" style="display: flex;justify-content: space-between;align-items: center;padding:10px;">
<ul style="display:flex;flex-wrap: wrap;">
${el.children.map((child,childIndex)=>
`${childIndex < 6? `<li style="padding:5px">
<div style="padding:5px;border:1px solid red;background:#eee;">
<span>${child.name}</span>
</div>
</li>`:""}`
).join('')}
</ul>
<i class="icon-listright">
</i>
</li>`
});
return html;
},
autoScroll: false, // 滚动到底部不自动加载
});
}
})
核心就是把数据定义出来「由于我们返回的是一个数组,扬所以定义为 datas:[]」,然后使用 b-click 来调用 methods 中创建的方法完成条目单击事件,运行起来看效果
我们看到 log 是打印出来了,可是点击一下方法都调用了两桨,事件冒泡了,我们直接在 methods 方法中修改即可
methods: {
showDetail:function(index,e) {
console.log(index);
console.log(e);
// 阻止事件冒泡
// e.stopPropagation();
return false ;
}
},
使用 e.stopPropagation() 或是 return false 都可以解决这个问题
这下我们就正确的处理了列表条目点击事件
3、使用事件委托解决点击事件
试想一下如果渲染列表有 100 项会声明 100 个 onclick ,1w 项那简直是噩梦,会严重影响性能,所以我们使用事件委托机制来解决这个问题
事件委托机制内部采用的是事件冒泡机制,来看代码
先给我们的标签 li 给一个 id knowledge-li
,然后我们这个 li 其实是对应 knowledge 的 class 为 bui-list 的 ul 下,我们就可以把事件委托给 ul
router.$("ul").on("click", "#knowledge-li", function(e) {
var index = $(this).index();
console.log(index)
// 阻止事件冒泡
e.stopPropagation();
// return false ; 阻止后续事件和阻止事件冒泡效果相同
})
这就搞定了代码单独编写也没有问题,这里 bui-store 外面 ,就这么简单。来看一下效果
我们看到打出来的 log 是一组奇数,为什么呢?因为我们的 ul 下面还有一个标题呢,所以们点击标签条目的时候就会从 1 3 5 … 开始,这不行,我们拿到 data 才取索引值会有问题了,我们处理一下,将索引值 var index = $(this).index();
换成下面的方法即可
var index = ($(this).index()-1)/2;
这样我就就正确打出来了索引值,就可以取出条目中的数据然后传递到下一页去了
本节到此为止,这节我们就把在 bui 中点击事件方式大概说了一下,下节我们完成知识体系条目点击进二级导航
作者: TigerChain 公号同名,订阅查看更多内容