-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 79 题:input 搜索如何防抖,如何处理中文输入 #129
Comments
这个在复制粘贴中文内容的时候不会触发事件 |
有一个onpaste 事件 |
简易防抖
|
参考vue源码对v-model的实现中,对输入中文的处理 <input id='myinput'> function jeiliu(timeout){
var timer;
function input(e){
if(e.target.composing){
return ;
}
if(timer){
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log(e.target.value);
timer = null;
}, timeout);
}
return input;
}
function onCompositionStart(e){
e.target.composing = true;
}
function onCompositionEnd(e){
//console.log(e.target)
e.target.composing = false;
var event = document.createEvent('HTMLEvents');
event.initEvent('input');
e.target.dispatchEvent(event);
}
var input_dom = document.getElementById('myinput');
input_dom.addEventListener('input',jeiliu(1000));
input_dom.addEventListener('compositionstart',onCompositionStart);
input_dom.addEventListener('compositionend',onCompositionEnd); |
'jieliu',拼音没有那么棒棒hhh |
我看怎么像节流 |
你这不对哦,不是防抖 function debounce(fn, wait) {
var timer = null;
return function () {
var context = this
var args = arguments
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
fn.apply(context, args)
}, wait)
}
}
var fn = function () {
console.log('boom')
}
setInterval(debounce(fn,500),1000) // 第一次在1500ms后触发,之后每1000ms触发一次
setInterval(debounce(fn,2000),1000) // 不会触发一次(我把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条) |
我怎么感觉你们两个没什么区别? |
vue版本:
|
哈哈哈 就是没区别 |
function debounce(func,wait,immediate){
} |
// input 搜索如何防抖,如何处理中文输入
// 事件触发后,n秒后再执行回调
const ipt = document.querySelector(".input");
/**
* @param {fn} 需要防抖的函数
* @param {time} 防抖的时间
* */
function debounce(fn, time) {
let timer = 0;
return function (args) {
clearInterval(timer);
timer = setTimeout(function () {
fn.call(this, args);
}, time);
};
}
function ajax(val) {
console.log("val", val);
}
const test = debounce(ajax, 1500);
ipt.addEventListener("keyup", (e) => {
test(e.target.value);
}); |
贴个完整的 <html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" id="spell_input" />
<script>
function throttle(fn, delay) {
let timer;
let isFirstCall = true;
return function (...args) {
const ctx = this;
if (isFirstCall) {
isFirstCall = false;
fn.apply(ctx, args);
return;
}
if (timer) return;
timer = setTimeout(() => {
timer = null;
fn.apply(ctx, args);
}, delay);
};
}
function input(e) {
if (e.target.composing) {
return;
}
console.log(e.target.value);
}
function onCompositionStart(e) {
e.target.composing = true;
}
function onCompositionEnd(e) {
const event = new CustomEvent("input");
e.target.composing = false;
e.target.dispatchEvent(event);
}
function onCompositionUpdate(e) {
console.log(e.target.value);
}
const inputEle = document.getElementById("spell_input");
inputEle.addEventListener("input", throttle(input, 1000));
inputEle.addEventListener("compositionstart", onCompositionStart);
inputEle.addEventListener("compositionend", onCompositionEnd);
inputEle.addEventListener("compositionupdate", onCompositionUpdate);
</script>
</body>
</html> |
throttle这个是节流 |
防抖function debounce(fn, delay) {
let timer
return function() {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, arguments)
}, delay)
}
} |
function debounce(fn, delay) {
let timer = null;
return function(...args) {
const ctx = this;
if (timer) {
clearTimeout(timer);
} else {
timer = setTimeout(()=>{
fn.bind(ctx, ...args);
}
, delay);
}
}
}
const handlerChange=(ev)=>{console.log(ev.target.value)}
const handlerDebChange=debounce(handlerChange,1e3);
<input onChange={handlerDebChange} />
|
防抖就不说了,主要是这里提到的中文输入问题,其实看过elementui框架源码的童鞋都应该知道,elementui是通过compositionstart & compositionend做的中文输入处理:
相关代码:
<input
ref="input"
@compositionstart="handleComposition"
@compositionupdate="handleComposition"
@compositionend="handleComposition"
>
这3个方法是原生的方法,这里简单介绍下,官方定义如下compositionstart 事件触发于一段文字的输入之前(类似于 keydown 事件,但是该事件仅在若干可见字符的输入之前,而这些可见字符的输入可能需要一连串的键盘操作、语音识别或者点击输入法的备选词)
简单来说就是切换中文输入法时在打拼音时(此时input内还没有填入真正的内容),会首先触发compositionstart,然后每打一个拼音字母,触发compositionupdate,最后将输入好的中文填入input中时触发compositionend。触发compositionstart时,文本框会填入 “虚拟文本”(待确认文本),同时触发input事件;在触发compositionend时,就是填入实际内容后(已确认文本),所以这里如果不想触发input事件的话就得设置一个bool变量来控制。
根据上图可以看到
输入到input框触发input事件
失去焦点后内容有改变触发change事件
识别到你开始使用中文输入法触发**compositionstart 事件
未输入结束但还在输入中触发compositionupdate **事件
输入完成(也就是我们回车或者选择了对应的文字插入到输入框的时刻)触发compositionend事件。
那么问题来了 使用这几个事件能做什么?
因为input组件常常跟form表单一起出现,需要做表单验证
为了解决中文输入法输入内容时还没将中文插入到输入框就验证的问题
我们希望中文输入完成以后才验证
The text was updated successfully, but these errors were encountered: