欢迎来到小懒的博客~email:568705236@qq.com

转载:探索 layui 的 onevent 和 event

2020/10/2 10:29:40站长

    使用layui的同学,不知道大家是不是跟我一样其实基本不会用到layui提供的onevent和event这两个方法。但是其实我们每天都跟他们打交道,因为组件的事件监听基本都是基于onevent做的,只不过是在它的基础上又给加了一个“糖衣”,但是平时的话还是基本不会用onevent监听什么事件的。


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

image.png

    代码如下,如果想在本地试一下的同学请到这 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的最后片段。

image.png

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

image.png

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


    到此觉得很顺利,但是同时也觉得有一个隐患,如果定义事件的时候子事件早于母事件定义会是什么情况呢?比如把onevent send(A)的代码段放到send的前面,那么问题就来了,小明发送消息的时候会是消息在前时间在后面。
    来几个表情压压惊,其实也是可以接受理解的,假如,真把他们当成母子事件,那是不是应该先有母事件才能有子事件呢?OK,这回顺利,总不能先有了孩子再有妈妈吧。当然所谓的母子事件纯粹周末空闲倒腾出来的,是不是设计者设计的时候就考虑进去了这个只能官方的才能解密了。


    转自:https://fly.layui.com/jie/27143/

赞赏