事件句柄的注册时机

aki发表于:2020年11月17日 14:21:10更新于:2021年04月20日 15:13:00

Index

概要

如果kintone页面显示时发生的事件句柄注册的太晚,有可能捕捉不到该事件的促发。

因此,本文就针对以下内容进行解说:

  • kintone页面显示事件的促发时机

  • 事件句柄注册太晚时的警告提示

  • 在合适的时机注册事件句柄的代码写法

kintone页面显示事件的促发时机

浏览器在读取kintone页面时,kintone自身的JavaScript以及自定义用JavaScript的执行顺序如下。

  1. 浏览器开始读取页面的HTML

  2. 进行初始化为使用kintone的JavaScript API做好准备

  3. 读取自定义JavaScript的脚本

  4. 使用kintone自身的JavaScript开始执行页面的初始化处理

  5. 浏览器读完页面的HTML之后,促发DOMContentLoaded事件 (※ 1)

  6. HTML里指定的图片等资源读完之后,浏览器促发load事件 (※ 2) 

使用jQuery时,一部分JavaScript的惯例写法是在5.的DOMContentLoaded事件或者 6.的load事件的事件句柄内才开始处理。

kintone是在这些事件发生之前的顺序4.时就开始kintone自身的处理。
因此,kintone的页面显示事件有可能在DOMContentLoaded事件之前发生 (※ 3)。

如果在事件句柄注册之前就促发了事件,那么事件句柄不会被调用。
因此在DOMContentLoaded以及load事件内注册kintone的事件句柄时,有可能会不被调用。具体有以下事件。

  • app.record.create.show

  • app.record.edit.show

  • app.record.detail.show

因此,要确保能够与事件绑定的话,需要在顺序3.的读取自定义JavaScript的同时,使用kintone.events.on()注册事件句柄。

※ 1 参考 (外部网站): https://developer.mozilla.org/zh-CN/docs/Web/Events/DOMContentLoaded

※ 2 参考 (外部网站): https://developer.mozilla.org/zh-CN/docs/Web/Events/load

※ 3 kintone的页面上显示的很多控件都是由JavaScript生成的。因此,由浏览器触发的DOMContentLoaded以及load事件的结束时间与kintone 的DOM构建的完成时间是没有直接关系的。 

显示警告

如果不在顺序3.的读取自定义JavaScript的同时通过kintone.events.on()注册事件句柄,会在浏览器的开发者工具console里提示以下警告 (※ 4)。

0015fbc932a814ee51fa0b3ac21d342

如果显示此警告,请参考以下的写法示例修改事件句柄的注册时机。

※ 4 是2018年7月版之后新增的功能。如果没有注册app.record.create.show、app.record.edit.show、app.record.detail.show,或者读取自定义时在合适的时机注册了事件句柄时,不显示此警告。

写法示例

使用jQuery时的写法

不好的例子

作为jQuery的习惯性写法之一,就是用$(function(){...});的方法包住整个JavaScript的处理。

$(function() {
    kintone.events.on('app.record.create.show', function(event) {
        window.alert('促发了记录添加事件');
    });
});

根据jQuery的式样,这样写的话,会在DOMContentLoaded事件的事件句柄内执行 ... 部分的代码。

document.addEventListener("DOMContentLoaded", function(loadedEvent) {
    kintone.events.on('app.record.create.show', function(event) {
        window.alert('促发了记录添加事件');
    });
});

如上述所述,DOMContentLoaded事件是在kintone本身通过JavaScript初始化页面之后才会促发。
而这种写法,有可能发生用kintone.events.on()注册事件句柄的时间晚于app.record.create.show事件的发生,而导致不会调用事件句柄。

好的例子

虽然有点复杂,以下是结合捕捉jQuery全局变量的写法。

(function($) {
    "use strict";

    kintone.events.on('app.record.create.show', function(event) {
        window.alert('促发了记录添加事件');
    });
})(jQuery);

另外,根据自定义的处理内容,有时需要等到DOMContentLoaded事件发生之后才开始处理。

这种情况,请将“用kintone.events.on()注册事件句柄”和“在$(function() {...}内执行的处理”分开来写。

(function($) {
    "use strict";

    kintone.events.on('app.record.create.show', function(event) {
        window.alert('促发了记录添加事件');
    });

    $(function() {
        // 需要等待DOMContentLoaded的处理写在这里。
        // ...
    });
})(jQuery);

通常情况的例子

不使用jQuery时,app.record.create.show等事件句柄要在读取自定义脚本时同步执行。

不好的例子

  • 在DOMContentLoaded的事件句柄内注册app.record.create.show等事件句柄

    (function() {
        "use strict";
    
        document.addEventListener("DOMContentLoaded", function(loadedEvent) {
            kintone.events.on('app.record.create.show', function(event) {
                window.alert('促发了记录添加事件');
            });
        });
    })();
  • 在load的事件句柄内注册app.record.create.show等的事件句柄
    load事件比DOMContentLoaded更加晚被调用,因此请避免在load事件句柄内注册。

    (function() {
        "use strict";
    
        document.addEventListener("load", function(loadedEvent) {
            kintone.events.on('app.record.create.show', function(event) {
                window.alert('促发了记录添加事件');
            });
        });
    })();
  • 另外,在诸如异步请求的回调等异步处理的回调函数内异步注册

    (function() {
        "use strict";
    
        kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {app: appId}, function(result) {
            kintone.events.on('app.record.create.show', function(event) {
                window.alert('促发了记录添加事件');
            });
        });
    })();

好的例子

(function() {
    "use strict";

    kintone.events.on('app.record.create.show', function(event) {
        window.alert('促发了记录添加事件');
    });
})();

最后

以上介绍了页面显示时kintone的事件发生时机以及这些事件调用的事件句柄的合理注册时机。

就算事件句柄的注册时机晚了,并且也显示警告了,但是有时也会看起来正常执行的。
但是,如果遇到网络延迟、客户端PC的性能差或受其他的自定义脚本的影响,可能导致异步处理里的事件句柄注册发生比较大的延迟时,就会导致无法正常执行。
希望各位能参考本次内容,在开发时注意在合适的时机注册事件句柄。

本Tips在2018年7月版的 kintone中确认过。