前端_网页编程 跨域与JSONP- 淘宝搜索案例

ゝ一世哀愁。 2022-12-01 15:44 299阅读 0赞

文章目录

  • 前言
    1. 要实现的UI效果
    1. 实现步骤
    • 2.1 获取用户输入的搜索关键词
    • 2.2 建议搜索列表的函数封装
    • 2.3 渲染建议列表的UI结构
      • 2.3.1 定义搜索建议列表
      • 2.3.2 定义模板结构
      • 2.3.1 定义渲染模板结构的函数
    • 2.4 美化搜索建议列表
      • 2.4.1 建议列表框美化
    • 2.5 输入框的防抖
      • 2.5.1 什么是防抖
      • 2.5.2 防抖的应用场景
      • 2.5.3 实现输入框的防抖
        • 1)定义防抖延时器
        • 2)定义防抖函数
        • 3)实现防抖
    • 2.6 缓存搜索的建议列表
      • 2.6.1 定义全局缓存对象
      • 2.6.2 将搜索结果保存到缓存对象中
      • 2.6.3 优先从缓存对象中获取搜索建议
    1. 完整案例代码

前言

这里来实现一个淘宝搜索框输入时,下拉智能弹出选项的案例

1. 要实现的UI效果

在这里插入图片描述

2. 实现步骤

2.1 获取用户输入的搜索关键词

为了获取到用户每次按下键盘输入的内容,需要监听输入框的 keyup 事件。
并且给搜索输入框框起一个 idipt,示例代码如下:

  1. // 监听文本框的 keyup 事件
  2. $('#ipt').on('keyup', function() {
  3. // 获取用户输入的内容
  4. var keywords = $(this).val().trim()
  5. // 判断用户输入的内容是否为空
  6. if (keywords.length <= 0) {
  7. return
  8. }
  9. // TODO:获取搜索建议列表
  10. })

keyup 事件,鼠标弹起时触发

2.2 建议搜索列表的函数封装

将获取搜索建议列表的代码,封装到 getSuggestList 函数中,示例代码如下:

  1. function getSuggestList(kw) {
  2. $.ajax({
  3. // 指定请求的 URL 地址,其中,q 是用户输入的关键字
  4. url: 'https://suggest.taobao.com/sug?q=' + kw,
  5. // 指定要发起的是 JSONP 请求
  6. dataType: 'jsonp',
  7. // 通过回调函数拿到jsonp返回回来的数据
  8. success: function(res) {
  9. renderSuggestList(res)
  10. }
  11. })
  12. }

2.3 渲染建议列表的UI结构

2.3.1 定义搜索建议列表

在原HTML结构基础上,在搜索框的下方添加一个div盒子,取id名为“suggest-list”,如下所示:

  1. <div class="box">
  2. <!-- tab 栏区域 -->
  3. <div class="tabs"></div>
  4. <!-- 搜索区域 -->
  5. <div class="search-box"></div>
  6. <!-- 搜索建议列表 -->
  7. <div id="suggest-list"></div>
  8. </div>

2.3.2 定义模板结构

因为接下来要渲染搜索建议列表,在渲染数据结构期间,我们最好使用模板引擎,因此必须要定义一个模板结构。

A、导入模板引擎

  1. <script src="./lib/template-web.js"></script>

注:
本案例采用 art-template模板引擎
官方文档:http://aui.github.io/art-template/zh-cn/docs/index.html
art-template 模板引擎详细学习笔记:https://blog.csdn.net/zglibk/article/details/108048255

B、定义模板结构
分析:
由上面2.2 的代码”获取用户搜索建议列表” console.log(res)打印在控制台的信息可以看到一个从服务器返回的result对象,在这个对象中有一个result数组,每循环一次可以拿到一个建议项,里面每一个建议项又是一个数组,而实际上需要拿到的真正的建议内容是索引(下标)为0的这一项。
在这里插入图片描述
——因此,我们只需要循环result这个数组,就能拿到每一个搜索键,由于每一个键都可以用{ {$ value}}来表示,则{ {$ value}}里索引为0这一项,即为我们要获取的 搜索建议内容。

代码实现:
在模板引擎标签中,用{ {each}} { {/each}}语法来循环result,每循环一次,就创建一个div标签(放搜索建议项),给div指定一个类名suggest-item,每循环一次就将 搜索建议内容 打印出来:

  1. <script type="text/html" id="tpl-suggestList"> { { each result}} <div class="suggest-item">{ { $value[0]}}</div> { { /each}} </script>

2.3.1 定义渲染模板结构的函数

封装自定义函数renderSuggestList,调用函数渲染模板结构。

  1. // 渲染UI结构
  2. // 传入一个res参数(res就是待渲染的数据)
  3. function renderSuggestList(res) {
  4. // 判断是否有待渲染的数据,如果没有就return出去,清空列表并隐藏
  5. if (res.result.length <= 0) {
  6. return $('#suggest-list').empty().hide();
  7. }
  8. // 调用模板引擎的template函数
  9. var htmlstr = template('tpl-suggestList', res) // 返回一个渲染好的html结构
  10. // 将渲染好的字符串放到搜索建议列表div中,并展示出来
  11. $('#suggest-list').html(htmlstr).show();
  12. }

2.4 美化搜索建议列表

2.4.1 建议列表框美化

1)添加边框效果

  1. #suggest-list {
  2. border: 1px solid #ccc;
  3. /* 默认隐藏 */
  4. display: none;
  5. }

在这里插入图片描述
2)列表项美化

  1. /*设置行高、左边距*/
  2. .suggest-item {
  3. line-height: 14px;
  4. padding: 8px;
  5. }
  6. /*设置光标小手,列表项鼠标经过背景变色效果*/
  7. .suggest-item:hover {
  8. cursor: pointer;
  9. background-color: #eee;
  10. }

2.5 输入框的防抖

2.5.1 什么是防抖

防抖策略(debounce)是当事件被触发后,延迟 n 秒 后再 执行回调,如果在这 n 秒内事件又被触发,则 重新计时。

实现方式: 每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法;
缺  点: 如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟。

函数防抖: 将多次操作合并为一次操作进行。原理是维持一个计时器,规定在延迟时间后触发函数,但是在延迟时间内再次触发的话,就会取消之前的计时器而重新设置。这样,就可以保证只有最后一次操作被触发。

其原理图示如下:

在这里插入图片描述

2.5.2 防抖的应用场景

用户在输入框中连续输入一串字符时,可以通过防抖策略。只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源;
在这里插入图片描述
如果没有防抖策略,那么每摁一下键盘,就会触发一次网络请求(如上图)。

注:输入框防抖,是最典型的应用场景

2.5.3 实现输入框的防抖

实现的步骤:

  1. 定义防抖的timer
  2. 定义防抖的函数;
  3. 在触发keyup事件时,立即清空timer

代码实现的基本结构:

  1. var timer = null // 1. 定义防动延时器 timer
  2. function debounceSearch(keywords) { // 2. 定义防抖的函数
  3. timer = setTimeout(function() {
  4. // 发起 JSONP 请求
  5. getSuggestList(keywords)
  6. }, 500)
  7. }
  8. $('#ipt').on('keyup', function() { // 3. 在触发 keyup 事件时,立即清空 timer
  9. clearTimeout(timer)
  10. // (...略)
  11. debounceSearch(keywords)
  12. })

1)定义防抖延时器

  1. var timer=null;

2)定义防抖函数

  1. // 定义防抖的函数,延时500毫秒后,再请求数据接口
  2. function debounceSearch(kw){
  3. // 开启延时器
  4. timer = setTimeout(function(){
  5. getSuggestList(kw);
  6. ,500)}

3)实现防抖

首先,在触发keyup事件的时候,就要立即清空timer:

  1. $('#ipt').on('keyup', function() {
  2. clearTimeout(timer);
  3. //( ......略 )
  4. }

然后,在获取搜索建议列表函数这块,就不能直接调用getsuggestList函数,要将keyup事件函数调用做一下修改:

  1. // 绑定用户输入框keyup事件
  2. $('#ipt').on('keyup', function() {
  3. // 清空timer
  4. clearTimeout(timer);
  5. var keywords = $(this).val().trim();
  6. if (keywords.length <= 0) {
  7. // 如果用户没有输入内容,则退出并清空隐藏列表
  8. return $('#suggest-list').empty().hide()
  9. }
  10. // getSuggestList(keywords); // 改为:
  11. debounceSearch(keywords);
  12. })

在这里插入图片描述
这样,前面4次摁键(appl)的请求被取消,就只有最后1次(apple)才发起请求,实现了防抖

2.6 缓存搜索的建议列表

作用: 如果发起相同的请求,可以根据之前的缓存直接拿到搜索建议,就不用再重复发起请求,节约资源,提高搜索效率。

2.6.1 定义全局缓存对象

  1. // 定义全局缓存对象
  2. var cacheObj={ };

2.6.2 将搜索结果保存到缓存对象中

  1. function renderSuggestList(res) {
  2. //... 略去无关代码
  3. // 1、获取到用户输入的内容,当做键
  4. var k = $('#ipt').val().trim();
  5. // 2、将数据做为值缓存到全局对象中
  6. cacheObj[k] = res;
  7. }

2.6.3 优先从缓存对象中获取搜索建议

代码结构如下:

  1. // 监听文本框的 keyup 事件
  2. $('#ipt').on('keyup', function() {
  3. // ...省略其他代码
  4. // 优先从缓存中获取搜索建议
  5. if (cacheObj[keywords]) {
  6. return renderSuggestList(cacheObj[keywords])
  7. }
  8. // 获取搜索建议列表
  9. debounceSearch(keywords)
  10. })

3. 完整案例代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  7. <title>Document</title>
  8. <!-- 导入页面的基本样式 -->
  9. <link rel="stylesheet" href="./css/search.css" />
  10. <!-- 导入 jQuery -->
  11. <script src="./lib/jquery.js"></script>
  12. <!-- 导入模板引擎 -->
  13. <script src="./lib/template-web.js"></script>
  14. </head>
  15. <body>
  16. <div class="container">
  17. <!-- Logo -->
  18. <img src="./images/taobao_logo.png" alt="" class="logo" />
  19. <div class="box">
  20. <!-- tab 栏 -->
  21. <div class="tabs">
  22. <div class="tab-active">宝贝</div>
  23. <div>店铺</div>
  24. </div>
  25. <!-- 搜索区域(搜索框和搜索按钮) -->
  26. <div class="search-box">
  27. <input id="ipt" type="text" class="ipt" placeholder="请输入要搜索的内容" /><button class="btnSearch">
  28. 搜索
  29. </button>
  30. </div>
  31. <!-- 搜索建议列表 -->
  32. <div id="suggest-list"></div>
  33. </div>
  34. </div>
  35. <!-- 模板结构 -->
  36. <script type="text/html" id="tpl-suggestList"> { { each result}} <div class="suggest-item">{ { $value[0]}}</div> { { /each}} </script>
  37. <script> $(function() { // 1、定义防抖的延时器 timer var timer = null; // 定义全局缓存对象 var cacheObj = { }; // 定义防抖函数,延时500毫秒后,再请求数据接口 function debounceSearch(kw) { // 开启延时器 timer = setTimeout(function() { getSuggestList(kw); }, 500) } // 为输入框绑定Keyup事件 $('#ipt').on('keyup', function() { // 清空timer clearTimeout(timer); var keywords = $(this).val().trim(); if (keywords.length <= 0) { // 如果用户没有输入内容,则退出并清空隐藏列表 return $('#suggest-list').empty().hide() } // 发起请求之前,先判断缓存里是否有数据 if (cacheObj[keywords]) { return renderSuggestList(cacheObj[keywords]); } // TODO:获取搜索建议列表 // console.log(keywords); // 调用自定义函数 // getSuggestList(keywords); debounceSearch(keywords); }) // 获取搜索建议的函数封装 function getSuggestList(kw) { $.ajax({ url: 'https://suggest.taobao.com/sug?q=' + kw, // 发起JSONP请求 dataType: 'jsonp', success: function(res) { renderSuggestList(res); } }) } // 渲染UI结构 // 传入一个res参数(res就是待渲染的数据) function renderSuggestList(res) { // 判断是否有待渲染的数据,如果没有就return出去,清空列表并隐藏 if (res.result.length <= 0) { return $('#suggest-list').empty().hide(); } // 调用模板引擎的template函数 var htmlstr = template('tpl-suggestList', res); // 返回一个渲染好的html结构 // 将渲染好的字符串放到搜索建议列表div中,并展示出来 $('#suggest-list').html(htmlstr).show(); // 1、获取到用户输入的内容,当做键 var k = $('#ipt').val().trim(); // 2、将数据做为值缓存到全局对象中 cacheObj[k] = res; } }) </script>
  38. </body>
  39. </html>

至此,整个案例完成。

全套案例 源码 保存:

百度网盘:https://pan.baidu.com/s/1x9lVxBRxQplctihB1PRdnw    提取码:1w9a

发表评论

表情:
评论列表 (有 0 条评论,299人围观)

还没有评论,来说两句吧...

相关阅读

    相关 前端JSONP详解

    为什么会产生跨域 首先,跨域是针对客户端而言的,服务端是不存在跨域安全限制的。 **由于浏览器同源策略(同一协议,同一域名,同一端口号)的限制,非同源下的请求,都会...

    相关 jsonp

    我是做的一个跨站显示信息!! 鄙人文化不高,代码不严谨,仅供参考! 题目:用户在a站访问过的商品足迹可以在登录b站之后查看足迹! 首先创建两个域名www.a.com

    相关 jsonp

    jsonp跨域 Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src这个属性的标签都拥有跨域的能力,比如`<script>、<img>、<

    相关 jsonp

    域指的就是域名。 域名对应的是一个IP地址。 域名与IP地址的对应关系存储在域名服务器上。(DNS)   所谓跨域     1.就是跨域名,跨端口,跨协议