webapi,事件,高阶函数,环境对象,编程思想

122 阅读1分钟

webapi

一,事件

  • 事件:是在编程时系统内发生的动作或者发生的事情(比如用户在网页上单机一个按钮)
  • 事件监听: 就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件
  • 语法:

image.png

  • 事件监听三要素【1.事件源 2.事件 3.事件类型】 案例
  1. 添加事件监听
 <body>
    <button>点我啊</button>
    <script>
      // 1.获取元素
      let btn = document.querySelector('button')
      // 2.为元素绑定单击事件
      // btn.addEventListener(事件类型,事件处理函数)
      // click:单击事件:鼠标左键单击
      let opt = function() {
        console.log(123)
      }

      // 函数后面如果带(),说明在调用函数
      // 我们只是传递一个当事件触发之后的处理函数,但是函数并不是开发者直接调用的,而是事件处理机制监听到事件触发之后再调用的
      // 我们传入的是一个函数的声明
      btn.addEventListener('click', function() {
        console.log(123)
      })
    </script>
  </body>
  1. 点击关闭二维码
<style>
      .erweima {
        position: relative;
        width: 160px;
        height: 160px;
        margin: 100px auto;
      }
      span {
        position: absolute;
        left: -20px;
        top: 0;
        display: block;
        width: 20px;
        text-align: center;
        border: 1px solid #ccc;
        /* 鼠标效果 */
        cursor: pointer;
      }
    </style>
    
    <body>
    <div class="erweima">
      <img src="images/code.png" alt="" />
      <span> X </span>
    </div>
    <script>
      // 1.获取元素
      let span = document.querySelector('span')
      let erweima = document.querySelector('.erweima')

      // 2.为关闭按钮绑定单击事件
      span.addEventListener('click', function() {
        // 3.将二维码隐藏,通过样式可以实现
        erweima.style.display = 'none'
      })
    </script>
  </body>
  • 案例 随机点名
 <style>
      p {
        width: 200px;
        height: 100px;
        border: 1px solid red;
      }
    </style>
    
    <body>
    <p>这里显示名字</p>
    <button>随机点名</button>

    <script>
      // 1.模拟数据
      let names = ['曹操', '关羽', '张飞', '赵铁柱', '李狗蛋']
      // 2.获取两个元素
      let p = document.querySelector('p') // 显示姓名
      let button = document.querySelector('button') // 绑定单击事件
      // 3.为元素绑定单击事件
      button.addEventListener('click', function() {
        // 4.生成一个合理的索引
        let index = parseInt(Math.random() * names.length)
        // 5.获取索引位置对应的姓名
        let name = names[index]
        // 6.将当前索引位置的元素删除
        names.splice(index, 1)
        // 7.将姓名填充到指定的元素中
        p.innerText = name
        // 8.判断数组是否长度为0--为0说明删除了所有的元素
        if (names.length === 0) {
          button.disabled = true
        }
      })
    </script>
  </body>

随机点名2

 <style>
      p {
        width: 200px;
        height: 100px;
        border: 1px solid red;
      }
    </style>
    
    <body>
    <p>这里显示名字</p>
    <button class="start">开始随机点名</button>
    <button class="end">结束随机点名</button>

    <script>
      // 1.模拟数据
      let names = ['曹操', '关羽', '张飞', '赵铁柱', '李狗蛋']
      // 2.获取三个元素
      let start = document.querySelector('.start') // 开始
      let end = document.querySelector('.end') //结束
      let p = document.querySelector('p') // 渲染元素
      let timeId, index // 定时器句柄
      // 3.单击开始,仅仅是随机获取名字进行渲染--定时器
      start.addEventListener('click', function() {
        // 添加定时器
        timeId = setInterval(function() {
          // 生成一个随机索引
          index = parseInt(Math.random() * names.length)
          // 根据索引获取名字
          let name = names[index]
          // 渲染到p元素
          p.innerText = name
        }, 50)
      })

      // 4.单击结束,实现真正的点名
      // 函数内部无法直接使用另外一个函数内部声明的成员
      // 函数内部可以使用函数外部的成员
      end.addEventListener('click', function() {
        // 关闭定时器
        clearInterval(timeId)
        // 删除元素
        names.splice(index, 1)
        // 判断数组是否长度为0,为0禁用按钮
        if (names.length === 0) {
          start.disabled = true
        }
      })
    </script>
  </body>

事件的其他绑定方式

 <body>
    <button>点我啊</button>
    <script>
      let btn = document.querySelector('button')

      元素.on类型 = 处理函数
      btn.onclick = function() {
        console.log(123)
      }
      // 如果为元素重复绑定同一个事件,那么后面绑定的事件将前面绑定的事件覆盖--不允许为元素绑定同名事件
      btn.onclick = function() {
        console.log(456)
      }

      // 它不能设置在什么阶段触发事件:事件捕获  事件冒泡

      // 有兼容性:IE9下不支持
      btn.addEventListener('click', function() {
        console.log(123)
      })
      btn.addEventListener('click', function() {
        console.log(456)
      })
    </script>
  </body>
  • 常见的事件类型
<style>
      ul {
        border: 1px solid #f00;
        display: none;
      }
      .inputborder {
        border: none;
        outline: none;
        border: solid red 1px;
      }
</style>

<body>
    <button>进入后弹出层</button>
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
    </ul>
    <br />
    用户名:<input type="text" class="username" /> <br />
    密码:<input type="text" class="password" /> <br />

    <script>
      let username = document.querySelector('.username')
      let password = document.querySelector('.password')

      // 添加输入框的获得焦点事件--聚焦事件
        username.addEventListener('focus', function() {
        username.style.outline = 'none'
        username.style.border = '1px solid red'
      })
      // // 为输入框添加失焦事件:失去光标
      username.addEventListener('blur', function() {
        username.style.border = '1px solid #000'
      })

      // 对于键盘按键事件,先得让输入框聚焦
      username.addEventListener('keydown', function() {
        console.log('我按下一个键')
      })
      username.addEventListener('keyup', function() {
        console.log('我松开了')
      })

      password.addEventListener('keydown', function(e) {
        // 如果你按下的是  确认  键,我应该实现登陆业务
        if (e.which == 13) {
          console.log('我要去登陆了')
        }
      })
    </script>
  </body>
  • 其他事件类型
<body>
    手机号:<input type="text" /> <span>手机号输入不合法</span>
    <input type="file" />
    <script>
      // 输入框的事件:
      // focus:聚焦事件:只要获取焦点就会触发
      // blur:失焦事件:只要失去焦点就会触发
      // input:内容改变事件:只要内容改变,就会触发
      // change:内容改变的失焦事件:内容改变的同时,失去焦点就会触发
      let input = document.querySelector('input')

      // 当用户选择好文件 ,单击 对话框中的  “打开”的时候,触发change事件
      input.addEventListener('change', function() {
        console.log('我要开始上传文件了哦')
      })

      input.addEventListener('blur', function() {
        console.log('blur')
      })

      input.addEventListener('change', function() {
        console.log('change')
      })

      input.addEventListener('input', function() {
        console.log(input.value)
      })
    </script>
  </body>
  • 案例 小米搜索框
  <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      ul {
        list-style: none;
        display: none;
      }
      .mi {
        position: relative;
        width: 223px;
        margin: 100px auto;
      }
      .mi input {
        width: 223px;
        height: 48px;
        padding: 0 10px;
        font-size: 14px;
        line-height: 48px;
        border: 1px solid #e0e0e0;
        outline: none;
      }
      .mi .search {
        border: 1px solid #ff6700;
      }
      .result-list {
        position: absolute;
        left: 0;
        top: 48px;
        width: 223px;
        border: 1px solid #ff6700;
        border-top: 0;
        background: #fff;
      }
      .result-list a {
        display: block;
        padding: 6px 15px;
        font-size: 12px;
        color: #424242;
        text-decoration: none;
      }
      .result-list a:hover {
        background-color: #eee;
      }
    </style>
    
    <body>
    <div class="mi">
      <input type="search" placeholder="小米笔记本" />
      <ul class="result-list">
        <li><a href="#">全部商品</a></li>
        <li><a href="#">小米11</a></li>
        <li><a href="#">小米10S</a></li>
        <li><a href="#">小米笔记本</a></li>
        <li><a href="#">小米手机</a></li>
        <li><a href="#">黑鲨4</a></li>
        <li><a href="#">空调</a></li>
      </ul>
    </div>

    <script>
      // 1.获取元素
      let input = document.querySelector('input')
      let ul = document.querySelector('ul')

      // 2.为输入框添加聚焦事件
      input.addEventListener('focus', function() {
        // 让ul显示
        ul.style.display = 'block'
      })

      // 3.为输入框添加失焦事件
      input.addEventListener('blur', function() {
        // 让ul隐藏
        ul.style.display = 'none'
      })
    </script>
  </body>
  • 案例 全选反选
<style>
    * {
      margin: 0;
      padding: 0;
    }
    table {
      border-collapse: collapse;
      border-spacing: 0;
      border: 1px solid #c0c0c0;
      width: 500px;
      margin: 100px auto;
      text-align: center;
    }
    th {
      background-color: #09c;
      font: bold 16px '微软雅黑';
      color: #fff;
      height: 24px;
    }

    td {
      border: 1px solid #d0d0d0;
      color: #404060;
      padding: 10px;
    }
    .allCheck {
      width: 80px;
    }
  </style>
  <body>
  <table>
    <tr>
      <th class="allCheck">
        <input type="checkbox" name="" id="checkAll" />
        <span class="all">全选</span>
      </th>
      <th>商品</th>
      <th>商家</th>
      <th>价格</th>
    </tr>
    <tr>
      <td>
        <input type="checkbox" name="check" class="ck" />
      </td>
      <td>小米手机</td>
      <td>小米</td>
      <td>¥1999</td>
    </tr>
    <tr>
      <td>
        <input type="checkbox" name="check" class="ck" />
      </td>
      <td>小米净水器</td>
      <td>小米</td>
      <td>¥4999</td>
    </tr>
    <tr>
      <td>
        <input type="checkbox" name="check" class="ck" />
      </td>
      <td>小米电视</td>
      <td>小米</td>
      <td>¥5999</td>
    </tr>
  </table>
  <script>
    //想法1
    //1.获取元素
    //1.1获取全选复选框
    let checkAll = document.querySelector('#checkAll')
    //1.2获取文本容器
    let all = document.querySelector('.all')
    //获取下面的复选框
    let cks = document.querySelectorAll('.ck')
    // console.log(checkAll, all, cks);

    //2.为全选按钮添加单击事件
    checkAll.addEventListener('click', function () {
      //2.1先获取当前全选复选框经过这一次单机之后的状态
      let state = checkAll.checked
      //2.2将状态赋值给下面所有复选框
      cks.forEach(function (ele, index) {
        ele.checked = state
      })
      //如果是全选状态就是取消,否则就是全选
      all.innerText = state ? '取消' : '全选'
    })

    //设置一个全局的标记,遍历下面的复选框有没有被选中
    for (let i = 0; i < cks.length; i++) {
      cks[i].addEventListener('click', function () {
        let flag = true
        //判断当前遍历到的复选框是否为非选中
        cks.forEach(function (v, i) {
          if (v.checked == false) {
            flag = false
          }
        })
        checkAll.checked = flag
        all.innerText = flag ? '取消' : '全选'
      })
    }
    
    
    
      //想法2
      // 1.获取元素
      // 1.1 获取全选复选框
      let checkAll = document.querySelector('#checkAll')
      // 1.2 获取文本容器
      let all = document.querySelector('.all')
      // 1.3 获取其它的复选框
      let cks = document.querySelectorAll('.ck')

      // 2.实现全选和全不选
      // 用全选复选框的状态,赋值给下面的所有复选框
      checkAll.addEventListener('click', function() {
        // 2.1 先获取当前全选复选框经过这一次单击之后的状态
        let state = checkAll.checked
        // 2.2 将状态赋值给下面的所有复选框,伪数组需要遍历
        cks.forEach(function(ele, index) {
          ele.checked = state
        })
      })

      // 设置一个全局的标记
      for (let i = 0; i < cks.length; i++) {
        cks[i].addEventListener('click', function() {
          // 设置一个数量
          let count = 0
          // 实现方式就是获取当前被选中的 复选框的数量,与总数进行比较
          // 遍历所有复选框,判断复选框是否被选中,如果选中,数量+1
          cks.forEach(function(v) {
            if (v.checked == true) {
              count++
            }
          })
          // 判断当前被选中的复选框的数量是否等于 所有总数
          if (count == cks.length) {
            checkAll.checked = true
          } else {
            checkAll.checked = false
          }
        })
      }
    
    
    
    //想法3
     // 1.获取元素
      // 1.1 获取全选复选框
      let checkAll = document.querySelector('#checkAll')
      // 1.2 获取文本容器
      let all = document.querySelector('.all')
      // 1.3 获取其它的复选框
      let cks = document.querySelectorAll('.ck')

      // 2.实现全选和全不选
      // 用全选复选框的状态,赋值给下面的所有复选框
      checkAll.addEventListener('click', function() {
        // 2.1 先获取当前全选复选框经过这一次单击之后的状态
        let state = checkAll.checked
        // 2.2 将状态赋值给下面的所有复选框,伪数组需要遍历
        cks.forEach(function(ele, index) {
          ele.checked = state
        })
        all.innerText = state ? '取消' : '全选'
      })

      // 设置一个全局的标记
      for (let i = 0; i < cks.length; i++) {
        cks[i].addEventListener('click', function() {
          // 实现方式就是获取当前被选中的 复选框的数量,与总数进行比较
          // .ck:checked: 找到匹配的元素,只会匹配被选中的复选框
          let count = document.querySelectorAll('.ck:checked').length
          if (count === cks.length) {
            checkAll.checked = true
            all.innerText = '取消'
          } else {
            checkAll.checked = false
            all.innerText = '全选'
          }
        })
      }
    </script>
  </body>
  • 案例 购物车加减操作
<style>
      div {
        width: 80px;
      }

      input[type='text'] {
        width: 50px;
        height: 44px;
        outline: none;
        border: 1px solid #ccc;
        text-align: center;
        border-right: 0;
      }

      input[type='button'] {
        height: 24px;
        width: 22px;
        cursor: pointer;
      }

      input {
        float: left;
        border: 1px solid #ccc;
      }
    </style>
    
    <body>
    <div>
      <input type="text" id="total" value="4" readonly />
      <input type="button" value="+" id="add" />
      <input type="button" value="-" id="reduce" />
    </div>
    <script>
      // 1.获取元素
      let add = document.querySelector('#add')
      let reduce = document.querySelector('#reduce')
      let total = document.querySelector('#total')

      // 2.先做+
      add.addEventListener('click', function() {
        // 2.1 获取输入框的数量
        let count = total.value
        // 2.2 数量+1
        count++
        // 2.3 重新赋值给输入框
        total.value = count
        // 加一定会导致数量>1
        reduce.disabled = false
      })

      reduce.addEventListener('click', function() {
        // 2.1 获取输入框的数量
        let count = total.value
        // 2.2 数量+1
        count--
        // 2.3 重新赋值给输入框
        total.value = count
        // 2.4 判断数量是否是1,如果是1则禁用按钮
        if (count == 1) {
          reduce.disabled = true
        }
      })
    </script>
  </body>