淘宝购物车页面 智能搜索框Ajax异步加载数据
如果有朋友对本篇文章的一些知识点不了解的话,可以先阅读此篇文章。在这篇文章中,我大概介绍了一下构建淘宝购物车页面需要的基础知识。
这篇文章主要探讨的是智能搜索框Ajax异步加载数据。jQuery的社区非常的活跃,许多朋友都在不同地方分享了很多优秀的插件。我在相关的网站上找过想实现类似功能的插件,但是没有找到。于是乎,自己动手丰衣足食。自己来搭建智能搜索框下拉列表。当然,如果有类似功能并且常维护Bug的插件,望留言交流。
源码地址:Github 淘宝购物车页面--PC端和移动端项目实战
首先需要先给大家打一根预防针。本人实现的智能搜索框下拉列表只供学习参考使用。因为智能搜索和模糊匹配的实现没有那么简单,它需要自己的一套系统。如果想实现相同的功能,可以看看这个 智能搜索框制作 的视频。 视频中远人老师介绍了如何去获取微软必应搜索引擎的数据库然后实现智能搜索和模糊匹配的功能。
简单的介绍一下智能搜索框实现的一些功能:
1.当输入特定字符(在JSON数据定义的是查询字符串('lan'))时,会有一个下拉列表弹出,并且每一个li元素都有相应的数据(调用了search.json)。这里使用的是$.get方法获取JSON数据,然后动态加载HTML,最后插入到客户端的某个空容器中。
2:在搜索框输入字符串'lan',按下回车键,会有相应的商品被异步加载到页面中。这里也是使用了jQuery Ajax的$.get方法,调用了basketballShoes.json文件。
3:当我想查询某个商品,比如李宁的音速3篮球鞋。在搜索框输入'音速3',按下回车,相应的商品被异步加载到页面中。
4:在搜索框中查询,并且被异步加载到页面中的商品,所有的事件都需要绑定到非动态加载HTML的元素上(此实战绑定在了body元素上),不能绑定在该元素上。否则,所有事件都会失效。这里涉及了事件代理和事件冒泡的原理。
以下的分享会分为如下部分
1.智能搜索下拉列表的实现
2.ajax异步获取商品
3.事件代理和事件冒泡
1.智能搜索下拉列表的实现
首先,需要做的是定义想要查询的JSON数据。
[ [ { "Query":"lan", "Results":[ { "Type":"AS", "Suggests":[ { "Txt":"Nike 耐克官方 ZOOM KOBE 男子篮球鞋 " }, { "Txt":"adidas Regulate 篮球鞋 " }, { "Txt":"李宁2016新款男子音速3高帮反弹篮球鞋" }, { "Txt":"李宁2016新款男子减震CBA魅影篮球鞋" }, { "Txt":"李宁男子专业篮球鞋CBA球迷空袭" }, { "Txt":"adidas罗斯系列场上款篮球鞋" }, { "Txt":"adidas Boost 罗斯系列篮球鞋 JXO25 " }, { "Txt":"adidas场上款篮球鞋 D Rose 7 Primeknit" } ] } ] } ] ]
search.json
JSON是指Javascript对象字面量表示法,是一种用于数据交换的文本格式。每一个JSON对象,都是一个值。要么是简单类型的值,要么是复合类型的值。JSON对值的类型和格式有着严格的规定,比如说对象的名称(键名)必须放在双引号内,数组或对象的最后一个成员的后面,不能加逗号等等。所以构建JSON时一定要放到网上去检查一下是否书写正确。否则,JSON一旦出错,浏览器也不会报错。这个查错的成本就很高了。
以下是智能搜索的js代码。输入'lan' ,就有相应的下拉框弹出。
//搜索框下拉列表 $('body').on('keyup','.header-search-input',function(event){ //获取输入的值 var $val = $(this).val(); //使用$.get()方法,并且将查询的值放在URI后面 $.get('search.json',{'Query':$val}, function(data) { for (var i = 0; i < data.length; i++) { //如果值与json中的query字段匹配,动态加载html if ($val === data[i][0].Query) { var $data = data[i][0].Results[0].Suggests; var $html= ''; $html+='<ul>'; //全局函数$.each,也可以使用for循环 $.each($data, function(index, val) { $html+='<li>'+val.Txt+'</li>'; }); $html+='</ul>'; //下列列表dispaly:none的,当符合条件后 //调用show()函数,然后设定css样式 $('.list').html($html).show().css({ 'position':'absolute', 'left':0, 'top':$('.header-search-input').height()+5 }) } } //当点击每一条li数据时,会相应的将数据作为搜索框的值 $('.list li').click(function(event) { var $liText = $(this).text(); $('.header-search-input').val($liText); }); }); //如果值为空,则隐藏整个列表 if ($(this).val() === '') { $('.list').hide(); } //按下回车时,调用shoppingCart()函数。 if (event.which === 13) { shoppingCart(); } });
2.Ajax异步获取商品
在输入相应的查询字符串('lan' 或者是 '音速3'),按下回车键之后,会有相应的商品被动态加载到html结构当中,这里调用了baskedballShoes.json。
[ [ { "Query":"lan", "Results":[ { "Type":"AS", "Suggests":[ { "Txt":"李宁2016新款男子篮球鞋音速3高帮反弹篮球场地鞋ABAL031", "num":339, "max":764, "label":"liningBas", "shop":"李宁官方网店", "image":"css/images/lining-bas.png", "color":"颜色分类:荧光果粉/木梅红", "size":"鞋码:42", "nonDiscount":"¥539.00", "bandCard":"css/images/bankCard.png", "sevenDay":"css/images/sevenDay.png", "guarantee":"css/images/guarantee.png" }, { "Txt":" adidas阿迪达斯篮球男子篮球鞋Regulate", "num":419, "max":18, "label":"adidas", "nonDiscount":"¥539.00", "image":"css/images/adidas.png", "color":"颜色分类:银金属/深藏青蓝", "shop":"adidas官方旗舰店", "size":"鞋码:43.5", "bandCard":"css/images/bankCard.png", "sevenDay":"css/images/sevenDay.png", "guarantee":"css/images/guarantee.png" } ] } ] } ], [ { "Query":"音速3", "Results":[ { "Type":"AS", "Suggests":[ { "Txt":"李宁2016新款男子篮球鞋音速3高帮反弹篮球场地鞋ABAL031", "num":339, "max":764, "shop":"李宁官方网店", "image":"css/images/lining-bas.png", "color":"颜色分类:荧光果粉/木梅红", "size":"鞋码:42", "nonDiscount":"¥539.00", "bandCard":"css/images/bankCard.png", "sevenDay":"css/images/sevenDay.png", "guarantee":"css/images/guarantee.png" } ] } ] } ] ]
basketballShoes.json
这里需要注意一点的是,因为是使用Ajax 异步加载商品,动态创建html然后返回客户端,所以需要把某件商品的信息全部写到JSON中,比如商品图片,商品信息,单价,数量,金额等。然后再循环遍历每一个数组中的元素,通过点操作将数据写入浏览器中。
以下是Ajax异步获取商品的js代码。输入'lan'回车或者输入'音速3'回车。当然,可以在JSON中自行修改字符串的匹配。需要注意的是,因为是按下回车之后的查询,所以当event.which===13的时候,调用了shoppingCart()函数。
修改:感谢@troy.cui 和 @Genius Zhang 留言中提的意见,我已经对字符串拼接做了相应的调整。废弃了手写拼接字符串的方法,使用腾讯CDC的altTemplate.js模板引擎,这种方法的原理实质上就是在拼接字符串,并且让数据和结构相分离。相应的源代码已经放在GitHub 淘宝购物车页面--PC端和移动端项目实战了。
//购物车存放产品--- 通用function function shoppingCart(){ //获取输入框的值,用于字符串匹配 var $val = $('.header-search-input').val(); $.get('basketballShoes.json',{'Query':$val}, function(data) { for (var i = 0; i < data.length; i++) { if ($val === data[i][0].Query) { //字符串匹配 //当输入'lan'时,会匹配第一个数组 //当输入'音速3'时,会匹配第二个数组。 //也可以自行修改字符串匹配规则。 var $data = data[i][0].Results[0].Suggests; var results = data[i][0].Results[0]; /*第一种方法:手写拼接字符串,效率低,易出错, 结构与数据未分离,不推荐使用这种方法拼接字符串*/
/* var $html = ''; //使用$.each()方法循环每一个$data, //然后动态加载html, //把相应的商品信息放到指定的.commodityContainer容器中 $.each($data, function(index, val) { $html+='<div class="mainCommodity">'; $html+='<div class="shopInfo">'; $html+='<div class="shopMsg">'; //$.each()中回调函数中的第二个参数指定的是每一个值, //通过点操作来获取每个字段。 //比如val.label 就为 '李宁2016新款男子篮球鞋音速3高帮反弹篮球场地鞋ABAL031'。 //下面的操作相同。 $html+='<input type="checkbox" name="shopMsg" id="'+val.label+'" class="shopMsg-input" autocomplete="off">'; $html+='<label for="'+val.label+'">'; $html+='店铺:'; $html+='</label>'; $html+='<a href="#">'+val.shop+''; $html+='</a>' $html+='</div>'; $html+='</div>'; $html+='<div class="commodityInfo">'; $html+='<ul>'; $html+='<li class="td-chk">'; $html+='<div class="td-inner">'; $html+='<input type="checkbox" name="checkbox" autocomplete="off">'; $html+='</div>'; $html+='</li>'; $html+='<li class="td-item">'; $html+='<div class="td-inner">'; $html+='<a class="desImg" href="#">'; $html+='<img alt="'+val.Txt+'" src="'+val.image+'">'; $html+='</a>'; $html+='<div class="item-info">'; $html+='<div class="item-basis-info">'; $html+='<a href="#">'+val.Txt+''; $html+='</a>'; $html+='</div>'; $html+='<div class="item-other-info">'; $html+='<div class="item-other-space"></div>'; $html+='<div class="item-other-list">'; $html+='<a href="#" title="支持信用卡支付">'; $html+='<img alt="支持信用卡支付" src="'+val.bandCard+'">'; $html+='</a>'; $html+='<a href="#" title="7天无理由" class="sevenDay">'; $html+='<img alt="7天无理由" src="'+val.sevenDay+'">'; $html+='</a>'; $html+='<a href="#" title="消费者保障服务">'; $html+='<img alt="消费者保障服务" src="'+val.guarantee+'">'; $html+='</a>'; $html+='</div>'; $html+='</div>'; $html+='</div>'; $html+'</div>'; $html+='</li>'; $html+='<li class="td-info">'; $html+='<div class="td-info-msg">'; $html+='<p>'+val.color+'</p>'; $html+='<p>'+val.size+'</p>'; $html+='</div>'; $html+='</li>'; $html+='<li class="td-price">'; $html+='<div class="td-inner">'; $html+='<p class="non-discount">'+val.nonDiscount+'</p>'; $html+='<p class="discount">¥'; $html+='<span>'+val.num+'.00</span>'; $html+='</p>'; $html+='<div class="promotion">卖家促销'; $html+='<i class="promotionIcon"></i>'; $html+='</div>'; $html+='<div class="proSlidedown">'; $html+='<p class="newPro">卖家促销:秋季特惠</p>'; $html+='<p>优惠:¥'+val.disc+'</p>'; $html+='</div>'; $html+='</div>'; $html+='</li>'; $html+='<li class="td-amount">'; $html+='<div class="item-amount">'; $html+='<a href="#" class="amount-left amount-color">-</a>'; $html+='<input type="text" name="amountNum" value="1" autocomplete="off" />'; $html+='<a href="#" class="amount-right">+</a>'; $html+='</div>'; $html+='<div class="stock">'+val.max+'</div>'; $html+='<div class="outNum">'; $html+='<span class="instr">最多只能购买</span>'; $html+='<span class="stockNum"></span>'; $html+='<em>件</em>'; $html+='</div>'; $html+='</li>'; $html+='<li class="td-sum">'; $html+='<em>¥</em>' $html+='<span>'+val.num+'.00</span>'; $html+='</li>'; $html+='<li class="td-operation">'; $html+='<p>'; $html+='<a href="#" class="delete">删除</a>'; $html+='</p>'; $html+='</li>'; $html+='</ul>'; $html+='</div>'; $html+='</div>'; //将动态加载的html放到指定的容器中, //这里首先应该在html中放放上一个空容器 //<div className="commidityContainer"></div> $('.commodityContainer').html($html); }); */
手写拼接字符串,易出错,效率低
/*第二种方法:使用js模板引擎,结构与数据分离, 并且altTemplate效率高,速度快,推荐使用。*/
var $html = template('basketBallShoes',results); $('.commodityContainer').html($html); } } }); }
3.事件代理和事件冒泡
简单的介绍一下这两个概念吧。
事件传播模型会经历两个阶段。一是事件捕获,二是事件冒泡。事件捕获是指事件首先会交给最外层的元素,接着再交给更具体的元素。而事件冒泡是指当事件发生时,会首先发送给最具体的元素,在这个元素获得响应机会之后,事件会向上冒泡到更一般的元素。
在jQuery中,默认情况下始终会在模型的冒泡阶段注册事件处理程序。因此,可以假定最具体的元素首先获得响应事件的机会。
事件代理,也叫事件委托。事件委托就是利用事件冒泡的一项高级技术。通过事件委托,可以借助一个元素上的事件处理程序完成很多工作。
有时候我们需要给没有被渲染到浏览器的 (可能将来会被渲染)一段DOM元素绑定事件,比如说给一段通过Ajax请求完成后渲染的DOM节点绑定事件。一般绑定的逻辑会在渲染前执行,绑定的时候找不到元素所以事件会失效,使用事件代理/委托可以解决这种动态加载HTML元素的事件绑定问题。并且,事件代理的性能比单独绑定事件要好的多。
在这个实战中,
事件冒泡主要应用在扩大全选按钮和商品选择按钮的点击范围。
事件代理主要应用在通过Ajax异步加载的商品。
在这个例子中,把商品数量的输入框的keypress,keyup,blur事件全部代理到body元素中,这样就能确保每个事件都能够生效。而不会因为HTML元素未被浏览器渲染而导致事件失效的情况。当然商品数量增加和商品数量减少也是同样的原理。具体事件的代码会在下次分享中谈及。
源码地址:Github 淘宝购物车页面--PC端和移动端项目实战
完。
感谢大家的阅读。
转载请注明出处:http://www.cnblogs.com/Uncle-Keith/p/5930255.html
淘宝购物车页面 智能搜索框Ajax异步加载数据的更多相关文章
- ajax异步加载问题
使用ajax异步加载数据,在之后需要用到这个数据时,应该将之后的js一并写入ajax函数中,否则后面的js不能找到动态拼接的dom节点. 或者将其封装成方法,在ajax动态加载数据的最后调用该方法.
- 淘宝购物车页面 PC端和移动端实战
最近花了半个月的时间,做了一个淘宝购物车页面的Demo.当然,为了能够更加深入的学习,不仅仅有PC端的固定宽度的布局,还实现了移动端在Media Query为768px以下(也就是实现了ipad,ip ...
- Ajax 滚动异步加载数据
第一种情况:单个div滚动 HTML <body> <!-- search start --> <div class="search" #if($m_ ...
- Scrapy爬虫框架教程(四)-- 抓取AJAX异步加载网页
欢迎关注博主主页,学习python视频资源,还有大量免费python经典文章 sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction ...
- 向上滚动或者向下滚动分页异步加载数据(Ajax + lazyload)[上拉加载组件]
/**** desc : 分页异步获取列表数据,页面向上滚动时候加载前面页码,向下滚动时加载后面页码 ajaxdata_url ajax异步的URL 如data.php page_val_name a ...
- jQuery的AJax异步加载
主要用到load()方法以及getScript()方法,具体以一个例子说明: 在现有html文件中加载一个拟好的片段,以及在片段加载完成之前阻止用户进一步操作的弹出框. 首先是现有html代码,无任何 ...
- combotree -下拉框树异步加载
问题: 下拉树数据比较多时,全加载会产生页面延迟,需要实现异步加载 方案: 点击事件加载:先加载部分,点击节点时再展开并追加子节点 onBeforeExpand事件:在展开树前加载,感觉这种方式比较优 ...
- web——自己实现一个淘宝购物车页面
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- 使用Ajax异步加载页面时,怎样调试该页面的Js
前言-本人不是干前端的,所以有的名词不专业 在前端中,有时候会遇到这样的框架,http://172.17.11.151:8060/frontend/backend.html#1.html (通过解析U ...
随机推荐
- AndroidStudio错误总结及解决(待续)
AndroidStudio错误总结及解决 一. 当安装好AndroidStudio开启的时候出现如下错误: 百度的解决方法: 1)进入刚安装的Android Studio目录下的bin目录.找到ide ...
- 科学计算软件——Octave安装
Octave是一个旨在提供与Matlab语法兼容的开放源代码科学计算及数值分析的工具,是Matlab商业软件的一个强有力的竞争产品. 参考:[ML:Octave Installation] Gener ...
- 用javascript实现一个2048游戏
早就想自己写一个2048游戏了,昨晚闲着没事,终于写了一个 如下图,按方向键开始玩吧. 如果觉得操作不方便,请直接打开链接玩吧: http://gujianbo.1kapp.com/2048/2048 ...
- C#_闭包陷阱
如果匿名方法(Lambda表达式)引用了某个局部变量,编译器就会自动将该引用提升到该闭包对象中. 即将for循环中的变量i修改成了引用闭包对象的公共变量i.这样一来,即使代码执行后离开了原局部变量i的 ...
- 【腾讯Bugly干货分享】Redex初探与Interdex:Andorid冷启动优化
本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/583b9e3ee8992c2c2df6e6ac 导语 早在去年10月份,face ...
- 【转】我的技术学习方法 — Anytao
原文作者:anytao—王涛 他的著作:<你必须知道的.Net> 关于这个问题,也有不少刚刚入行的朋友向我问起.我想可能一千个人就有一千个答案,我不能保证自己的想法适合于所有的人,但是这确 ...
- Unit Testing with NSubstitute
These are the contents of my training session about unit testing, and also have some introductions a ...
- MySQL 权限
create user创建用户 CREATE USER li@localhost IDENTIFIED BY 'li'; 授予用户li数据库person的所有权限,并允许用户li将数据库person的 ...
- Javascript中相同Function使用多个名称
原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 看Log4js源码有如下实现: ['Trace','Debug','Info','Warn','Error', ...
- Java针对数据库增删改查代码
package com.bank.abc; import java.beans.PropertyVetoException; import java.sql.Connection; import ja ...