探索 layui 的 onevent 和 event

讨论 已结 精帖 29 7892
岁月小偷
悬赏:50飞吻
使用layui的同学,不知道大家是不是跟我一样其实基本不会用到layui提供的onevent和event这两个方法。但是其实我们每天都跟他们打交道,因为组件的事件监听基本都是基于onevent做的,只不过是在它的基础上又给加了一个“糖衣”,但是平时的话还是基本不会用onevent监听什么事件的。

今天社区有个问题 http://fly.layui.com/jie/27137/ 就是定义了onevent然后执行调用了一下layui.event结果出现执行了两次监听的情况。追了一下发现可能还是源码的一个处理逻辑有点问题。改一下自己定义onevent和执行event中带了(filter)然后就正常了。
看似问题解决了,但是也引起了我的好奇,对原先的设计有了一个大胆的猜想,是不是事件也有母子关系,不带filter的为母带filter的为子?动起手验证一下,确实达到了我猜想的效果,就是不知道是不是设计者的设计思路就不知道了,因为确实官方没有对onevent和event做什么介绍,只说了阅读源码,只能自行理解了。
例子效果如下

代码如下,如果想在本地试一下的同学请到这 https://pan.baidu.com/s/1uD7M84CwMTBzeLZBkOFd8A 下载,不要拷贝社区的代码,不敢保证社区的代码发出去会不会被控件转义了
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layui</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="js/layui/src/css/layui.css" media="all">
<!-- 注意:如果你直接复制所有代码到本地,上述css路径需要改成你本地的 -->
</head>
<body>
<div style="margin: 10px;">
<div class="layui-inline">
<label class="layui-form-label">小明:</label>
<div class="layui-input-inline">
<input name="phone" autocomplete="off" class="layui-input" style="width: 240px;">
</div>
</div>
<button class="layui-btn" lay-even="sendMessageA">发送</button>
</div>
<div style="margin: 10px;">
<div class="layui-inline">
<label class="layui-form-label">小红:</label>
<div class="layui-input-inline">
<input name="phone" autocomplete="off" class="layui-input" style="width: 240px;">
</div>
</div>
<button class="layui-btn" lay-even="sendMessageB">发送</button>
</div>
<div style="margin: 10px;">
<div class="layui-inline">
<label class="layui-form-label">系统时间</label>
<button class="layui-btn" lay-data="{align: 'center'}" lay-even="sendMessageS">发送</button>
</div>
</div>


<div id="messageView"
style="width: 480px; height: 300px;border: 1px solid #1E9FFF;margin-left: 120px;padding: 10px;overflow: auto;"></div>

<script src="js/layui/src/layui.js" charset="utf-8"></script>
<!-- 注意:如果你直接复制所有代码到本地,上述js路径需要改成你本地的 -->
<script>
layui.use(['jquery', 'util'], function ($, util) {
var active = {
sendMessageA: function () {
layui.event("message", "send(A)", {
align: 'left',
user: '小明',
msg: $(this).prev().find('input').val()
});
$(this).prev().find('input').val('');
},
sendMessageB: function () {
layui.event("message", "send(B)", {
align: 'right',
user: '小红',
msg: $(this).prev().find('input').val()
});
$(this).prev().find('input').val('');
},
sendMessageS: function () {
layui.event("message", "send", {
align: 'center'
});
}
};
var divElem = $('#messageView');
// 母事件,所有message.send(*)都会触发这个
layui.onevent("message", "send", function (params) {
divElem.append('<div style="text-align: ' + (params.align || 'center') + ';">' + util.toDateString(null, 'yyyy-MM-dd HH:mm:ss') + '</div>');
var timer = setTimeout(function () {
if (timer) {
clearTimeout(timer);
}
divElem.scrollTop(divElem[0].scrollHeight)
}, 50)
});
// 子事件A
layui.onevent("message", "send(A)", function (params) {
divElem.append('<div style="margin: 6px 0;text-align: left;">' + (params.msg || '<span style="color: #1E9FFF">没有输入,只是想你了一下</span>') + '</div>')
});
// 子事件B
layui.onevent("message", "send(B)", function (params) {
divElem.append('<div style="margin: 6px 0;text-align: right;color: pink;">' + (params.msg || '<span style="color: #1E9FFF">没有输入,只是想你了一下</span>') + '</div>')
});

$('.layui-btn').click(function () {
var elem = $(this),
event = elem.attr('lay-even');
typeof active[event] === 'function' && active[event].apply(this);
});
});

</script>

</body>
</html>

页面功能和代码相应的解析
首先定义了3个message的send事件一个“母事件”send(姑且这么叫,瞎编的可能不合适[哈哈] ),负责在聊天面板中追加系统时间,两个子事件send(A), send(B),分别就是小明和小红的聊天内容的输出啦。可以看到子事件中没有去操作调用母事件(输出发消息的时间);
然后就是三个人了,一个小明,一个小红,还有一个系统按钮,触发的方法就是去执行layui.event来触发我们定义的对应的layui.onevent事件,同样可以看到,小明或者小红发送消息的时候也没有去调用系统按钮的功能。
最终的效果就是,小明或者小红输入信息发送,会首先触发母事件然后再触发子事件,也就是先输出一个发送消息的时间然后再是发送的内容。而系统时间按钮就只触发了自身的事件。
到此感觉这可能是一个以后可以好好利用的机制。[色] 但是!还不能高兴太早!
首先如果小伙伴有兴趣的可以把我的测试代码下下来换个layui的路径跑一下试一下。应该就会很快发现一个问题,点击系统时间发送的时候会有两个连着输出了,不要怀疑是不是双击了,不是,这个就是最开始说的那个问题,不在赘叙,我说的源码的不太合理的地方是event的最后片段

可见如果是一个母事件,filter为空那么会执行两次回调。改成下面的

就正常了,其他的子事件也没有问题。

到此觉得很顺利,但是同时也觉得有一个隐患,如果定义事件的时候子事件早于母事件定义会是什么情况呢?比如把onevent send(A)的代码段放到send的前面,那么问题就来了,小明发送消息的时候会是消息在前时间在后面。
[哈哈] [哈哈] [哈哈] 来几个表情压压惊,其实也是可以接受理解的,假如,真把他们当成母子事件,那是不是应该先有母事件才能有子事件呢?OK,这回顺利,总不能先有了孩子再有妈妈吧。当然所谓的母子事件纯粹周末空闲倒腾出来的,是不是设计者设计的时候就考虑进去了这个只能官方的才能解密了[嘻嘻]
回帖
  • 胡歌
    2018-5-20
    [good]
    0 回复
  • 一阔树
    2018-5-20
    用阻止冒泡可以去掉一次出发,但是接下来return无效了。
    5 回复
  • @时光的旅行 不好意思,刚看了你发的贴了额,iframe这个我不擅长,以为一直以来都是做单页面的,只有在学校用过iframe,所以基本没啥经验,刚想这两天有人发了分享,不过看到你也在里面评论了应该是看过了,我觉得可能关键问题在于如何找到对应的iframe,然后就可以使用该iframe的document了,里面的属性之类的估计就都能得到了,不知道是不是这个意思,现在有事在忙,等闲下来就自己做测试例子看看能不能搞定,可以的话就再@ 你一下额。
    5 回复
  • @时光的旅行 [good] 不错不错
    3 回复
  • @胡歌 周末愉快[嘻嘻]
    1 回复
  • @岁月小偷 大哥可不可以帮我看看啊
    1 回复
  • 谢谢大哥了
    1 回复
  • 一阔树
    2018-5-20
    [good] [good] [good] 楼主精神佳佳佳!
    0 回复
  • @一阔树 [嘻嘻] 摸索学习
    0 回复
  • @岁月小偷 大哥能帮我一下么
    0 回复