资讯专栏INFORMATION COLUMN

实现一个 suggest-input 控件

lykops / 2013人阅读

摘要:最近公司碰到一个需求,基于开发一个通用的带建议的控件忙乱中写出了一个通用结构和方法,跟大家分享一下,同时也算做自己的踩坑总结吧。如果不解绑,会导致你改变其中一个的值,其它都改变因为你初始化的时候,为每一个都绑定了事件。

最近公司碰到一个需求,基于jq 开发一个通用的 带建议 的input 控件;

忙乱中写出了一个通用结构和方法,跟大家分享一下,同时也算做自己的踩坑总结吧。

通用一个模板,不影响原有 input 所在结构;

因为原来的表单中 已经有固定结构的 input 了; 所以不能改html结构;

大概的思路就是,定义一个option 包裹层;然后点击需要带建议的input的时候,去根据自定义属性 suggest-url 拿到对应接口,取数据回来遍历出选项。然后根据 这个input 的top,left 做绝对定位显示出来。

</>复制代码

  1. //以下是固有的 form input 结构
  2. 单位
  3. (默认)
  4. //随意放一个包裹层

    逐步分解 实现步骤 希望只调用一个函数实现功能

    全局 有 suggest-input 类 的input 都实现option 功能;

    </>复制代码

    1. function initEvent() {
    2. suggestInput();
    3. })
    函数实现与解析 如下:

    </>复制代码

    1. function suggestInput() {
    2. //在input focus 的时候做处理。
    3. $(".suggest-input").focus(function () {
    4. //获取相关 接口的值
    5. var url = $(this).attr("suggest-url");
    6. //缓存操作对象
    7. var $input = $(this);
    8. var $suggest = $(".suggest-option");
    9. var $ul = $suggest.find("ul");
    10. //通过input 找到 option 应该显示的top 和left
    11. var top = $input.offset().top + $input.outerHeight()+5;
    12. var left = $input.offset().left;
    13. var width = $input.outerWidth();
    14. //如下是基于 url 的ajax请求,此处暂时用静态数据
    15. /*doAjaxPost(url,"",function (resp) {
    16. if(resp.status==1){
    17. var dataObj = resp.data;
    18. $ul.html("");
    19. dataObj.forEach(function (p1) {
    20. $ul.append("
    21. "+p1.title+"
    22. ");
    23. });
    24. }else {
    25. $ul.append("
    26. 暂无数据
    27. ")
    28. return;
    29. }
    30. });*/
    31. var dataObj = [{id:1,title:""},{id:1,title:""},{id:1,title:""}];
    32. //先清空 ul;
    33. $ul.html("");
    34. //遍历产生 option
    35. dataObj.forEach(function (p1) {
    36. $ul.append("
    37. "+p1.title+"
    38. ");
    39. });
    40. //设置 option框 应该显示的位置
    41. $suggest.css({
    42. top:top,
    43. left:left,
    44. width:width
    45. }).show();
    46. //找到发生滚动事件的 包裹层,定制滚动时的处理
    47. $input.parents().each(function (i,o) {
    48. if($(o).css("overflow-y")=="auto"){
    49. return $(o);
    50. }
    51. }).scroll(function () {
    52. $suggest.css({
    53. top:$input.offset().top + $input.outerHeight()+5,
    54. })
    55. });
    56. //点击消失相关操作
    57. $input.click(function (e) {
    58. e.stopPropagation();
    59. })
    60. $("body").click(function () {
    61. $suggest.hide();
    62. })
    63. //选中option 时回填数据
    64. $suggest.find("li").unbind("click").click(function (e) {
    65. $input.val($(this).text());
    66. $suggest.hide();
    67. e.stopPropagation();
    68. })
    69. })
    70. }

    效果如下:

    遇到的坑

    整个代码逻辑下来 其实并不难理解,但是有两个需要注意到的地方;

    每次为点击li绑定事件的时候,应该先解除之前绑定的相同事件。

    </>复制代码

    1. $suggest.find("li").unbind("click").click(function (e) {
    2. })

    如果不解绑,会导致你改变 其中一个 input 的值,其它input都改变; 因为你初始化的时候,为每一个li 都绑定了click 事件。

    当表单出现滚动的时候,option 框没有跟着 移动;

    </>复制代码

    1. $input.parents().each(function (i,o) {
    2. if($(o).css("overflow-y")=="auto"){
    3. return $(o);
    4. }
    5. }).scroll(function () {
    6. $suggest.css({
    7. top:$input.offset().top + $input.outerHeight()+5,
    8. })
    9. });

    解决办法就是 检查 发生滚动的box ;发生滚动的时候,重新计算一次 option 的 top;

    不过如果手动绑定 scroll 监听,会容易有两个问题。一,可能发生滚动的 box 不是你监听的box; 二,即使你知道发生滚动的div,如果直接写死的话,发生结构变化时,代码不够通用。

    因为我通过遍历 input 的父子集,找到最近一个 overflow-y:auto 的父box;这就是发生滚动的父box。
    然后绑定事件。
    最后效果:

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/93963.html

    相关文章

    • Flutter交互实战-即刻App探索页下拉&拖拽效果

      摘要:前言最近比较热门,但是成体系的文章并不多,前期避免不了踩坑我这篇文章主要介绍如何使用实现一个比较复杂的手势交互,顺便分享一下我在使用过程中遇到的一些小坑,减少大家入坑作者链接先睹为快本项目支持运行,效果如下对了,顺便分享一下生成的小窍门,建 前言 Flutter最近比较热门,但是Flutter成体系的文章并不多,前期避免不了踩坑;我这篇文章主要介绍如何使用Flutter实现一个比较复杂...

      miracledan 评论0 收藏0

    发表评论

    0条评论

    最新活动
    阅读需要支付1元查看
    <