背景:html
製做一個相似百度輸入法的智能提示框,node
其中當關鍵詞輸入進來時,會有智能提示展開,實際需求是當點擊智能提示框的漢字時,輸入框中自動補全並關閉智能提示,app
當點擊其餘區域時,智能提示框自動隱藏,以下所示:this
分析:點擊用onclick事件觸發獲取的值,而後點擊外框用失去焦點的方式解決spa
但實際出現效果是:指針
若是添加了失去焦點的方法,點擊提示文本的時候,文字也會由於輸入框失去焦點而被隱藏,以致於文字沒法被選中上去:code
問題出現時用方法以下:htm
//oA是智能提示框的列表中的單個文字 oA.onclick = function(){ populateModel(this) }; // 點擊提示文本,獲取文本並填充到輸入款中(wd是輸入框) function populateModel(cell) { wd.value = cell.firstChild.nodeValue; clearModels();//清除自動完成行 } //填充後清除提示 function clearModels() { while (oUl.childNodes.length > 0) { oUl.removeChild(oUl.firstChild); } oLi.style.border = "none"; } // 失去焦點隱藏 其中輸入框中有屬性:onblur="upperCase()",其中oUI 是智能提示的區域 function upperCase() { oUl.style.display = 'none'; }
解決方案: 這裏不得不先講下鼠標點擊事件對象
屬性 | 描述 | DOM |
---|---|---|
onclick | 當用戶點擊某個對象時調用的事件句柄。 | 2 |
oncontextmenu | 在用戶點擊鼠標右鍵打開上下文菜單時觸發 | |
ondblclick | 當用戶雙擊某個對象時調用的事件句柄。 | 2 |
onmousedown | 鼠標按鈕被按下。 | 2 |
onmouseenter | 當鼠標指針移動到元素上時觸發。 | 2 |
onmouseleave | 當鼠標指針移出元素時觸發 | 2 |
onmousemove | 鼠標被移動。 | 2 |
onmouseover | 鼠標移到某元素之上。 | 2 |
onmouseout | 鼠標從某元素移開。 | 2 |
onmouseup | 鼠標按鍵被鬆開。 |
鼠標點擊點擊過程是先按下鼠標(mousedown)而後彈起來(mouseup),這一過程才觸發了click事件,當click觸發以前,也就是mouseup時,blur已經先觸發失去焦點,blog
所以,當你點擊提示框文字時,並無觸發到click事件而是由於失去了焦點而提示框提早被隱藏掉了;
因此綜上分析,解決方法有兩種
1 將文字被選中這一事件用mousedown來監聽,當鼠標按下時,就將文字先選中,而後彈起來時再自動觸發onblur事件隱藏提示框中內容:
代碼以下:
oA.onmousedown = function(){ populateModel(this) };//修改了onclick改成onmousedown,其餘均不變;
2另外一種方式就是,不用失去焦點的方式來隱藏DOM,而是用鼠標移出提示框區域時,觸發mouseseleave事件來隱藏DOM
代碼以下:
oA.onclick = function(){ populateModel(this) };//仍然使用onclick事件觸發文字獲取 oUl.onmouseleave = function(){ oUl.style.display = 'none'; }// 當鼠標移除提示框以外後,自動隱藏
完整的百度智能輸入法提示的JS代碼:
<script> var wd = document.getElementById('wd'); var oUl = document.getElementById('list'); wd.oninput = debounce(getUserAction, 100, false); function debounce(func, wait, immediate) { var timer = null; var result; var debounced = function () { var _this = this; var argu = arguments; clearTimeout(timer); if (immediate) { if (!timer) func.apply(_this, argu); timer = setTimeout(function () { timer = null; }, wait) } else { timer = setTimeout(function () { func.apply(_this, argu); }, wait) } return result; } debounced.cancel = function () { clearTimeout(timer); timer = null; } return debounced; } function getUserAction() { if (wd.value) { var oScript = document.createElement('script'); oScript.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=' + wd.value + '&cb=doJson'; document.body.appendChild(oScript); document.body.removeChild(oScript); } else { oUl.style.display = 'none'; } } function doJson(data) { var dataList = data.s; oUl.innerHTML = ''; if (dataList.length == 0) { oUl.style.display = 'none'; } else { dataList.forEach(function (item, index) { var oLi = document.createElement('li'); var oA = document.createElement('a'); oA.onmousedown = function(){ populateModel(this) };//單擊oA是的方法爲populateModel // oA.onclick = function(){ populateModel(this) };//單擊oA是的方法爲populateModel // oUl.onmouseleave = function(){ oUl.style.display = 'none'; } oA.innerText = item; oLi.appendChild(oA); oUl.appendChild(oLi); oUl.style.display = 'block'; }) } } function populateModel(cell) { wd.value = cell.firstChild.nodeValue; clearModels();//清除自動完成行 } function clearModels() { while (oUl.childNodes.length > 0) { oUl.removeChild(oUl.firstChild); } oLi.style.border = "none"; } // 失去焦點隱藏 function upperCase() { oUl.style.display = 'none'; } </script>