百度前端 第二十八天到三十天

今日開始學習写代码之前开始画流程图

目標:
建立一個純js搜索提示框

  • 当用户没有任何输入时,提示框消失
  • 当用户输入字符后,显示提示框,并且把用户输入的内容自动拼上邮箱后缀进行显示
  • 注意用户输入中前后空格需要去除

心得:
整體的思路並不難,需要花時間的地方是如何將需求包裝成個別的函數。

首先整個的事件會跟input有關所以在每次輸入時調用函數

  		var input = document.querySelector('#email-input')
        var ul = document.querySelector('#email-sug-wrapper')
        var postfixList = ['163.com', 'gmail.com', '126.com', 'qq.com', '263.net'];

  input.addEventListener('input', function (e) {
            addPrompt()
            display()
            selected()
            eventAdd()
        })

獲取用戶的輸入,並將每次用戶輸入的前後空白刪除(trim),再將結果返回,這裡也可以封裝成一個函數,每次調用時就會獲取其結果

    function getInput() {
            //拿到input输入框的输入内容trim后返回
            var input1 = input.value;
            return input1.trim();
        }

封裝一個讓提示框顯示或隱藏的函數,因為在之後我們需要反覆調用提示框的顯示和隱藏
先獲取用戶輸入的的內容並去掉前後的空白格的

 function show() {
            ul.style.display = 'block'

        }
        function hide() {
            ul.style.display = 'none'
        }

再來定義提示框什麼時候出現與隱藏 先獲取用戶輸入的內容並且將其內容去掉前後空格的值(trim),再來判斷如果其值為空,則表示用戶沒有輸入,此時提示框隱藏,若相反,則表示用戶在輸入,讓其提示框顯示

  function display() {
            var out = getInput()
            if (out === '') {
                hide();
            } else {
                show();
                ul.children[0].classList.add('active')
            }
        }

最後在遍歷已提供的數組值(儲存著信箱後綴)
在每次遍歷都把後綴的值和用戶輸入的值拼接
在這裡,因為有多個值,所以建立個數組,將數值存入數組
最後將其值顯示在提示框裡。

  function setPrompt() {
            var input1 = getInput()
            var res = []
            for (var i = 0; i < postfixList.length; i++) {
                    res[res.length] = input1 + '@' + postfixList[i]
                }
            }
            return res
        }
         function addPrompt() {
            /* 获取用户输入
             遍历postfixList {
                 把用户输入和每一个postfix进行结合成为每一个Li
             }
             返回生成的提示内容*/
            var result = setPrompt()
            var len = ul.childNodes.length;
            for (var i = len - 1; i >= 0; i--) {
                ul.removeChild(ul.childNodes[i]);
            }
            for (var i = 0; i < result.length; i++) {
                ul.appendChild.innerHTML = ''
                var li = document.createElement('li')
                li.innerHTML = result[i]
                ul.appendChild(li)
            }
        }

優化1

此時大部分架構已經出來,但仍有很多地方可以優化。
如果我们输入的是 abc@1,这个时候出现的提示框内容是
abc@1@163.com
abc@1@gmail.com
abc@1@126.com

很明显,上面的提示框不是一个符合用户需求的提示,我们需要做一些优化:

  • 当用户输入含有 @ 符号时,我们选取用户输入的@前面的字符来和后缀拼接

這個問題很簡單只要用if加入條件,如果數入值裡有@那就擷取@以前的數值

  function setPrompt() {
            var input1 = getInput()
            var input2;
            var res = []
            if(input.indexOf('@')===-1){
              input2 = input1.slice(0, input1.indexOf('@');
            }else{
            	input2=input1;
            }
            for (var i = 0; i < postfixList.length; i++) {
                    res[res.length] = input2+ '@' + postfixList[i]
                }
            }
            return res
        }

不过用户如果已经输入了@1,说明他大概率要输入163或者126,我们需要让我们的提示更加符合用户的期望。满足以下需求:

  • 当用户输入了 @ 及部分后缀时,只从 postfixList 选取符合用户输入预期的后缀,我们以前缀匹配为要求。
  • 当用户输入不满足任何前缀匹配时,则显示全部提示

當用戶輸入的值含有@時,將@前的值保存在input2變量裡,將@後的值保存在input3裡,若不含@則將值input2=input1
然後再次循環後綴並判斷是否和input3相同,若有則將input2和相同的後綴拼接起來,並顯示
若否,input2則和所有後綴拼接,並顯示。
這裡用到了閥流夾,一般情況下flag為0,如果當後綴和input3匹配到的話,則flag為1,這樣只會輸出匹配到的後綴,如果沒有匹配到則flag仍然為0並輸出所有後綴!

function setPrompt() {
            var flag = 0
            var input1 = getInput()
            var input2;
            var input3;
            if (input1.indexOf('@') === -1) {
                input2 = input1
            } else {
                input2 = input1.slice(0, input1.indexOf('@'))
                input3 = input1.slice(input1.indexOf('@') + 1)
            }
            var res = []
            for (var i = 0; i < postfixList.length; i++) {
                if (postfixList[i].indexOf(input3) === 0) {
                    res[res.length] = input2 + '@' + postfixList[i]
                    flag = 1;
                }
            }
            if (flag === 0) {
                for (var i = 0; i < postfixList.length; i++) {
                    res[res.length] = input2 + '@' + postfixList[i];
                }
            }
            return res
        }

最後剩下用戶點擊和按下enter的互動優化,需求為:

  • 使用CSS实现:鼠标滑过提示框的某一个提示时,这个提示内容背景色变化,表示鼠标经过了这个DOM节点
  • 鼠标如果点击某个提示,则提示内容进入输入框,同时提示框消失 在上个步骤结束后,
  • 在输入框中任意再输入字符或删除字符,则重新开始出现提示框
  function selected() {
            /*if 被点击的是不是提示框中的Li节点 {
                获取被点击Li对应的提示内容
                将内容放到input输入框中
                隐藏输入框*/
            ul.onclick = function (e) {
                var ev = e || window.event;
                var target = ev.target || ev.srcElement;
                if (target.nodeName.toUpperCase() == 'LI') {
                    input.value = target.innerText;
                    hide();
                }
            }

        }

加上键盘
需求
我们给提示框加上3个按键的功能,分别是回车和上下键,使得可以通过键盘操作进行提示框的选择

  • 当有提示框的时候,默认第一个提示为被选择状态,用一个和鼠标滑过不一样的背景色来标识
  • 当有输入框的时候,按上键,可以向上移动选择状态,如果按键之前的被选择提示是第一个,则被选状态移到最下面一个
  • 当有输入框的时候,按下键,可以向下移动选择状态,如果按键之前的被选择提示是最后一个,则被选状态移到第一个
  • 当有输入框时,按回车键,则将当前被选中状态的提示内容,放到输入框中,并隐藏提示框 当没有输入框的时候,这3个键盘按键无响应
  • 当用户输入发生改变的时候,选择状态都重新切回到第一个提示

這裡的思路有兩種方法,一種是基於dom另外一種則是,我選擇的,基於數據方式。
先設定一個index,如果觸發了下鍵,則 :

  1. index++,並且清除上一個的active
  2. 判斷index是否等於0,如果等於0則讓列表內第一個active
  3. 判斷index是否等於最後一個(index === lis.length),如果index在最後一個又按下了下鍵表示index要回到第一個,並讓index=0
  4. 如果既不是第一個也不是最後一個的狀態下,直接將index賦值即可
    ( lis[index].classList.add(‘active’))

如果觸發了上鍵,則 :

  1. 先清除 ’ 當前的index’,然後再來判斷index

  2. 如果判斷index等於0,則讓列表最後一個active(lis.length - 1),並且讓index的值變成列表值最後一個( index = lis.length; index–),最後index

 function eventAdd() {
            var index = 0;
            var lisLi = null;
            window.addEventListener("keyup", function (event) {
                console.log(event.code);

                var lis = ul.children
                if (event.defaultPrevented) {
                    return; // Do nothing if event already handled
                }

                if (event.code === 'ArrowDown') {
                    index++;
                    lis[index - 1].classList.remove('active')
                    if (index === 0) {
                        lis[0].classList.add('active')

                    } else if (index === lis.length) {
                        lis[0].classList.add('active')
                        index = 0;

                    } else {
                        lis[index].classList.add('active')

                    }
                }
                if (event.code === 'ArrowUp') {

                    lis[index].classList.remove('active')
                    if (index === 0) {
                        lis[lis.length - 1].classList.add('active')
                        index = lis.length;
                        index--
                    } else {
                        lis[index - 1].classList.add('active')
                        index--
                    }
                }
                if (event.code === "Enter") {
                    input.value = lis[index].innerText;
                    hide();
                }
                if (event.code === 'Escape') input.select()
                input.addEventListener("dblclick", function () {
                    input.select()
                });


            })
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值