通过一系列的练习掌握如何分解问题、解决问题,在这个过程中如何设计自己的代码结构,如何优化及重构。
通过一个小练习综合运用 HTML、CSS、JavaScript,我们要实现一个邮箱输入的提示功能。最终示意图:
部分代码参考:
<div class="wrapper"> <input id="email-input" type="text"> <ul id="email-sug-wrapper" class="email-sug"></ul> </div>
// 邮箱后缀List参考 var postfixList = ['163.com', 'gmail.com', '126.com', 'qq.com', '263.net'];
根据下面需求实现如示意图所示的邮箱输入提示功能,注意,根据要求只需实现下面功能
从今天开始,我们希望你在写代码之前开始画流程图
推荐工具:
这个任务的总目标是用户有输入的时候,进行对应的提示,所以核心流程是:
用户输入 -> 提示框进行反馈
那核心流程进一步进行拆解,就包括了:
发现用户输入 -> 获取用户输入内容 -> 生成提示框提示内容 -> 进行提示
第一步,发现用户输入,可以利用监听用户在输入框的输入对应的事件,尝试用 keyup、keypress、keydown 以及 oninput 四个事件分别来测试对于用户输入的事件监听,并在事件响应函数中增加 console.log('event handle') 。并尝试以下输入方式,观察提示框内容变化的情况,以及 console 的输出情况:
记住试验结论,然后就上面 4 个事件进行搜索,阅读相关规范标准及技术文章。根据实验结果选择你认为合适的事件监听方式。
第一步是后面几步的起点,所以,我们可以把后面几步各自封装成一个函数,在第一步里进行调用
第二步,获取用户输入,这个比较简单,注意考虑 trim
第三步,生成提示框提示内容,根据第二步获得的内容,遍历 postfixList 数组,生成要在 email-sug-wrapper 的 UL 中填充的内容。
第四步,根据实际是否有提示内容,控制 email-sug-wrapper 的显示 / 隐藏情况
这样,这个任务被分解为 4 个步骤,你要做的就是实现这 4 个步骤的代码细节。
代码结构参考如下:
inputDom的输入监听 = function() { 获取用户输入,生成提示框中的提示内容,将提示内容添加到email-sug-wrapper中 控制email-sug-wrapper的显示/隐藏状态 } function 获取用户输入() { 拿到input输入框的输入内容trim后返回 } function 生成提示框中的提示内容() { 获取用户输入 遍历postfixList { 把用户输入和每一个postfix进行结合成为每一个Li } 返回生成的提示内容 } function 将提示内容添加到email-sug-wrapper中() { 获取生成提示框中的提示内容 将内容添加到email-sug-wrapper中 } function 控制email-sug-wrapper的显示/隐藏状态() { if 用户输入为空 { 隐藏提示框 } else { 显示提示框 } } function 隐藏提示框() { 做具体隐藏提示框的操作 } function 显示提示框() { 做具体显示提示框的操作 }
测试用例的阅读方式:描述中间有一个 -> 符号,-> 前面的内容表示请你这么操作来测试,-> 后面的内容表示应该出现的结果
如果我们输入的是 abc@1 ,这个时候出现的提示框内容是
abc@1@163.com
abc@1@gmail.com
abc@1@126.com …… 很明显,上面的提示框不是一个符合用户需求的提示,我们需要做一些优化:
当用户输入含有 @ 符号时,我们选取用户输入的@前面的字符来和后缀拼接
同样有经验的同学请跳过,零基础同学和我一起
上面的需求,在我们上一步的结构中,需要在“生成提示框中的提示内容”这个函数中进行调整
我们把需求解读一下,关键在于判断用户输入有没有 @,那如何判断字符串中是否包含某个字符呢?可以回顾一下字符串相关的内容。
在发现有 @ 之后,要做的就是拿到 @ 符号之前的字符串内容,来和 postfixList 进行拼接。
代码结构:
function 生成提示框中的提示内容() { 用来拼接的用户输入内容 = 获取用户输入 if 用户输入含有@ { 用来拼接的用户输入内容 = 只使用@之前的字符串 } 遍历postfixList { 把用来拼接的用户输入内容和每一个postfix进行结合成为每一个Li } 返回生成的提示内容 }
这下出现的提示好多了,不过用户如果已经输入了 @1 ,说明他大概率要输入 163 或者 126 ,我们需要让我们的提示更加符合用户的期望。满足以下需求:
这个需求依然需要调整“生成提示框中的提示内容”,如果用户输入的字符含有 @ ,我们需要拿到 @ 之后的字符串,来和 postfixList 中每个字符串做前缀匹配,符合要求的我们才会使用
代码结构
function 生成提示框中的提示内容() { 用来拼接的用户输入内容 = 获取用户输入 if 用户输入含有@ { 用来拼接的用户输入内容 = @之前的字符串 用来前缀匹配的用户输入内容 = @之后的字符串 } 遍历postfixList { if 用来前缀匹配的用户输入内容前缀匹配遍历字符串元素 把用来拼接的用户输入内容和这个字符串进行结合成为一个Li } 返回生成的提示内容 }
上面我们只完成了提示,但提示还没有直接作用到选择中,我们现在完成以下需求:
鼠标点击,是一个新的用户输入,所以我们需要有一个新的事件监听,那用哪一个 DOM 节点来监听这个鼠标事件呢?想一想前面提到的事件代理,选择一个合适的事件监听方式。
当监听到用户点击某一个提示的 Li 后,我们需要做的就是,把 Li 对应的提示内容,放在输入框中,同时隐藏提示框
代码结构
选择一个合适的DOM节点.监听鼠标点击 = function () { if 被点击的是不是提示框中的Li节点 { 获取被点击Li对应的提示内容 将内容放到input输入框中 隐藏输入框 } }
尝试在输入框中输入<b>,看看提示框发生了什么
我们需要在两个地方进行处理,一个是在生成提示内容那里,对于特殊字符进行转义编码,另一个是在把鼠标点击的提示框内容转回输入框时进行解码。
我们给提示框加上 3 个按键的功能,分别是回车和上下键,使得可以通过键盘操作进行提示框的选择
整体任务核心流程为:
监听键盘事件 -> 判断按键 -> 如果是上下键则变更选中状态,如果是回车键则进行内容进输入框操作
监听键盘事件及判断按键:我们需要在键盘监听中,增加对于这 3 个键的特殊处理。回忆一下之前的实验,keydown,keypress,keyup,oninput,对于这 3 个键的监听是和之前的合并,还是另外处理,不妨实验一下。
如果是上下键则变更选中状态:这里的关键在于,我们如何记录选中状态,以及如何改变。对于零基础的同学,在不基于任何框架的情况下,我们介绍两种基本思路:
// 需要修改一下之前的inputDom的输入监听 inputDom的输入监听 = function() { // 新增 如果按键不是上下及回车重置选中状态() 获取用户输入,生成提示框中的提示内容,将提示内容添加到email-sug-wrapper中 控制email-sug-wrapper的显示/隐藏状态 } function 重置选中状态() { 找到当前为选中状态的Li if (当前选中状态Li不是第一个) { 清除掉它的选中状态 设置第一个Li为选中状态 } } // 监听特殊3个键的键盘事件,这个事件可能就是inputDom的输入监听,也有可能是另外一个,请自己测试后判断 监听特殊3个键的键盘事件 = function() { 找到当前为选中状态的Li 清除掉它的选中状态 if 按的是上键 { if 找到的Li不是第一个 { 将它的前一个Li设为选中 } else { 将最后一个Li设为选中 } } if 按的是下键 { if 找到的Li不是最后一个 { 将它的下一个Li设为选中 } else { 将第一个Li设为选中 } } if 按的是回车 { 将找到的Li的HTML内容解码后填到input中 隐藏提示框 } }
// 增加一个变量,用于存储当前选中的提示Li的序号 var nowSelectTipIndex = 0; // 需要修改一下之前的“生成提示框中的提示内容()” function 生成提示框中的提示内容() { 获取用户输入 遍历postfixList { 把用户输入和每一个postfix进行结合成为每一个Li } // 新增 将第nowSelectTipIndex个Li的样式设置为被选样式 返回生成的提示内容 } function 将提示内容添加到email-sug-wrapper中() { 获取生成提示框中的提示内容 将内容添加到email-sug-wrapper中 } // 需要修改一下之前的inputDom的输入监听 inputDom的输入监听 = function() { // 新增 如果按键不是上下及回车重置选中状态() 获取用户输入,生成提示框中的提示内容,将提示内容添加到email-sug-wrapper中 控制email-sug-wrapper的显示/隐藏状态 } function 重置选中状态() { 将 nowSelectTipIndex 设为0 } // 监听特殊3个键的键盘事件,这个事件可能就是inputDom的输入监听,也有可能是另外一个,请自己测试后判断 监听特殊3个键的键盘事件 = function() { if 按的是上键 { if nowSelectTipIndex不是第一个 { nowSelectTipIndex设置为当前提示框的Li的个数 - 1 } else { nowSelectTipIndex - 1 } } if 按的是下键 { if nowSelectTipIndex小于Li的最大索引 { nowSelectTipIndex设置为 0 } else { nowSelectTipIndex + 1 } } if 按的是回车 { 从当前提示框中选第 nowSelectTipIndex 个Li,将其HTML内容解码后填到input中 隐藏提示框 } }
介绍完两种思路后,请你用两种思路都实现一遍,我们更加鼓励基于数据的思路,这样可以方便我们把用户界面、交互和数据业务逻辑进行解耦。当然上面的数据思路中,我们可以做得更加彻底一些,哪里还可以优化呢?这就是留给大家的作业。
当我们进入页面,或者当我们点击鼠标进行提示选择后,输入框的焦点就不在了,所以请你优化一下用户体验:
将这次任务最后实现的代码进行提交。
把今天的学习用时,收获,问题进行记录。
更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。
长按或扫描下方二维码,免费获取 Python公开课和大佬打包整理的几百G的学习资料,内容包含但不限于Python电子书、教程、项目接单、源码等等
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!