Jquery相关

jQuery01

曾经的年代, jQuery一家独大, 前端必学的框架

作用: 利用封装技巧, 把 DOM 操作进行了封装, 提供了一个简单易用的框架

官方理念: Write less, do More 写的少 做的多

实际开发中, 很少书写 原生的DOM 代码, 因为太长!

仿写

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>选修-jQuery仿写</title>
</head>
​
<body>
  <div>Hello</div>
  <div>World</div>
​
  <script>
    // 原生DOM: 修改两个div的颜色 -- red
    const items = document.querySelectorAll('div')
    items.forEach(item => item.style.color = 'red')
​
    // 封装: 只要一次, 以后就可以随时复用
    function $(selector) {
      return document.querySelectorAll(selector)
    }
​
    // 向原型 NodeList 中,添加一个css方法
    NodeList.prototype.css = function (name, value) {
      // name: 是变量, 要用 [] 语法来赋值
      // items.forEach(item => item.style.color = 'red')
      this.forEach(item => item.style[name] = value)
    }
​
    // 访问器的方括号语法
    // var a = 'gege'
    // var obj = {}
    // obj[a] = '格格' // gege   []中的变量会换成其值
    // obj.a = '家乐' // a  点语法 写什么是什么
​
    const a = $('div') //结果同 items
    console.log(a);
​
    // 经过封装后: 希望如下写法
    $('div').css('color', 'blue')
    $('div').css('border', '2px solid gray')
  </script>
</body>
​
</html>

选择器

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>选择器</title>
</head>
​
<body>
  <div id="box">
    <button>111</button>
    <p>Hello</p>
    <p>World</p>
  </div>
​
  <!-- 使用第三方时, 需要先引入 -->
  <!-- 脚本通常分两个版本: 开发版 和 产品版 -->
  <!-- 开发版: 带注释,缩进 , 给人看 但是体积大 -->
  <!-- 产品版: 删除了注释和缩进, 作为产品, 体积小 -->
  <script src="./vendor/jquery-3.6.0.js"></script>
​
  <script>
    // 原生DOM: 区分1个还是多个, 采用不同方法
​
    // 作者: 不需要用户区分个数, 统一查询出类数组 类型的对象
​
    // $: 函数名,  值是css选择器
    console.log($('button'))
    console.log($('p'))
    // 作者为查询出来的类数组的原型中: 添加了大量的方法可以使用
    // 比如 css ,可以自动遍历添加 样式
    $('p').css('color', 'red')
  </script>
</body>
​
</html>

css

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>css</title>
</head>
​
<body>
  <div>Hello</div>
  <div>World</div>
  <div>Vue</div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 本质: $ 就是 document.querySelectorAll('div')
    $('div').css('color', 'blue')
​
    // jQuery作者 大量采用了 函数重载 技巧
    // 函数重载: 通过判断 参数的个数 或 类型不同, 执行不同的逻辑代码
​
    // css只有1个参数 且 是字符串: 则返回此样式的值
    console.log($('div').css('color'))
​
    // css只有1个参数 且 是对象: 则
    $('div').css({
      border: '1px solid black',
      backgroundColor: 'green',
      padding: '10px',
      margin: '5px'
    })
  </script>
</body>
​
</html>

事件

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>事件</title>
</head>
​
<body>
  <button>11</button>
  <button>22</button>
  <button>33</button>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 事件要做为参数, 传递给 click 方法
    // 底层: 自动遍历选中的元素, 挨个 = 传入的方法
    $('button').click(function () {
      console.log(this)
    })
  </script>
</body>
​
</html>

仿写

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>仿写</title>
</head>
​
<body>
  <button>111</button>
  <button>222</button>
​
  <script>
    // 选修: 仿写click
    function $(s) {
      return document.querySelectorAll(s)
    }
​
    // $(..).click(函数)  函数传递给 fn
    NodeList.prototype.click = function (fn) {
      // 遍历找到的元素, 挨个=fn
      this.forEach(item => item.onclick = fn)
    }
​
    //
    $('button').click(function () { console.log(this) })
  </script>
</body>
​
</html>

class

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>class</title>
  <style>
    #box {
      user-select: none;
    }
​
    #box>span {
      display: inline-block;
      background-color: #aaa;
      width: 80px;
      text-align: center;
      border-radius: 4px;
      line-height: 30px;
      margin: 0 10px 10px 0;
    }
​
    #box>span.active {
      background-color: orange;
      color: white;
    }
  </style>
</head>
​
<body>
  <div id="box">
    <span class="active">vue</span>
    <span>dom</span>
    <span>js</span>
    <span>express</span>
    <span>mysql</span>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // $():选择元素   JQ的方法们 自带遍历
    $('#box span').click(function () {
      // this: 运行时所在的对象
      // this.classList.add('active')
      console.log('this:', this);
      // this是DOM元素, 但是: 要想对DOM元素采用jQuery的语法
      // 必须把 DOM 转变成 jQuery 类型的对象
      // $(this): 把 this 即当前DOM元素, 装载到 jQuery 对象里
      console.log($(this))
​
      // siblings: 兄弟姐妹
      // 当前元素.添加(active).兄弟姐妹们.移除(active)
      $(this).addClass('active').siblings().removeClass('active')
    })
  </script>
</body>
​
</html>

练习

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>练习</title>
  <style>
    #box {
      user-select: none;
    }
​
    #box>span {
      display: inline-block;
      width: 90px;
      text-align: center;
      line-height: 90px;
      background-color: #aaa;
      transition: 0.4s;
    }
​
    #box>span.active {
      background-color: orange;
      border-radius: 50%;
      color: white;
    }
  </style>
</head>
​
<body>
  <h3>请选择英雄:</h3>
  <div id="box">
    <span class="active">德莱文</span>
    <span>万豪</span>
    <span>提莫</span>
    <span>纳尔</span>
    <span>猫咪</span>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#box>span').mouseenter(function () {
      $(this).addClass('active').siblings().removeClass('active')
    })
  </script>
</body>
​
</html>

显示与隐藏

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>显示与隐藏</title>
​
  <style>
    #box {
      width: 300px;
      height: 300px;
      margin-top: 10px;
      background-color: royalblue;
    }
  </style>
</head>
​
<body>
  <button>显示</button>
  <button>隐藏</button>
  <button>切换</button>
​
  <div id="box"></div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 考虑到 3个按钮都要操作 box, 提前查询出来备用
    // 一种约定俗成的规范: jQuery类型的变量, 用 $ 开头, 非强制
    // 类似: 结婚后 应该带婚戒, 一看就知道已婚. -- 不强制
    const $box = $('#box')
​
    // 找到第一个按钮
    $('button:first-child').click(function () {
      $box.show()  //show:显示
    })
​
    // 第二个按钮
    console.log($('button'))
    // 可以通过序号(从0开始数) 从查询结果中读取某个元素
    // 注意: 序号不是 nth-child, 是指查询结果中的元素序号
    // eq: equal缩写, 等于
    $('button:eq(1)').click(function () {
      $box.hide() //hide:隐藏
    })
​
    // 读取按钮中, 序号2 的
    $('button').eq(2).click(function () {
      // 参数可选, 代表动画时长: 'slow' 'fast' 或者 毫秒数
      $box.toggle(2000) // toggle:切换
    })
  </script>
</body>
​
</html>

菜单

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>菜单</title>
  <style>
    #menu {
      user-select: none;
    }

    /* #menu:hover>div:last-child {
      display: block;
    } */

    #menu>div:first-child {
      font-size: 1.2em;
      background-color: #eee;
      padding: 5px;
    }

    #menu>div:last-child {
      padding: 10px;
      background-color: #ccc;
      display: none;
    }
  </style>
</head>

<body>
  <div id="menu">
    <div>1号佳丽: 雷佳乐</div>
    <div>
      <div>肤白</div>
      <div>貌美</div>
      <div>大长腿</div>
      <div>唱跳rap,打篮球</div>
    </div>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#menu>div').eq(0).click(function () {
      // 下一个兄弟, 原生: nextElementSibling
      // next(): 获取下一个兄弟
      // $(this).next().toggle()

      // slideToggle: 滑动切换, 参数 slow fast 毫秒数字
      // 1000毫秒 = 1秒
      $(this).next().slideToggle(100)
    })
  </script>
</body>

</html>

练习

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>练习</title>
  <style>
    #ad {
      background-color: antiquewhite;
      position: fixed;
      width: 140px;
      height: 200px;
      bottom: 10px;
      right: 10px;
    }
  </style>
</head>

<body>
  <div id="ad">
    <button>关闭</button>
    <div>
      震惊! 家乐的妻子竟然是它?
    </div>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#ad button').click(function () {
      // 原生读取父元素: parentElement
      // $(this).parent().hide(1000)

      // slide:滑动   slideUp: 滑动收起
      // 参数2: 动画结束后的回调函数
      $(this).parent().slideUp(2000, function () {
        alert('真的不再看看嘛?')
        $(this).slideDown(2000) //滑动展开 -- 显示
      })
    })
  </script>
</body>

</html>

属性操作

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>属性操作</title>
</head>

<body>
  <a href="http://tmooc.cn" id="a1" data-xx="111"></a>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 属性读取分两种方式:
    // 旧方案: getAttribute  setAttribute
    // 新方案: .属性名  .属性名=值

    // jQuery提供了两种操作属性的方案: prop(新方案)  attr(旧方案)
    const $a = $('a')
    console.log($a.attr('href'))
    console.log($a.attr('id'))
    console.log($a.attr('data-xx'))
    //修改
    $a.attr('href', 'http://www.baidu.com')

    // prop: 底层实现方式 是 DOM的新方案  元素.属性名
    console.log($a.prop('href'));
    console.log($a.prop('id'));
    $a.prop('href', 'http://douyu.com')

    // 自定属性读取: 专业的 data
    console.log($a.data('xx')) // data-xx

    // property : 财产,资源, 属性
    // 实践中: 推荐使用 prop 来读取系统属性,  data 读取自定义属性
    // attr 使用较少
  </script>
</body>

</html>

大小图切换

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>大小图切换</title>
  <style>
    body {
      background-color: #eee;
    }

    #box {
      user-select: none;
      width: 400px;
    }

    #box>img {
      width: 100%;
    }

    #box>div>img {
      width: 23%;
      /* transparent: 透明  */
      border: 2px solid transparent;
    }

    #box>div>img.active {
      border-color: orangered;
    }
  </style>
</head>

<body>
  <div id="box">
    <img src="./imgs/1_lg.jpg" alt="">
    <div>
      <!-- 利用自定义属性, 在小图上绑定 大图的名字 -->
      <img data-big="1_lg.jpg" class="active" src="./imgs/1.sm.jpg" alt="">
      <img data-big="2.lg.jpg" src="./imgs/2.sm.jpg" alt="">
      <img data-big="3.lg.jpg" src="./imgs/3.sm.jpg" alt="">
      <img data-big="4.lg.jpg" src="./imgs/4.sm.jpg" alt="">
    </div>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#box>div>img').mouseenter(function () {
      $(this).addClass('active').siblings().removeClass('active')

      // 自定义属性读取?  data
      const big = $(this).data('big')
      // src属性是否是 系统提供的?  是 ; 用 prop
      // src的值是路径, big只是图片名, 必须拼接成相对路径再用
      $('#box>img').prop("src", './imgs/' + big)
      console.log('./imgs/' + big);
      // img.src(参数1) = 值(参数2)
      // 原理同: css的仿写
    })
  </script>
</body>

</html>

标签栏

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>标签栏</title>
  <style>
    #tabs {
      user-select: none;
      width: 500px;
      background-color: #eee;
    }

    #tabs>div:first-child>span {
      display: inline-block;
      width: 120px;
      line-height: 40px;
      text-align: center;
    }

    #tabs>div:first-child>span.active {
      background-color: red;
      color: white;
    }

    #tabs>div:last-child>div {
      height: 200px;
      padding: 10px;
      border: 1px solid brown;
      margin-top: 1px;
    }

    /* 没有 active 样式的, 隐藏 */
    #tabs>div:last-child>div:not(.active) {
      display: none;
    }
  </style>
</head>

<body>
  <div id="tabs">
    <div>
      <!-- 通过自定义属性, 保存标题 对应的 详情元素的id -->
      <span data-id="tab1" class="active">商品介绍</span>
      <span data-id="tab2">规格与包装</span>
      <span data-id="tab3">售后保障</span>
      <span data-id="xxyy">家乐购物会</span>
    </div>
    <div>
      <div id="xxyy">家乐购物会...</div>
      <div id="tab1" class="active">商品介绍...</div>
      <div id="tab2">规格与包装...</div>
      <div id="tab3">售后保障...</div>
    </div>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#tabs>div:eq(0)>span').click(function () {
      $(this).addClass('active').siblings().removeClass('active')

      const id = $(this).data('id') //读取标题上存储的自定义属性
      // 假设 id='tab1',  
      // 下方拼接出的 '#tabs #tab1'
      $(`#tabs #${id}`).addClass('active').siblings().removeClass('active')
    })
  </script>
</body>

</html>

标签内容

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>标签内容</title>
</head>

<body>
  <div id="box">
    <a href="http://tmooc.cn">Go Tmooc</a>
  </div>

  <div id="app"></div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 读取标签内容有两种方式:
    // 1. innerHTML: 读取标签中的 HTML代码+文本
    // 2. innerText: 读取标签中的 文本
    console.log($('#box').html()) // HTML + 文本
    console.log($('#box').text()) // 文本

    // 设置文本
    $('#box').html('<h1>Hello</h1>') // 当做HTML解析
    $('#app').text('<h1>Hello</h1>') // 当做文本展示, 不解析

    // 累加拼接: 没有 += , 只能读取出来, 拼接, 再设置回去
    $('#app').html($('#app').html() + '333')
  </script>
</body>

</html>

总结

jQuery: 一套封装DOM操作 而成的 第三方.

理念: Write Less, do More! 写的少做的多

  • FTP上已提供的 PDF 包含了所有 jQuery 的方法说明, 推荐看一看

  • 晚上作业: 把DOM部分 前3天的的练习, 都用 jQuery 改写一次

  • 关于考试题: 把 DOM 和 JS高级的 考试题做一遍

    DOM_2202

    JSCORE_2202

  • jQuery的原理: 最好能看懂

    • 前提条件: JS高级讲解的 原型理论

  • 关于作业: 轮播图必须要做, 明天要讲解更加高级的轮播图 -- 无缝衔接的循环滚动

jQuery原理

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>选修-jQuery仿写</title>
</head>

<body>
  <div>Hello</div>
  <div>World</div>

  <script>
    // 原生DOM: 修改两个div的颜色 -- red
    const items = document.querySelectorAll('div')
    items.forEach(item => item.style.color = 'red')

    // 封装: 只要一次, 以后就可以随时复用
    function $(selector) {
      return document.querySelectorAll(selector)
    }

    // 向原型 NodeList 中,添加一个css方法
    NodeList.prototype.css = function (name, value) {
      // name: 是变量, 要用 [] 语法来赋值
      // items.forEach(item => item.style.color = 'red')
      this.forEach(item => item.style[name] = value)
    }

    // 访问器的方括号语法
    // var a = 'gege'
    // var obj = {}
    // obj[a] = '格格' // gege   []中的变量会换成其值
    // obj.a = '家乐' // a  点语法 写什么是什么

    const a = $('div') //结果同 items
    console.log(a);

    // 经过封装后: 希望如下写法
    $('div').css('color', 'blue')
    $('div').css('border', '2px solid gray')
  </script>
</body>

</html>

jQuery02

复习

jQuery

  • 是利用封装技术, 把 DOM 操作封装之后 得到的一个扩展

  • 理念: Write Less, Do More 写的少,做的多

  • 选择器: 用$代替document.querySelectorAll

  • 方法: jQuery方法都自带遍历

    • css: 设置内联样式, 有3种用法 -- 函数重载技术

      • css(样式名, 值): 单独设置某个样式

      • css(对象): 设置多个样式

      • css(样式名): 读取此样式的值

    • 事件: 例如 click mouseenter ...

      • $(...).事件( function(){} )

    • class相关

      • addClass: 添加

      • removeClass: 删除

    • 元素的选择:

      • siblings(): 选择所有兄弟元素

      • next(): 下一个兄弟元素

      • parent(): 父元素

      • eq(): 通过序号选择

    • 显示和隐藏

      • show(显示) hide(隐藏) toggle(切换)

      • slideUp 滑动收起; slideDown: 滑动展开; slideToggle: 滑动切换

    • 属性操作

      • attr: 万能, 源码中采用 setAttribute..

      • prop: 系统属性读取

      • data: 自定义属性

    • 标签内容:

      • html

      • text

作业

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>作业</title>
  <style>
    h2 {
      color: red;
    }
​
    #box {
      user-select: none;
    }
​
    #box>span {
      width: 140px;
      line-height: 40px;
      text-align: center;
      border: 2px solid gray;
      color: gray;
      margin: 0 10px 10px 0;
      display: inline-block;
      border-radius: 4px;
    }
​
    #box>span.active {
      color: red;
      border-color: red;
    }
  </style>
</head>
​
<body>
  <h2>4899</h2>
  <div id="box">
    <!-- 利用自定义属性, 存储每项的价格 -->
    <span data-price="4899" class="active">12G+512GB</span>
    <span data-price="3999">8GB+256GB</span>
    <span data-price="3699">8G+128GB</span>
    <span data-price="4399">12G+256GB</span>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // DOM操作的核心: 找到你要操作的元素, 然后 操作他
    $('#box span').click(function () {
      // 当前项.添加active.兄弟项.删除active
      // this: 代表原生的DOM元素
      // this - 钢铁侠    $(this): 穿上装甲的钢铁侠 --强大的功能
      $(this).addClass('active').siblings().removeClass('active')
​
      const price = $(this).data('price')
      $('h2').html(price) // html -> innerHTML
    })
​
  </script>
​
</body>
​
​
</html>

轮播图

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>轮播图</title>
  <style>
    #banner {
      user-select: none;
      overflow: hidden;
      border: 2px solid red;
      width: 600px;
      /* 子绝父相 */
      position: relative;
    }
​
    #banner>div:last-child {
      position: absolute;
      bottom: 5px;
      /* border: 2px solid red; */
      width: 100%;
      text-align: center;
    }
​
    #banner>div:first-child {
      display: flex;
    }
​
    #banner img {
      width: 600px;
      transition: 0.5s;
    }
​
    /* 移动第一个图片, 剩余图片会随着变化 */
    #banner img:first-child {
      /* margin-left: -000%; */
      /* margin-left: -100%; */
    }
​
    #banner span {
      display: inline-block;
      width: 14px;
      height: 14px;
      border-radius: 50%;
      background-color: aqua;
    }
​
    #banner span.active {
      background-color: orange;
    }
  </style>
</head>
​
<body>
  <div id="banner">
    <div>
      <img src="./imgs/banner1.png" alt="">
      <img src="./imgs/banner2.png" alt="">
      <img src="./imgs/banner3.png" alt="">
      <img src="./imgs/banner4.png" alt="">
    </div>
    <div>
      <span class="active"></span>
      <span></span>
      <span></span>
      <span></span>
    </div>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#banner span').mouseenter(function () {
      $(this).addClass('active').siblings().removeClass('active')
      // jQuery提供了 index 方法, 用来获取指定元素的序号
      // [家乐, 鑫鑫, 波波].index(家乐) :  0  -- 代表家乐是序号0的
      // $('#banner span'): 查询到所有的span 小圆点
      // this: 当前的 span 小圆点
      const i = $('#banner span').index(this)
      console.log('i:', i)
​
      // 第一张图的 margin-left
      // $('#banner img:eq(0)').css('margin-left', -i + '00%')
      $('#banner img').css('transform', `translateX(${-i}00%)`)
      console.log(-i + '00%');
    })
​
    // 每两秒钟滚动一次
    setInterval(() => {
      // 当前激活的小圆点的 下一个
      let $next = $('#banner span.active').next()
      console.log($next)
      // 数组长度 length  1代表找到1个 0没找到
      if ($next.length == 0) {
        // 如果没找到, 则触发第一个小圆点
        $next = $('#banner span:eq(0)')
      }
​
      // 触发其 mounseenter 事件
      $next.mouseenter()  //直接用()触发, 不传参就是触发事件
    }, 2000);
​
    // var a = '家乐'
    // console.log('我喜欢a') // 这句话会打印出  我喜欢家乐 吗?
    // console.log(`我喜欢${a}`) // 这句话会打印出  我喜欢家乐 吗?
  </script>
</body>
​
</html>

自定义动画

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>自定义动画</title>
    <style>
      #box {
        width: 100px;
        height: 100px;
        background-color: gray;
        position: relative;
      }
    </style>
  </head>
​
  <body>
    <button>开始动画</button>
    <button>结束动画</button>
    <div id="box"></div>
​
    <script src="./vendor/jquery-3.6.0.js"></script>
    <script>
      $("button:eq(0)").click(function () {
        // animate(): 设置动画效果
        // 参数1: 目标css样式   参数2: 动画时长   参数3:完成后的回调
        $("#box").animate({
          borderRadius: "50%",
          top: "100px",
          left: "200px",
        });
​
        // 动画队列: 书写多个动画, 则会依次执行
        $("#box").animate({ left: 0 }).animate({ top: 0 });
​
        // animate:不支持 颜色 和 transform
        // 参数2: 持续时长,  单位 毫秒
        // 参数3: 动画完成后的回调
        $("#box").animate({ borderRadius: 0 }, 1000, function () {
          alert("动画执行完毕!");
        });
      });
​
      // 停止动画
      $("button:eq(1)").click(function () {
        // 默认: 停止当前动画, 开始下一次的动画
        // 参数1: boolean类型, 代表是否要停止整个动画队列
        // 参数2: 停止时, 是否立刻变为动画的最终效果
        $("#box").stop(true, true);
      });
    </script>
  </body>
</html>
​

循环轮播图

评分

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>评分</title>
  <style>
    #score>img {
      width: 50px;
      height: 50px;
    }
  </style>
</head>
​
<body>
  <h2>1</h2>
  <div id="score">
    <img src="./imgs/pj1.png" alt="">
    <img src="./imgs/pj0.png" alt="">
    <img src="./imgs/pj0.png" alt="">
    <img src="./imgs/pj0.png" alt="">
    <img src="./imgs/pj0.png" alt="">
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#score img').mouseenter(function () {
      // 获取当前项的序号
      const i = $('#score img').index(this)
      const src = `./imgs/pj${i + 1}.png`
      console.log('src:', src);
​
      $(this).prop('src', src)
      // prevAll:  前方所有的兄弟
      $(this).prevAll().prop('src', src)
      // nextAll: 后面的所有兄弟
      $(this).nextAll().prop('src', './imgs/pj0.png')
​
      $('h2').html(i + 1)
    })
  </script>
</body>
​
</html>

准备就绪

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>准备就绪</title>
  <script src="./vendor/jquery-3.6.0.js"></script>
  <!-- 代码从上 向下执行, 执行脚本时, DOM元素还没加载, 所以不好用
  理论上: JS代码应该书写在 body 的最后面
  -->
  <!-- 实际工作中: 往往要把 JS 代码书写在外部的js文件 -->
  <script>
    $('#box').css('color', 'green')
  </script>
​
  <script src="./06.js"></script>
</head>
​
<body>
  <div id="box">加油, 小马! 站起来</div>
​
  <!-- 正常人引入外部脚本, body最后 -->
  <!-- <script src="./06.js"></script> -->
</body>
​
</html>
// 实际工作时, 往往会团队合作
// 人员的技术能力 参差不齐, 例如 家乐就有极大的可能 把 外部js 在head中引入, 那就会失效
// 家乐肯定会想: 什么垃圾框架, 都不好用!
​
// 作为高手写代码: 一定要 防御性编程 -- 让不会用的人一样能好用
​
// 监听: DOM加载完毕的时机, 再调用方法
// window.onload = function(){
//   // 页面加载完毕时, 才自动调用
//   $('#box').css('border', '2px solid red')
// }
​
// jQuery进行了封装, 提供更简单的书写方式
// $(函数): 在DOM加载完毕时, 自动触发函数
$(function(){
  $('#box').css('border', '2px solid red')
})
​
// 稍微复杂点的写法, 没人用, 但是你要知道
// $(document).ready(function(){
//   $('#box').css('border', '2px solid red')
// })

动态新增数据

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>数据的动态新增</title>
  <style>
    #box {
      padding: 10px;
      background-color: #eee;
    }
  </style>
</head>
​
<body>
  <button id="add">新增数据</button>
​
  <div id="box">
    <button>家乐</button><button>天宝</button>
    <button>蔡瑶</button>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#add').click(function () {
      // box.innerHTML += '<button>小龙</button>'
​
      // append: 添加子元素
      $('#box').append('<button>小龙</button>')
    })
​
    // 事件委托: jQuery提供专门的 on 方法, 实现委托
    // on: 当....时
​
    // 参数1: 事件名, 例如 click  mouseenter  keyup...
    // 参数2: 过滤 -- 过滤出指定的 事件当事人, this指向当事人
    // 参数3: 回调函数
    $('#box').on('click', 'button', function () {
      // 冒泡: 怎么获取谁触发的事件  e.target
      console.log('点击:', this);
      $(this).remove() // remove: 删除元素自身
    })
  </script>
</body>
​
</html>

待办事项

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>待办事项</title>
</head>
​
<body>
  <div>
    <input type="text" placeholder="请输入待办事项">
    <!-- 表单元素都具有的 disabled 属性, 不可用 -->
    <button disabled>确定</button>
  </div>
  <ul>
    <li>
      <span>吃饭</span><button>删除</button>
    </li>
    <li>
      <span>睡觉</span><button>删除</button>
    </li>
    <li>
      <span>打亮亮</span><button>删除</button>
    </li>
  </ul>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 输入框的值实时变化监听
    // 作者没有封装  input 事件, 只能通过通用的 on 方式添加
    $('input').on('input', function () {
      console.log(this.value);
      // disabeld: 不可用
      // if (this.value == '') {
      //   $(this).next().prop('disabled', true)
      // } else {
      //   // 不 不可用 -> 可用
      //   $(this).next().prop('disabled', false)
      // }
​
      // 空字符串 -> false -> !false -> true
      $(this).next().prop('disabled', !this.value)
    })
​
​
    // 考虑到 子元素会动态新增, 所以给父元素添加委托
    $('ul').on('click', 'button', function () {
      // this指向 参数2 过滤出来的元素
      console.log('this:', this);
      $(this).parent().remove()
    })
​
    $('div>button').click(function () {
      // jQuery类型的元素, 存储在变量里, 最好是 $ 开头
      const $inp = $(this).prev() //prev: 上一个元素
      // 输入框的值: 原生value  JQ: val
      const kw = $inp.val()
      console.log($inp);
      console.log(kw);
​
      $('ul').append(`<li>
        <span>${kw}</span><button>删除</button>
      </li>`)
​
      // 把输入框的value 改成 空字符串
      $inp.val('') // val(): 如果传参, 就是赋值操作
      // 点击确定按钮后, 让其不可用
      $(this).prop('disabled', true)
    })
​
    // 键盘:
    $('input').keyup(function (e) {
      // 按键编号13 是回车
      if (e.keyCode == 13) {
        // 触发 确定按钮相同的操作
        // 判断按钮 可以用, 再触发
        const $btn = $('div>button')
        // 不不可用 == 可用: 双重否定表肯定
        !$btn.prop('disabled') && $btn.click()
        // 逻辑短路:  逻辑与中,  前面是真的, 才会执行后续的
      }
    })
​
    // 操作动态新增的子元素 -- 用委托
  </script>
</body>
​
</html>

作业

  • 考试题满分

  • jQuery练习

    • 把本周的所有练习, 用JQ实现

jQuery03

回顾

jQuery是一个 利用封装技巧, 把DOM操作进行封装后得到的框架

  • 理念:Write Less, do More 写的少做的多

核心操作分两类:

  • 查找到目标元素: $(选择器)

    • 查询结果是一个 类数组 类型, 其原型中充满各种相关方法

  • 操作查找到的元素

    • 每个方法内部,都会自动遍历, 为每个元素都添加

    • 大量采用函数重载技巧: 函数根据参数的个数类型不同, 产生不同的效果

      • 例如css:

        • css(属性名, 值): 设置一组属性和值

        • css(属性名): 读取指定属性的值

        • css(对象类型): 一次性设置多个

      • 例如click

        • click(函数): 为每个元素绑定事件

        • click(): 触发元素上的事件

克隆

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>克隆</title>
  <style>
    #box1 {
      padding: 10px;
      background-color: lightcoral;
    }
  </style>
</head>
​
<body>
  <div id="box">
    <button>红烧牛肉</button>
    <button>鲜虾鱼板</button>
    <button>老坛酸菜</button>
    <button>香辣牛肉</button>
    <button>小鸡炖蘑菇</button>
  </div>
​
  <hr>
  <h3>今日午餐:</h3>
  <div id="box1"></div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 点击 div#box 中的 按钮, 把这个按钮添加到 div#box1 的子元素中
    $('#box button').click(function () {
      // clone: 复制元素
      const c = $(this).clone()
      // 把复制出来的, 添加到子元素
      $('#box1').append(c)
    })
  </script>
</body>
​
</html>

替换

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>替换</title>
</head>
​
<body>
  <div id="box">
    家乐的男神是: <button>胡歌</button>
  </div>
  <hr>
  <div id="box1">
    <button>胡歌</button>
    <button>彭于晏</button>
    <button>杨洋</button>
    <button>智超</button>
    <button>陈浪浪</button>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 委托: 给父元素加事件, 监听指定的子元素button
    $('#box1').on('click', 'button', function () {
      // replace: 替换     with: 和...
      $("#box>button").replaceWith($(this).clone())
    })
  </script>
</body>
​
</html>

序号相关

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>序号相关选择器</title>
</head>
​
<body>
  <ul>
    <li>楠姐0</li>
    <li>楠姐1</li>
    <li>楠姐2</li>
    <li>楠姐3</li>
    <li>楠姐4</li>
    <li>楠姐5</li>
    <li>楠姐6</li>
  </ul>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 以下都是根据 查询出来的 元素的序号进行操作
    console.log($('li'))
​
    // even  -- 偶数,  4个字母
    // odd   -- 奇数,  3个字母
    $('li:even').css('background-color', 'gray')
​
    $('li:odd').css('background-color', 'blue')
​
    // lt : less than 小于
    // gt:  greater than  大于
    $('li:lt(3)').css('color', 'red')
    $('li:gt(4)').css('color', 'green')
​
    // eq: 等于 equal
    $('li:eq(3)').css('padding', '10px')
​
  </script>
</body>
​
</html>

包含关系

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>包含关系选择器</title>
</head>
​
<body>
  <ul>
    <li>楠姐666</li>
    <li>亮哥888</li>
    <li>铭铭322</li>
    <li>家乐678</li>
  </ul>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 把标签内容中含有 6 的标红
    // contains :包含
    $('li:contains(6)').css('color', 'red')
​
    // 练习: 把 包含  哥  字的标签 变蓝 blue
    $('li:contains(哥)').css('color', 'blue')
​
    // :not()  不, 反向
    $('li:not(:contains(哥))').css('border', '2px red solid')
​
    // 感兴趣, 查文档:  find 方法
    // 在选出来的元素里, 接着进行选择
  </script>
</body>
​
</html>
<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>包含关系</title>
</head>
​
<body>
  <div></div>
  <div>
    <a href="">Tmooc</a>
  </div>
  <div>
    <button>我是按钮</button>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 查找到 空的div,  empty
    $('div:empty').css({
      height: '30px', border: '3px solid red'
    })
​
    // 查找到 非空的div,  parent 父母
    $('div:parent').css('border', '2px dashed green')
​
    // 把带有按钮子元素的div
    // has: 有.   
    $('div:has(button)').css('padding', '10px')
  </script>
</body>
​
</html>

ajax

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ajax</title>
  <style>
    #box {
      user-select: none;
      width: 800px;
      margin: 0 auto;
    }
​
    #box>div {
      display: flex;
      /* 空白在中间间隔 */
      justify-content: space-between;
      padding: 10px;
      border-bottom: 1px dashed gray;
    }
  </style>
</head>
​
<body>
  <div id="box">
    <!-- 套路: 应该先用假数据 配合 css 做出效果, 然后换成真数据 -->
    <div>
      <span>题目</span>
      <span>时间</span>
    </div>
  </div>
​
  <!-- Ajax: 利用 JS 来发送网络请求, 从服务器获取数据 -->
  <!-- 前提:要有网 -->
  <!-- 原生的Ajax使用起来颇为繁琐, 在 jQuery中作者进行了封装 -->
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 这是用PHP制作的服务器接口, 可以直接使用
    const url = 'http://www.codeboy.com:9999/mfresh/data/news_select.php'
​
    // 请求分多种, 其中 GET 和 POST 最常见
    // get: 封装得到的发送get请求的方法
    // 参数1: 请求的接口地址    参数2: 成功后的回调函数
​
    // 对于数据是哪里来的感兴趣 - 复习亮亮的 express
​
    // $.取餐(隔壁的肯德基, 外卖 => { })
    $.get(url, data => {
      console.log(data)
      // 先把数据映射成 HTML代码的数组
      const a = data.data.map(value => {
        const { title, pubTime } = value
        // 真数据, 替换掉 假数据
        return `<div>
          <span>${title}</span>
          <span>${pubTime}</span>
        </div>`
      })
​
      console.log(a)
      // 拼接成字符串, 放到box里
      // jQuery: 当检测到内容是数组, 会自动拼接成字符串
      // $('#box').html(a) //做法1: innerHTML, 覆盖效果
​
      // 做法2:  append: 添加子元素, 累加效果
      $('#box').append(a)
    })
  </script>
</body>
​
</html>

练习

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>练习</title>
</head>
​
<body>
  <div id="box">
    <div>title1 - model - func</div>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    const url = 'http://www.codeboy.com:9999/mfresh/data/product_select.php'
​
    // 发请求, 获取数据, 转换成HTML代码, 添加到 box 里
    // const $ = { get:function(){} }
    // $.get()
​
    $.get(url, data => {
      console.log(data)
​
      const a = data.data.map(({ title1, func, model }) => {
        // const {title1, func, model} = value
        return `<div>${title1} - ${model} - ${func}</div>`
      })
​
      $('#box').html(a)
    })
  </script>
</body>
​
</html>
<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- 图片经常有防盗链 403, 只要添加如下代码: -->
  <meta name="referrer" content="no-referrer">
​
  <title>练习</title>
</head>
​
<body>
  <div id="box">
    <div>
      <div>标题</div>
      <div>详情</div>
      <!-- 图片后台报错 是正常的, 有防盗, 需要特殊处理 -->
      <img src="" alt="">
    </div>
  </div>
​
  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    const url = 'https://api.xin88.top/bilibili/recommends.json'
​
    $.get(url, data => {
      console.log(data);
​
      const a = data.data.map(value => {
        // JS高级第五天
        const { title, summary, image_urls: [url] } = value
​
        return `<div>
          <div>${title}</div>
          <div>${summary}</div>
          <img src="${url}" alt="">
        </div>`
      })
​
      $('#box').html(a)
    })
  </script>
</body>
​
</html>

番剧

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- 阻止防盗链 -->
  <meta name="referrer" content="no-referrer">
  <title>番剧</title>
  <style>
    #box>div {
      margin: 0 10px 10px 10px;
      display: inline-block;
      width: 150px;
      border: 1px solid gray;
    }

    #box>div>img {
      width: 150px;
    }
  </style>
</head>

<body>
  <div id="box">
    <div>
      <img src="" alt="">
      <div>标题</div>
    </div>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    const url = 'https://api.xin88.top/bilibili/timeline.json'

    $.get(url, data => {
      console.log(data)

      const a = data.result.map(({ title, square_cover }) => {
        return `<div>
          <img src="${square_cover}" alt="">
          <div>${title}</div>
        </div>`
      })

      $('#box').html(a)
    })
  </script>
</body>

</html>

练习

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>练习</title>
  <meta name="referrer" content="no-referrer">

  <style>
    #box>div {
      display: flex;
      margin: 10px;
    }

    #box>div>img {
      width: 170px;
      border-radius: 3px;
      margin-right: 10px;
    }

    #box>div>div {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }

    #box>div>div>div {
      color: gray;
      display: flex;
      flex-direction: column;
      font-size: 0.9em;
    }
  </style>
</head>

<body>
  <div id="box">
    <div>
      <img src="" alt="">
      <div>
        <span>题目</span>
        <div>
          <span>全12话</span>
          <span>xxx万播放 xx万弹幕</span>
        </div>
      </div>
    </div>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    const url = 'https://api.xin88.top/bilibili/recommend.json'

    $.get(url, data => {
      console.log(data)

      const a = data.data.season.map(value => {
        const { title, new_ep: { cover, index_show },
          stat: { danmaku, view } } = value
        // toFixed: 数字类型的 保留几位小数
        return `<div>
          <img src="${cover}" alt="">
          <div>
            <span>${title}</span>
            <div>
              <span>${index_show}</span>
              <span>${(view / 10000).toFixed(1)}万播放 · ${(danmaku / 10000).toFixed(1)}万弹幕</span>
            </div>
          </div>
        </div>`
      })

      $('#box').html(a)
    })
  </script>

</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>练习</title>
  <style>
    body {
      background-color: #1b222a;
    }

    #box>div {
      background-color: #14151a;
      display: inline-flex;
      flex-direction: column;
      width: 100px;
      color: white;
      align-items: center;
      padding: 10px;
      margin: 0 10px 10px 0;
      border: 1px solid gray;
    }

    #box>div>img {
      width: 100%;
    }
  </style>
</head>

<body>
  <div id="box">
    <div>
      <img src="" alt="">
      <span>名字</span>
      <span>价格</span>
    </div>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    const url = 'https://api.xin88.top/game/items.json'
    $.get(url, data => {
      console.log(data);

      const a = data.items.map(value => {
        const { iconPath, name, price } = value

        return `<div>
          <img src="${iconPath}" alt="">
          <span>${name}</span>
          <span>${price}</span>
        </div>`
      })

      $('#box').html(a)
    })
  </script>
</body>

</html>

post

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>POST</title>
</head>

<body>
  <!-- 
    常见网络请求方式: GET 和 POST
    - GET: 获取 -- 通常用来从服务器获取数据, 对应的数据库 查询操作
    - POST: 传输 -- 通常用来向服务器传递数据, 对应数据库的 增删改 操作

    两者在使用时的差异: 主要在于参数传递方式的不同
    - GET:  路径?参数=值&参数=值
          例如: getNews.php?page=1&size=10   代表获取第一页的10条数据
    - POST: 路径 和 参数需要分开传递
         例如: getNews.php    {page:1, size:10}
   -->
  <div id="box">
    <input type="text" placeholder="请输入您的用户名">
    <br>
    <input type="password" placeholder="请输入您的密码">
    <br>
    <button>登录</button>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    $('#box>button').click(function () {
      const uname = $('input').eq(0).val() // val - value
      const upwd = $('input').eq(1).val()
      // POST参数和路径分开
      const url = 'http://www.codeboy.com:9999/data/user/login.php'
      // 参数是 uname 和 upwd, 由服务器规定
      const params = { uname, upwd } // { uname:uname, upwd:upwd}
      // 属性名:变量  如果属性名和变量一样, 则可以合写
      $.post(url, params, data => {
        console.log(data)
        // 正确的账号: doudou  密码:123456
      })
    })
  </script>
</body>

</html>

练习

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>练习</title>
</head>

<body>
  <div id="box">
    <input type="text" placeholder="邮箱/手机号">
    <br>
    <input type="password" placeholder="密码">
    <br>
    <button>立即登录</button>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    const url = 'http://www.codeboy.com:9999/mfresh/data/user_login.php'
    // 用户名 unameOrPhone    密码 upwd

    $('#box button').click(function () {
      // 故意把 变量名 和 参数名 写一样, 为了后续的语法糖
      const unameOrPhone = $('#box input:eq(0)').val()
      const upwd = $('#box input').eq(1).val()
      // 防止空用户名和密码 导致的 跨域报错
      if (unameOrPhone == '' || upwd == '') {
        alert("不能为空!")
        return
      }

      const p = { unameOrPhone, upwd }
      console.log(p) //打印从后台看

      $.post(url, p, data => {
        console.log(data)
      })
    })
  </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>练习</title>
  <style>
    #box {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
  </style>
</head>

<body>
  <div id="box">
    <input type="text" placeholder="用户名">
    <input type="password" placeholder="密码">
    <input type="text" placeholder="邮箱">
    <input type="text" placeholder="手机号">
    <button>提交注册信息</button>
  </div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    const url = 'http://www.codeboy.com:9999/data/user/register.php'

    // 参数: uname  upwd  email  phone
    $('#box button').click(function () {
      const uname = $('#box input').eq(0).val()
      const upwd = $('#box input').eq(1).val()
      const email = $('#box input').eq(2).val()
      const phone = $('#box input').eq(3).val()

      const params = { uname, upwd, email, phone }

      $.post(url, params, data => {
        console.log(data)
      })
    })
  </script>
</body>

</html>

load

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>load</title>
  <style>
    div {
      padding: 10px;
      background-color: lightgray;
      margin: 10px;
    }
  </style>
</head>

<body>
  <!-- 
    真正的大型网页, 页面代码非常多, 涉及到 拆分 和 复用 

    - HTML:  外部html文件  .html  利用 JQ的 load 引入
    - CSS:  外部css  .css文件, 利用 link 引入
    - JS:  外部 js   .js文件, 利用 script 引入
   -->
  <div id="box1"></div>
  <div id="box2"></div>
  <div id="box3"></div>

  <script src="./vendor/jquery-3.6.0.js"></script>
  <script>
    // 必须用服务器打开, 即 live server 插件
    // 右键当前文件 open with live server

    // load: 加载,  把指定文件中的代码 加载到子元素里
    // load: 就是把文件中的代码复制到了 指定的元素里
    // 注意: 如果多个文件中代码有冲突会报错, 例如 css 冲突, const变量名冲突http://127.0.0.1:5500/15.load.html
    $('#box1').load('./16.com.html')

    $('#box2').load('./16.com.html')

    $('#box3').load('./06.ajax.html')

  </script>
</body>

</html>

<ul>
  <li>亮亮</li>
  <li>铭铭</li>
  <li>凯凯</li>
  <li>楠楠</li>
</ul>

今日内容

  • 几个选择器

    • 序号: lt小于 gt大于 even偶数 odd奇数 eq等于

    • 包含: :contains() 含有文字 :has() 含有标签

      :not()没有 :parent 非空标签 :empty空标签

  • 克隆元素: clone

  • 替换: replaceWith

  • ajax

    • get: $.get(地址, data=>{})

    • post: $.post(地址, 参数, data=>{})

    • load: $.load(地址)

      • 加载文件中的内容 到指定标签里

明日安排

利用 Express 服务器, 自己做接口 配合 jQuery 使用, 跨域问题

环境搭建:

  • node必须是 12版本及以上 , 最高16版本 12<=版本<=16

    查看命令: node -v

    官网: Node.js 中文网, 版本不对的 卸载重装新版本

  • npm: node提供的下载管理 第三方模块的软件, 其默认的下载地址是国外的源, 速度极慢

    • 修改成国内的taobao

    • 查看当前源: npm config get registry 如下是中国的

    • 修改命令: 修改后重新查看npm config get registry

      npm config set registry https://registry.npm.taobao.org/
  • 生成一个 express 的项目包, 明天用

    • 先创建一个文件夹, 名字随便, 最好是 :my-server

    • my-server目录下, 执行初始化命令

    • 安装 express 模块: npm i express 如果有报错, 大概率是npm的源不对, 检查!

作业

  • api.xin88.top上有很多可以练习的接口, 并且都搭配了效果图, 自己练习

  • 复习 express部分, 只使用基础的 get 和 post, 静态文件夹, 不涉及mysql

  • JS高级和 DOM的考试题, 继续做, 达到能背下来的程度!

    老师的网站: xin88.top DOM考试题: DOM_2202 JS考试题: JSCORE_2202

    jQuery: jQuery_2202

jQuery04

回顾

Ajax

  • jQuery通过封装技巧, 把Ajax操作进行了封装

  • get: $.get(接口地址, 回调函数)

    • $.点外卖(餐厅地址, 餐食 => {})

  • post: $.post(接口地址, 参数, 回调函数)

  • load: 可以加载外部的 HTML 文件

今日主题

利用 Express 制作我们自己的服务器

如何生成Express项目包

  • node环境搭建

    • node软件版本需要在 12 ~ 16 之间

    • 做开发, 优先使用稳定版 -- 兼容性强

    • 版本号查看: node -v

  • npm: node的扩展包的管理工具, 默认的下载源是 外国的服务器, 速度极慢

    • 修改为中国镜像 npm config set registry https://registry.npm.taobao.org/

    • 查看当前镜像: npm config get registry

开启服务器

nodemon

侦测修改, 自动重启服务器的软件: nodemon

安装完毕后, 使用 nodemon 来启动服务器: nodemon app.js

跨域

跨域: 浏览器具有同源策略

  • 同源: 在网页中利用 AJAX发送网络请求, 必须是同一个服务器上的

    • 通俗来说:自己家里人可以互相访问, 比如 成亮的钱 成小亮可以随意使用, 但是 雷佳乐跟成亮要钱花, 就会被果断拒绝 -- 因为他们不熟

  • 通过 http://localhost:3000 来访问的index.html 文件

  • 在 index.html 文件中, 使用 ajax 发送请求

    姓: http, 名字是 localhost 端口:3000

跨域报错: 在自己家里, 访问了别人家的东西 -- 不同源,就报错!

  • 场景: 利用 live server, 开启index.html http://localhost:5500

  • 在这个地址中, 请求http://localhost:3000/skills

跨域解决

目前流行前后端分离 项目

  • 由于现在的网站访问量很大, 如果把所有操作都放在一台计算机上, 负载太高, 压力大

  • 做法: 拆分

    • 数据库放在一个服务器上

    • 前端页面放在另一个电脑上

  • 不是同一台电脑, 非同一个服务器 互相之间访问, 必然会跨域

  • 所以: 解决跨域问题是 前端程序员必备技能!!!

解决方案主流有3种

  • CORS: 最主流推荐

    • 原理:在服务器上添加一个白名单, 通过响应头告知浏览器, 不要拦截指定来源的

  • PROXY: 代理方案, 适合服务器不可修改的场景

  • JSONP: 比较适合PHP服务器, 日常使用较少

接口抓取

由于前后端分离项目, 都是通过 ajax 发送请求, 我们可以通过浏览器抓到这个接口来用

 

https://m.douyu.com/api/room/list?page=2&type=yz

代理服务器

通俗的例子: 假设 家乐建军 关系不好, 见面就打架, 但是 家乐想跟建军借 游戏机玩. 晓婷建军 家乐 关系都不错

 

代码

<!DOCTYPE html>
<html lang="en">
​
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>首页</title>
</head>
​
<body>
  <!-- 文件名 index.html 这是固定的特殊文件名,代表首页 -->
  <!-- 特点: 当访问服务器时, 默认找到名字是 index.html 的 -->
  <h1>Welcome to Express!</h1>
​
  <script src="./jquery-3.6.0.js"></script>
  <script>
    const url = 'http://localhost:3000/skills'
​
    $.get(url, data => {
      console.log(data)
    })
​
    // 斗鱼服务器采用了 cors. 设置了白名单, 导致其他服务器无法访问
    // 场景: 服务器无法修改, 不能操作 添加 cors
    // 
    // 办法: 代理模式
    // const dy = 'https://m.douyu.com/api/room/list?page=2&type=yz'
    const dy = 'http://localhost:3000/dy/api/room/list?page=2&type=yz'
    $.get(dy, data => {
      console.log(data)
    })
  </script>
</body>
​
</html>

cors入门

const express = require('express')
​
const app = express()
​
// 指定静态文件 -- html文件存储的路径
app.use(express.static('public'))
​
// CORS: 在服务器添加白名单, 允许来自其他来源的访问即可
// all: 代表所有类型的网络请求, POST GET DELETE PUT ...
// * : 通配符, 匹配所有请求的地址
// 回调函数有3个参数:  函数的重载机制 -- 检测参数的个数, 如果是3个就被当做是拦截器来使用
// 拦截所有类型的网络请求, 所有的请求地址, 统一返回一个 响应头, 会传递给浏览器, 告诉浏览器, 允许的来源
app.all('*', (req, res, next) => {
  // 不安全: 直接允许所有来源 不安全
  // 所以: 可以采用 第三方 cors 模块, 来精确配置允许的来源
  res.header('Access-Control-Allow-Origin', '*')
  //          访问 - 控制 - 允许 - 来源   :  * 代表任何来源
  next()
})
​
app.listen(3000, () => {
  console.log('服务器启动成功, 端口3000');
})
​
// 关于命令行工具, 推荐采用 cmd , 另外一款工具 power shell 对脚本支持不好
// 启动: 在 my-server 文件夹下, 运行命令  node app.js
// 通过浏览器访问 localhost:3000
​
// 服务器上的 app.js 如果有修改, 必须重启服务器才能生效
// 重启服务器分 手动 和 自动两种方式
// 手动: 在命令行按 ctrl+c 停止, 再用 node app.js 启动
// 自动: 安装 nodemon 模块
//    -- 全局安装  npm i -g nodemon
​
// GET接口
// localhost:3000/skills
app.get('/skills', (req, res) => {
  // res: response响应,  响应用户发来的请求, 返回数据给用户
  // send: 发送, 可以把内容发送给用户
  res.send(['vue', 'react', 'angular', 'uniapp', 'dom', 'JS'])
​
  // 如果是实际项目: 数据应该是从 mysql 查询出来
​
})

cors模块

const express = require('express')
// cors模块: 可以精确配置 白名单
// 先安装, 在 my-server 目录下执行: npm i cors
const cors = require('cors')
​
const app = express()
​
// 利用 cors 直接允许所有来源, 不安全
// app.use(cors())
​
// 精确配置
app.use(cors({
  // 数组类型,可以加多个地址, 代表允许的来源
  origin: ['http://127.0.0.1:5500', '可以书写更多地址']
}))
// 测试方式: 通过 live server 运行 index.html
// 手动把浏览器地址 从 127.0.0.1 改成 localhost 试试
// 结果: 127的不报错, 因为在 origin中
// localhost会报错, 因为不在 origin 里
​
​
app.use(express.static('public'))
​
app.listen(3000, () => {
  console.log('服务器启动成功, 端口3000');
})
​
app.get('/skills', (req, res) => {
  res.send(['vue', 'react', 'angular', 'uniapp', 'dom', 'JS'])
})

代理

const express = require('express')
const cors = require('cors')
// 代理模块: npm i express-http-proxy
const proxy = require('express-http-proxy')
​
const app = express()
// 允许所有来源: 接受任何来源的访问
app.use(cors())
​
// 必须写在 cors 下方, 否则可能出现跨域
// 参数1 是自定义的,  /xxx
app.use('/dy', proxy('https://m.douyu.com'))
// 凡是 localhost:3000/dy/....  都会转到  https://m.douyu.com/.... 
​
app.use(express.static('public'))
​
app.listen(3000, () => {
  console.log('服务器已启动');
})
​
// node app.js

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值