angular 中使用原生拖拽页面卡顿,表单控件输入延迟

说明

之前有一个angular项目,页面上表单不算多,也就一百来个(这个不固定,有的地方多,有的地方少),但是再输入的时候会造成输入延迟,反应不灵敏,对用户体验极其不好。还有一个功能就是拖拽功能(原生,没有使用官方中的拖拽功能),从左边拖到右边区域,拖拽区域少的时候还挺流畅,但一旦有几百上千的时候反应极其的慢

原因(?)

上面两个问题其实都和angular的机制有关。一个双向绑定一个拖拽归根结底都是因为angular的变化检测
angular的双向绑定主要是脏数据检查,如果大量的检查,效率比较低。(双向绑定时向zone挂载一个异步函数,对数据改变是做处理,及时将变化反馈显示在页面上)可能就会输入延迟
拖拽(也是向zone挂载异步函数)则是因为angular对每个可移动像素的元素进行检测而且还可能涉及对dom的操作,当拖拽区域数量较为多时,绑定的函数就越多,angular需要检测的元素区域就越来越多,处理起来就越力不从心(即使元素隐藏也不代表不会进行变化检测)

解决

  1. 对于双向绑定造成的输入延迟,停止使用双向绑定,改用单向绑定
  2. 拖拽过程angular一直检测页面变化,所以页面卡顿。我们需要做的就是设置对某些操作不跟踪变化
this.ngZone.runOutsideAngular(() => {
        this.dragEnter = this.rd.listen(spanDom, 'dragenter', this.dragenterHandler.bind(this));
        this.dragOver = this.rd.listen(spanDom, 'dragover', (e) => {
            e.preventDefault();
        });
    this.dragLeave = this.rd.listen(spanDom, 'dragleave', this.dragLeaveHandle.bind(this));
});
this.dragDrop = this.rd.listen(spanDom, 'drop', this.dropHandler.bind(this));

对频繁的操作(如dragover)不去触发变更检测。使用NgZone中的runOutsideAngular方法,angular不会对里面的变化进行跟踪。

看到有个人抄了我这篇文章……前面是我的内容后面不知道从哪来的代码(他加了个PS的拖拽demo),两个根本不能合起来用(不能一起用,除非自己改造)。后面的demo是用的别人写好的组件,没有我上面涉及到的那么多事件。我这个写的完全是原生的JS,没有使用任何工具组件(不算使用的angular框架),只要在dom标签上加上dragable,然后监听事件。这里的这个文章虽然比那篇文章发的晚,但是我首发的是简书。(PS:我这个拖拽非常的复杂,简单的list中拖拽满足不了需求,所以才自己写的)