双向绑定不更新问题

前几天发现数据编辑后台的双向绑定不生效了。看了下源码,已经近1年多没有commit记录,那怎么就突然不能使用了呢?


compositionstart & compositionend

这里就要从compositionstart & compositionend开始说起,这两个事件一般用于中文输入法的优化,比如常用的下面几行代码:

var node = document.querySelector('input');
var cpLock = false;
node.addEventListener('compositionstart', function(){
    cpLock = true;
})
node.addEventListener('compositionend', function(){
    cpLock = false;
})
node.addEventListener('input', function(){
    if(!cpLock)console.log(this.value);
});

compositionstart:当浏览器有非直接的文字输入时, compositionstart事件会以同步模式触发。

compositionend:当浏览器是直接的文字输入时, compositionend会以同步模式触发。

通过这个DEMO输入中文感受下:

双向绑定不更新

经过排查发现,是inputcompositionend回调的前后顺序改变了。

我用新版Chrome测试的: chrome 我用Safari/老版Chrome测试的: safari

我依次输入的是n-i-h-a-o-Enter,可以对比出,最后一次input回调和compositionend回调的先后顺序在不同浏览器的表现不同。以前Chrome版本和Safari都是compositionend回调在input之前,Chrome新版变成了compositionend回调在input之后。代码里的cpLock还是锁住的,就不会更新数据。

因此,可以得出结论:浏览器改变了默认事件


解决办法

node.addEventListener('input', function(){
    if(!cpLock)console.log(this.value);
});

这段代码可以对compositionend也做一次:

node.addEventListener('input', function(){
    if(!cpLock)console.log(this.value);
});
node.addEventListener('compositionend', function(){
    if(!cpLock)console.log(this.value);
});

如果担心性能不好,多做了一次操作。可以对浏览器进行判断,或者其它更好的方案。

麻凯倩

微信:makaiqian