关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

头部布局搜索验证和AJAX自动搜索提示并封装成组件提高代码复用性

发布时间:2020-02-24 00:00:00

index.html 头部区结构和样式

效果图

 

 静态样式

index.html中的部分

     头部 --><div class="header"><div class="container"> h1标签是为了搜索引擎优化,表示重要
            但是页面内不要出现太多 --><h1 class="fl"><a href="#" class="header-logo text-hidden">慕淘网a>h1><div class="search fl"> 由于没有自己的搜索页,演示时设置为提交到淘宝,参考淘宝设置 --><form action="https://s.taobao.com/search"> 由于input是内联块,相当于display:inline-block
                    如果换行写,会造成空隙,空隙大小一般是默认字体的一半
                    可以不换行书写,但是可读性较差
                    都添加左浮动可以解决 --> 设置name才能提交 --><input type="text" class="search-input fl" name="q" placeholder="灵魂美食一元抢" autocomplete="off"><input type="submit" value="搜索" class="search-btn fl">form><ul class="search-list"><li class="search-item text-ellipsis" title="111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111">111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111li><li class="search-item text-ellipsis" title="222">222li><li class="search-item text-ellipsis" title="333">333li>ul>div><div class="header-cart fr">div>div>div>

common.css中新增搜索框组件公共样式

/*搜索框组件 search*/.search{position: relative;width:679px;border:1px solid #cfd2d5;
}.search-input{width:586px;height:40px;line-height:40px;background-color:#fff;border:none;padding:0 10px;
}.search-btn{width:73px;height:40px;background-color:#07111b;color:#fff;line-height:40px;text-align: center;cursor:pointer;border:none;
}.search-list{display: none;background-color:#fff;position: absolute;width:586px;top:100%;/*父容器的高度*/left:-1px;border:1px solid #cfd2d5;padding:0 10px;

}.search-item{height:24px;line-height:24px;
}

index.css中新增header中独有的样式

/*header*/.header{height:124px;background-color: #f3f5f7;
}.header-logo{display: block;background:url(../img/header-logo.png) no-repeat;width:136px;height:48px;margin-top:36px;margin-left:15px;
}.header .search{margin-top:36px;margin-left:144px;
}

引入search.js文件

这里补充下几个文本框事件的触发条件的区别:

change  文本框内容改变 + blur

keypress  按键触发,如果鼠标不抬起连续按键,则连续触发

keyup 按键释放触发,不管按什么键(包括上下箭头等无文字意义符号),而且鼠标粘贴过来的文本无法触发

input 文本输入,跟change的区别是不需要 blur 即可触发;鼠标粘贴也可触发(兼容性不好:IE8以下不支持)

综上所述,最理想的选择是 input,但有时为了兼容性,只能选择 keyup,并可以自己做一些约束改造


 

查看淘宝搜索的form表单提交action

//s.taobao.com/search

自己在表单使用时参考淘宝需要在前面加上https:协议

即:https://s.taobao.com/search

 

 

查看淘宝搜索输入框的name属性

name="q"

 

 

查看淘宝提交时ajax请求的url地址

1、打开网址,打开控制台,找到network,点击下面的JS

2、可以先用绿色框的那个按钮将下面的内容清空一下,然后在输入框中写内容,下面Name的地方就会出来信息

3、点击任意一个进去,就会出现右侧的Headers,里面的Request URL粘贴复制在浏览器地址栏中就可以看到了。

 

 

 

 

 

 


 

添加搜索验证和获取数据功能:

search.js

(function($){"use strict";//验证var search=$(".search"),
        searchInput=search.find(".search-input"),
        searchBtn=search.find(".search-btn"),
        searchList=search.find(".search-list");

    searchBtn.on("click",function(){//submit按钮默认行为是提交表单,return false可以阻止默认行为//$.trim() 去掉字符串两边的空格,阻止无内容提交if($.trim(searchInput.val())==="") return false;

    });//自动完成searchInput.on("input",function(){var url = 'https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q='
         + encodeURIComponent($.trim(searchInput.val()));

        $.ajax({
            url:url,
            dataType:"jsonp",//jsonp用于跨域success:function(data){
                console.log(data);
            },
            error:function(data){
                console.log(error);
            }
        });

    });

})(jQuery)

由于jQuery.ajax返回的是jqXHR对象,它是浏览器原生XMLHttpRequest对象的一个超集,为了让回调函数名字统一,便于$.ajax中使用,jqXHR提供了.error(),.success(),.complete()

由于版本升级,才有了相应的.fail(),.done(),.always()三个方法

使用done(), fail(), always()是 为了避免代码嵌套在ajax里面,方便阅读

因此$.ajax写法可以做如下修改,异步避免回调:

        // 异步避免回调        $.ajax({
            url:url,
            timeout:1,//失败常见原因是超时,这里为了演示,将超时设置为1毫秒dataType:"jsonp"}).done(function(data){//成功执行            console.log(data);
        }).fail(function(){//失败执行console.log("fail");
        }).always(function(){//总是执行console.log("always");
        });

 失败有很多种原因,其中超时是一个很常见的原因

为了演示超时,设置timeout:1 (1毫秒)

 

 $.trim(searchInput.val()) 这边默认是使用的utf-8编码

如果在页面为其他编码格式,如:gbk 时,可能会因为编码问题造成读取数据失败

因此使用 encodeURIComponent( ) 来解决编码问题

1、encodeURIComponent(URIstring ) 函数可把字符串作为 URI 组件进行编码,返回值是URIstring 的副本,其中的某些字符将被十六进制的转义序列进行替换。简单来说作用就是进行编码,能够被后台识别,后台开发语言都有相应的解码 api,这样就可以成功的返回数据。

2、网页的编码会影响到发送请求时数据的编码,所以不一致时需要编码。

        var url = 'https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q='
         + encodeURIComponent($.trim(searchInput.val()));

生成下拉层数据结构

(function($){"use strict";//验证var search=$(".search"),
        searchInput=search.find(".search-input"),
        searchBtn=search.find(".search-btn"),
        searchList=search.find(".search-list");

    searchBtn.on("click",function(){//submit按钮默认行为是提交表单,return false可以阻止默认行为//$.trim() 去掉字符串两边的空格,阻止无内容提交if($.trim(searchInput.val())==="") return false;

    });//自动完成searchInput.on("input",function(){var url = 'https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q='
         + encodeURIComponent($.trim(searchInput.val()));// 异步避免回调        $.ajax({
            url:url,
            dataType:"jsonp"}).done(function(data){//成功执行//console.log(data["result"]);var html="";var dataNum=data["result"].length;//实际数据量var maxNum=10;//最大显示数据量if(dataNum===0) searchList.hide().html("");for(var i=0;i<dataNum;i++){if(i>=maxNum) break;//console.log(data["result"][i][0]);html+=''+data["result"][i][0]+'';
            }
            searchList.html(html).show();

        }).fail(function(){//失败执行searchList.hide().html("");
        }).always(function(){//总是执行console.log("always");
        });

    });

})(jQuery)

顺便将之前index.html中这部分注释掉

                <ul class="search-list"> 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222333-->ul>

效果

 

 

事件代理和显示隐藏下拉层

(function($){"use strict";//验证var search=$(".search"),
        searchForm=search.find(".search-form"),
        searchInput=search.find(".search-input"),
        searchBtn=search.find(".search-btn"),
        searchList=search.find(".search-list");

    searchForm.on("submit",function(){//return false可以阻止默认行为,即阻止表单提交//$.trim() 去掉字符串两边的空格,阻止无内容提交if($.trim(searchInput.val())==="") return false;

    });//自动完成searchInput.on("input",function(){var url = 'https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q='
         + encodeURIComponent($.trim(searchInput.val()));// 异步避免回调        $.ajax({
            url:url,
            dataType:"jsonp"}).done(function(data){//成功执行//console.log(data["result"]);var html="";var dataNum=data["result"].length;//实际数据量var maxNum=10;//最大显示数据量if(dataNum===0) searchList.hide().html("");for(var i=0;i<dataNum;i++){if(i>=maxNum) break;//console.log(data["result"][i][0]);html+=''+data["result"][i][0]+'';
            }
            searchList.html(html).show();

        }).fail(function(){//失败执行searchList.hide().html("");
        }).always(function(){//总是执行console.log("always");
        });

    });//jquery的事件代理//事件绑定在父元素上,第一个参数是事件,第二个参数是被代理的子元素们,第三个参数是函数//函数里的$(this)指向的是被代理的子元素searchList.on("click",".search-item",function(){
        searchInput.val(removeHTML($(this).html()));
        searchForm.submit();
    });//显示隐藏下拉层// searchInput.on("focus",function(){//     searchList.show();// }).on("blur",function(){//     searchList.hide();// });//以上这种方法不可行,会导致点击列表项失效//因为blur事件与click事件冲突//因为在选项上按下鼠标时,已经触发了input的blur事件,导致列表隐藏;再出发列表项的点击时,列表已经被隐藏searchInput.on("focus",function(){
        searchList.show();
    }).on("click",function(){return false;//阻止点击时冒泡到document    });
    $(document).on("click",function(){
        searchList.hide();
    });//去掉下拉列表项目的html标签,不然点击后会显示在搜索框中function removeHTML(str){// 示例:// 1、标签中的属性使用的引号 可能是双引号,也可能是单引号,所以匹配引号外面的内容使用^取反,双引号,单引号和>不能获取,其他都是可以获取的。// 2、匹配引号里面的内容,不能匹配到引号,其他都是可以的,数量上可以为0,也就是引号中间没有内容。单引号和双引号都有可能,所以写了两次。// 3、然后把这匹配的三个作为一组,需要全部都进行匹配,数量上可以为0,不需要捕获分组的内容,所以使用了?:// 4、最外层是<>return str.replace(/]|"[^"]*"|'[^']*')*>/g,"");
    }

})(jQuery)

知识点:

点击 input 显示下拉层,点击其他地方隐藏下拉层

这个功能,不能用下面这段代码

    searchInput.on("focus",function(){
        searchList.show();
    }).on("blur",function(){
        searchList.hide();
    });

因为这里的blur事件与click事件存在冲突
在选项上按下鼠标时,已经触发了input的blur事件,导致列表隐藏;再出发列表项的点击时,列表已经被隐藏

需要使用下面这段代码:(注意要阻止冒泡)

    //显示隐藏下拉层searchInput.on("focus",function(){
        searchList.show();
    }).on("click",function(){return false;//阻止点击时冒泡到document    });
    $(document).on("click",function(){
        searchList.hide();
    });

去掉字符串中 html 标签的正则:

    //去掉下拉列表项目的html标签,不然点击后会显示在搜索框中function removeHTML(str){return str.replace(/]|"[^"]*"|'[^']*')*>/g,"");
    }

示例:
1、标签中的属性使用的引号 可能是双引号,也可能是单引号,所以匹配引号外面的内容使用^取反,双引号,单引号和>不能获取,其他都是可以获取的。
2、匹配引号里面的内容,不能匹配到引号,其他都是可以的,数量上可以为0,也就是引号中间没有内容。单引号和双引号都有可能,所以写了两次。
3、然后把这匹配的三个作为一组,需要全部都进行匹配,数量上可以为0,不需要捕获分组的内容,所以使用了?:
4、最外层是<>


 

 面向对象方式封装搜索框功能

search.js

(function($){"use strict";function Search(elem,options){this.elem=elem;//已经是传入的jquery对象this.options=options;this.form=this.elem.find(".search-form");this.input=this.elem.find(".search-input");this.list=this.elem.find(".search-list");        //绑定提交事件,事件代理this.elem.on("click",".search-btn",$.proxy(this.submit,this));//如果设置了自动完成if(this.options.autocomplete) this.autocomplete();
    }//默认参数Search.defaults={
        autocomplete:false,
        url:"https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q=",
        css3:false,
        js:false,
        animation:"fade"}

    Search.prototype.submit=function(){if($.trim(this.input.val())==="") return false;this.form.submit();
    }

    Search.prototype.autocomplete=function(){this.input.on("input",$.proxy(this.getData,this));this.list.showHide(this.options);//向showhide组件传参,初始化//显示隐藏下拉层this.input.on("focus",$.proxy(this.showList,this))
                  .on("click",function(){                      return false;//阻止点击时冒泡到document                  });
        $(document).on("click",$.proxy(this.hideList,this));
    }

    Search.prototype.getData=function(){var self=this;

        $.ajax({
            url:this.options.url+encodeURIComponent($.trim(this.input.val())),
            dataType:"jsonp"}).done(function(data){//发送data数据,触发事件self.elem.trigger("search-getData",[data,self.list]);//数据需要用数组形式}).fail(function(){//发送失败数据,触发事件self.elem.trigger("search-noData",[self.list]);
        });    
    }

    Search.prototype.showList=function(){//list里有内容才显示if(this.list.children().length===0) return;this.list.showHide("show");//使用showhide组件的show方法    }

    Search.prototype.hideList=function(){this.list.showHide("hide");//使用showhide组件的hide方法    }

    Search.prototype.setInput=function(val){this.input.val(val);
    }//插件形式    $.fn.extend({
        search:function(opt,value){return this.each(function(){var ui=$(this);var search=ui.data("search");//opt是参数对象var options=$.extend({},Search.defaults,ui.data(),typeof opt==="object"&&opt);                //单例:一个DOM元素对应一个实例,如果已经存在则不需要反复实例化if(!search){
                    search=new Search(ui,options);
                    ui.data("search",search);
                }                //暴露出一些方法供外部调用if(typeof search[opt]==="function"){
                    search[opt](value);
                }
            });
        }
    });

})(jQuery)

index.js

// 不要暴露在全局,使用匿名函数自执行(function($){"use strict";    
//menu//绑定事件 显示之前加载数据$(".dropdown").on("dropdown-show",function(e){var ui=$(this);var dataLoad=ui.data("load");if(!dataLoad) return;if(!ui.data("loaded")){var list=ui.find(".dropdown-list");var html="";

            setTimeout(function(){
                $.getJSON(dataLoad,function(data){for(var i=0;i<data.length;i++){
                        console.log(data[i]);
                        html+=''+data[i]["name"]+'';
                    }
                    list.html(html);    
                    ui.data("loaded",true);

                });                
            },500);
        }    
    });//插件形式调用$(".dropdown").dropdown({
        css3:true,
        js:true});//searchvar headerSearch=$("#header-search");var html="";var maxNum=10;//最大显示数据量headerSearch.search({
        autocomplete:true,
        css3:false,
        js:false,
        animation:"fade"});//接收事件headerSearch.on("search-getData",function(e,data,list){//console.log(e.type);//console.log(data);var ui=$(this);//获取数据之后的处理html=createHeaderList(data,maxNum);
        list.html(html);if(html){
            ui.search("showList");
        }else{
            ui.search("hideList");
        }
        
    });

    headerSearch.on("search-noData",function(e,list){
        ui.search("hideList");//隐藏下拉列表list.html("");//清空内容    });

    headerSearch.on("click",".search-item",function(){
        headerSearch.search("setInput",$(this).text());
        headerSearch.search("submit");
    });//创建header中搜索框的下拉列表结构function createHeaderList(data,maxNum){var html="";var dataNum=data["result"].length;//实际数据量if(dataNum===0) return "";for(var i=0;i<dataNum;i++){if(i>=maxNum) break;
            html+=''+data["result"][i][0]+'';
        }return html;
    }

})(jQuery);

 

 接下来进行代码的优化:

1、上面这句代码是对DOM的操作,比较耗费性能。优化:引入loaded变量来判断

 

2、发送ajax请求时,需要新增判断数据为空的情况

 

 

3、如果一次ajax请求还没完成,就发送了下一次ajax请求,那么会导致返回的数据无法判断是哪一次的。优化:进行下一次请求时先终止之前的请求

 

 

4、搜索框每输入一个字符,就会发送一次ajax请求,即使两次间隔很短;建议:根据用户需求,判断是否需要加入延迟

 

 优化后的search.js

(function($){"use strict";function Search(elem,options){this.elem=elem;//已经是传入的jquery对象this.options=options;this.form=this.elem.find(".search-form");this.input=this.elem.find(".search-input");this.list=this.elem.find(".search-list");this.loaded=false;//是否装载html//绑定提交事件,事件代理this.elem.on("click",".search-btn",$.proxy(this.submit,this));//如果设置了自动完成if(this.options.autocomplete) this.autocomplete();
    }//默认参数Search.defaults={
        autocomplete:false,
        url:"https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q=",
        css3:false,
        js:false,
        animation:"fade",
        delay:200//默认200毫秒延迟    }

    Search.prototype.submit=function(){if($.trim(this.input.val())==="") return false;this.form.submit();
    }

    Search.prototype.autocomplete=function(){var self=this;var timer=null;this.input.on("input",function(){if(self.options.delay){
                clearTimeout(timer);
                timer=setTimeout(function(){
                    self.getData();
                },self.options.delay);                
            }else{
                self.getData();//delay为0时,不需要开定时器//因为定时器属于异步,即使延迟为0,也会进入排队状态,无法立刻执行            }

        });this.list.showHide(this.options);//向showhide组件传参,初始化//显示隐藏下拉层this.input.on("focus",$.proxy(this.showList,this))
                  .on("click",function(){                      return false;//阻止点击时冒泡到document                  });
        $(document).on("click",$.proxy(this.hideList,this));
    }

    Search.prototype.getData=function(){var self=this;var inputVal=this.input.val();if(!inputVal) return self.elem.trigger("search-noData");if(this.jqXHR) this.jqXHR.abort();//进行ajax请求时,先终止之前的请求this.jqXHR=$.ajax({
            url:this.options.url+encodeURIComponent($.trim(inputVal)),
            dataType:"jsonp"}).done(function(data){//发送data数据,触发事件self.elem.trigger("search-getData",[data]);//数据需要用数组形式}).fail(function(){//发送失败数据,触发事件self.elem.trigger("search-noData");
        }).always(function(){//执行完毕后self.jqXHR=null;
        });    
    }

    Search.prototype.showList=function(){//list里有内容才显示if(!this.loaded) return;this.list.showHide("show");//使用showhide组件的show方法    }

    Search.prototype.hideList=function(){this.list.showHide("hide");//使用showhide组件的hide方法    }

    Search.prototype.setInput=function(val){this.input.val(val);
    }

    Search.prototype.appendHTML=function(html){this.list.html(html);this.loaded=!!html;//!!转布尔值,如果html有内容,转为真;否则为假    }//插件形式    $.fn.extend({
        search:function(opt,value){return this.each(function(){var ui=$(this);var search=ui.data("search");//opt是参数对象var options=$.extend({},Search.defaults,ui.data(),typeof opt==="object"&&opt);                //单例:一个DOM元素对应一个实例,如果已经存在则不需要反复实例化if(!search){
                    search=new Search(ui,options);
                    ui.data("search",search);
                }                //暴露出一些方法供外部调用if(typeof search[opt]==="function"){
                    search[opt](value);
                }
            });
        }
    });

})(jQuery)

index.js

// 不要暴露在全局,使用匿名函数自执行(function($){"use strict";    
//menu//绑定事件 显示之前加载数据$(".dropdown").on("dropdown-show",function(e){var ui=$(this);var dataLoad=ui.data("load");if(!dataLoad) return;if(!ui.data("loaded")){var list=ui.find(".dropdown-list");var html="";

            setTimeout(function(){
                $.getJSON(dataLoad,function(data){for(var i=0;i<data.length;i++){
                        console.log(data[i]);
                        html+=''+data[i]["name"]+'';
                    }
                    list.html(html);    
                    ui.data("loaded",true);

                });                
            },500);
        }    
    });//插件形式调用$(".dropdown").dropdown({
        css3:true,
        js:true});//searchvar headerSearch=$("#header-search");var html="";var maxNum=10;//最大显示数据量headerSearch.search({
        autocomplete:true,
        css3:false,
        js:false,
        animation:"fade",
        delay:0});//接收事件headerSearch.on("search-getData",function(e,data){//console.log(e.type);        console.log(data);        var ui=$(this);//获取数据之后的处理html=createHeaderList(data,maxNum);
        ui.search("appendHTML",html);if(html){
            ui.search("showList");
        }else{
            ui.search("hideList");
        }
        
    }).on("search-noData",function(e){

        $(this).search("hideList");//隐藏下拉列表$(this).search("appendHTML","");//清空内容}).on("click",".search-item",function(){

        $(this).search("setInput",$(this).text());
        $(this).search("submit");

    });//创建header中搜索框的下拉列表结构function createHeaderList(data,maxNum){var html="";var dataNum=data["result"].length;//实际数据量if(dataNum===0) return "";for(var i=0;i<dataNum;i++){if(i>=maxNum) break;
            html+=''+data["result"][i][0]+'';
        }return html;
    }

})(jQuery);

index.html

<!DOCTYPE html><html lang="zh-CN"> 设置简体中文 --><head><meta charset="UTF-8"><title>indextitle><link rel="stylesheet" href="css/base.css"><link rel="stylesheet" href="css/index.css"><link rel="stylesheet" href="css/common.css"> css一般放在DOM加载前,防止DOM裸奔 -->head><body> 导航 --><div class="nav-site"><div class="container"><ul class="fl"><li class="fl"><a href="javascript:;" class="nav-site-login">亲,请登录a>li><li class="fl"><a href="javascript:;" class="nav-site-reg link">免费注册a>li><li class="fl"><a href="#" class="nav-site-shop link">手机逛慕淘a>li>ul><ul class="fr"><li class="fl dropdown menu" data-active="menu"><a href="javascript:;" class="dropdown-toggle link transition">我的慕淘<i class="dropdown-arrow iconfont transition">&#xe642;i>a><ul class="dropdown-list dropdown-left"><li class="menu-item"><a href="#">已买到的宝贝a>li><li class="menu-item"><a href="#">我的足迹a>li>ul>li><li class="fl dropdown menu" data-active="menu"><a href="javascript:;" class="dropdown-toggle link transition">收藏夹<i class="dropdown-arrow iconfont transition">&#xe642;i>a><ul class="dropdown-list dropdown-left"><li class="menu-item"><a href="#">收藏的宝贝a>li><li class="menu-item"><a href="#">收藏的店铺a>li>ul>li><li class="fl dropdown"><a href="javascript:;" class="nav-site-cat link">商品分类i>a>li><li class="fl dropdown menu" data-active="menu" data-load="js/dropdown-seller.json"><a href="javascript:;" class="dropdown-toggle link transition">卖家中心<i class="dropdown-arrow iconfont transition">&#xe642;i>a><ul class="dropdown-list dropdown-left"><li class="dropdown-loading">li> 免费开店已卖出的宝贝出售中的宝贝卖家服务市场卖家培训中心体验中心-->ul>li><li class="nav-site-service fl dropdown menu" data-active="menu"><a href="javascript:;" class="dropdown-toggle link transition">联系客服<i class="dropdown-arrow iconfont transition">&#xe642;i>a><ul class="dropdown-list dropdown-right"><li class="menu-item"><a href="#">已买到的宝贝a>li><li class="menu-item"><a href="#">我的足迹a>li>ul>li>ul>div>div> 头部 --><div class="header"><div class="container"> h1标签是为了搜索引擎优化,表示重要
            但是页面内不要出现太多 --><h1 class="fl"><a href="#" class="header-logo text-hidden">慕淘网a>h1><div id="header-search" class="search fl"> 由于没有自己的搜索页,演示时设置为提交到淘宝,参考淘宝设置 --><form action="https://s.taobao.com/search" class="search-form"> 由于input是内联块,相当于display:inline-block
                    如果换行写,会造成空隙,空隙大小一般是默认字体的一半
                    可以不换行书写,但是可读性较差
                    都添加左浮动可以解决 --> 设置name才能提交 --><input type="text" class="search-input fl" name="q" placeholder="灵魂美食一元抢" autocomplete="off"><input type="submit" value="搜索" class="search-btn fl">form><ul class="search-list"> 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222333-->ul>div><div class="header-cart fr">div>div>div>     //短路操作,如果cdn的jquery没有引用成功,则会执行后面一句,引入本地jquery
        //括号中的标签会被当做当前标签的结束标签,因此需要转义
        window.jQuery || document.write('');--><script src="js/jquery.js">script><script src="js/transition.js">script><script src="js/showhide.js">script><script src="js/dropdown.js">script><script src="js/search.js">script><script src="js/index.js">script>body>html>

最后,优化之数据缓存

思路:获取到的数据存入变量、cookie、或是本地存储:session storage / local storage (HTML5) 或是本地数据库

search.js

(function($){"use strict";var cache={
        data:{},
        count:0,//数据条数addData:function(data,key){if(!this.data[key]){this.data[key]=data;this.count++;            
            }
        },
        readData:function(key){return this.data[key];
        },
        deleteDataByKey:function(key){delete this.data[key];this.count--;
        },
        deleteDataByNum:function(num){var count=0;//对象没有length属性,只能通过for in来遍历for(var p in this.data){if(count>=num) break;this.deleteDataByKey(p);this.count++;
            }
        }

    };function Search(elem,options){this.elem=elem;//已经是传入的jquery对象this.options=options;this.form=this.elem.find(".search-form");this.input=this.elem.find(".search-input");this.list=this.elem.find(".search-list");this.loaded=false;//是否装载html//绑定提交事件,事件代理this.elem.on("click",".search-btn",$.proxy(this.submit,this));//如果设置了自动完成if(this.options.autocomplete) this.autocomplete();
    }//默认参数Search.defaults={
        autocomplete:false,
        url:"https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q=",
        css3:false,
        js:false,
        animation:"fade",
        delay:200//默认200毫秒延迟    }

    Search.prototype.submit=function(){if($.trim(this.input.val())==="") return false;this.form.submit();
    }

    Search.prototype.autocomplete=function(){var self=this;var timer=null;this.input.on("input",function(){if(self.options.delay){
                clearTimeout(timer);
                timer=setTimeout(function(){
                    self.getData();
                },self.options.delay);                
            }else{
                self.getData();//delay为0时,不需要开定时器//因为定时器属于异步,即使延迟为0,也会进入排队状态,无法立刻执行            }

        });this.list.showHide(this.options);//向showhide组件传参,初始化//显示隐藏下拉层this.input.on("focus",$.proxy(this.showList,this))
                  .on("click",function(){                      return false;//阻止点击时冒泡到document                  });
        $(document).on("click",$.proxy(this.hideList,this));
    }

    Search.prototype.getData=function(){var self=this;var inputVal=this.input.val();if(!inputVal) return self.elem.trigger("search-noData");//判断是否已有缓存if(cache.readData(inputVal)) return self.elem.trigger("search-getData",[cache.readData(inputVal)]);if(this.jqXHR) this.jqXHR.abort();//进行ajax请求时,先终止之前的请求this.jqXHR=$.ajax({
            url:this.options.url+encodeURIComponent($.trim(inputVal)),
            dataType:"jsonp"}).done(function(data){//发送data数据,触发事件            cache.addData(data,inputVal);//添加缓存            console.log(cache.data);
            console.log(cache.count);
            self.elem.trigger("search-getData",[data]);//数据需要用数组形式}).fail(function(){//发送失败数据,触发事件self.elem.trigger("search-noData");
        }).always(function(){//执行完毕后self.jqXHR=null;
        });    
    }

    Search.prototype.showList=function(){//list里有内容才显示if(!this.loaded) return;this.list.showHide("show");//使用showhide组件的show方法    }

    Search.prototype.hideList=function(){this.list.showHide("hide");//使用showhide组件的hide方法    }

    Search.prototype.setInput=function(val){this.input.val(val);
    }

    Search.prototype.appendHTML=function(html){this.list.html(html);this.loaded=!!html;//!!转布尔值,如果html有内容,转为真;否则为假    }//插件形式    $.fn.extend({
        search:function(opt,value){return this.each(function(){var ui=$(this);var search=ui.data("search");//opt是参数对象var options=$.extend({},Search.defaults,ui.data(),typeof opt==="object"&&opt);                //单例:一个DOM元素对应一个实例,如果已经存在则不需要反复实例化if(!search){
                    search=new Search(ui,options);
                    ui.data("search",search);
                }                //暴露出一些方法供外部调用if(typeof search[opt]==="function"){
                    search[opt](value);
                }
            });
        }
    });

})(jQuery)

 


/template/Home/Zkeys/PC/Static