20230318----重返学习-交叉信息监听事件IntersectionObserver-AJAX基础-瀑布流

54 阅读4分钟

day-030-thirty-20230318-交叉信息监听事件IntersectionObserver-AJAX基础-瀑布流

交叉信息监听事件IntersectionObserver

  • IntersectionObserver:监听器,监控盒子在视口中出现的交叉信息

    • 语法: IntersectionObserver(函数,对象)

      • 入参

        • 函数 (changes)=>{}

          • 有参数 changes

            • changes—是一个数组

            • changes[0]—对象,box的交叉信息

              • isIntersecting: 元素是否在视口中出现 true 出现 false 未出现
              • target: 监控的目标元素
              • boundingClientRect:元素的某些信息
        • 对象 {threshold:[]} 省略时默认值为{threshold:[0]} 用来控制元素与视口的交叉监听情况

          • 用于控制监听对象与视口交叉程度,才触发的事件

          • 触发情况举例

            • 触发情况(0)

              1. 一打开页面立刻触发一次
              2. 元素在视口中出现一个边,触发一次
              3. 元素在视口中完全消失,触发一次。
              4. 之后2与3根据情况出现
              <!DOCTYPE html>
              <html lang="en">
              <head>
                  <meta charset="UTF-8">
                  <title>Document</title>
              </head>
              <body style="height:3000px;">
                  <div id="box" style="height:400px;width:100px;background-color: red;margin-top:1000px;margin-left:100px;"></div>
              
                  <script>
              
                      var ob=new IntersectionObserver((changes)=>{
                          console.log(changes,'changes')
                          if(changes[0].isIntersecting){
                            console.log('按要求显示了')
                            ob.unobserve(changes[0].target)//取消监控
                          }
                      },{
                          threshold:[0]
                      })
              
                      ob.observe(document.querySelector('#box'))//启动监听
                  </script>
              </body>
              </html>
              
            • 触发情况(0.5)

              1. 一打开页面立刻触发一次
              2. 元素在视口中出现一半,触发一次
              3. 元素在视口中消失一半,触发一次。
              4. 之后2与3根据情况出现
              <!DOCTYPE html>
              <html lang="en">
              <head>
                  <meta charset="UTF-8">
                  <title>Document</title>
              </head>
              <body style="height:3000px;">
                  <div id="box" style="height:400px;width:100px;background-color: red;margin-top:1000px;margin-left:100px;"></div>
              
                  <script>
              
                      var ob=new IntersectionObserver((changes)=>{
                          console.log(changes,'changes')
                          if(changes[0].isIntersecting){
                            console.log('按要求显示了')
                            ob.unobserve(changes[0].target)//取消监控
                          }
                      },{
                          threshold:[0.5]
                      })
              
                      ob.observe(document.querySelector('#box'))//启动监听
                  </script>
              </body>
              </html>
              
            • 触发情况(1)

              1. 一打开页面立刻触发一次
              2. 元素在视口中完全出现,触发一次
              3. 元素在视口中消失一个边,触发一次。
              4. 之后2与3根据情况出现
              <!DOCTYPE html>
              <html lang="en">
              <head>
                  <meta charset="UTF-8">
                  <title>Document</title>
              </head>
              <body style="height:3000px;">
                  <div id="box" style="height:400px;width:100px;background-color: red;margin-top:1000px;margin-left:100px;"></div>
              
                  <script>
              
                      var ob=new IntersectionObserver((changes)=>{
                          console.log(changes,'changes')
                          if(changes[0].isIntersecting){
                            console.log('按要求显示了')
                            ob.unobserve(changes[0].target)//取消监控
                          }
                      },{
                          threshold:[1]
                      })
              
                      ob.observe(document.querySelector('#box'))//启动监听
                  </script>
              </body>
              </html>
              
      • 出参

        • 一个监听器对象

          • 监听器对象.observe(DOM元素对象)//启动监听对应的DOM元素对象

          • 监听器对象.unobserve(changes[下标].target)//取消监控changes[下标].target对应的DOM元素对象

            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>Document</title>
            </head>
            <body style="height:3000px;">
                <div id="box" style="height:400px;width:100px;background-color: red;margin-top:1000px;margin-left:100px;"></div>
            
                <script>
            
                    var ob=new IntersectionObserver((changes)=>{
                        console.log(changes,'changes')
                        if(changes[0].isIntersecting){
                          console.log('按要求显示了')
                          ob.unobserve(changes[0].target)//取消监控
                        }
                    },{
                        threshold:[1]
                    })
                    console.log(ob)
            
                    ob.observe(document.querySelector('#box'))//启动监听
                </script>
            </body>
            </html>
            
    • IntersectionObserver配合图片懒加载

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <title>Document</title>
          <style>
            body {
              height: 3000px;
            }
            .imgbox {
              width: 300px;
              height: 400px;
              margin-top: 1300px;
              margin-left: 100px;
              background-color: #ccc;
              background-position: center;
              background-repeat: no-repeat;
              background-image: linear-gradient(to bottom, yellow, skyblue);
            }
            .imgbox img {
              width: 300px;
              height: 400px;
            }
            img[src=""] {
              display: none;
            }
          </style>
        </head>
        <body>
          <div class="imgbox">
            <img src="" data-src="linear-gradient(to bottom,blue)" alt="" />
          </div>
      
          <script>
            var canvas = document.createElement("canvas");
            canvas.width = "300";
            canvas.height = "300";
            const ctx = canvas.getContext("2d");
      
            // 在 canvas 上绘制一些内容
            ctx.fillStyle = "red";
            ctx.fillText('在 canvas 上绘制一些内容;获取图片的 Base64 编码数据', 50, 50);
            ctx.fillRect(10, 10, 50, 50);
            const dataURL = canvas.toDataURL();//获取图片的 Base64 编码数据
      
            var imgbox = document.querySelector(".imgbox");
            var img = document.querySelector(".imgbox img");
      
            console.log(ctx);
            img.setAttribute("data-src", dataURL);
            console.log(dataURL);
            var ob = new IntersectionObserver(
              (changes) => {
                console.log("111");
                if (changes[0].isIntersecting) {
                  //加载图片
                  if (img.flag) {
                    ob.unobserve(imgbox);
                    return;
                  }
                  showimg();
                }
              },
              {
                threshold: [1],
              }
            );
      
            ob.observe(imgbox);
      
            function showimg() {
              console.log("2222");
              var dataSrc = img.getAttribute("data-src");
              var newimg = new Image();
              newimg.src = dataSrc;
              newimg.onload = function () {
                img.src = dataSrc;
                img.removeAttribute("data-src");
                newimg = null;
                img.flag = true;
              };
            }
          </script>
        </body>
      </html>
      

AJAX基础

  • ajax是一个前后端进行数据交互的协议格式

    • json格式的数据 —> 也是后台的数据格式
  • 通过ajax ->获取json格式的数据

    • 一般只能通过ajax才能将json数据获取到页面中
  • json格式数据

    • 最外层 可以是数组,对象(键值对—key必须加双引号)

      • 也可以用基础数据类型

        [1,"str",true,null,{  "name": "lili",  "age": 18},[]]
        
        {
            "name":"lili",
            "age":18,
            "arr":[
                {
                  "a":10
                },
                {
                  "a":20
                }
            ]
        }
        
      • 也可以用基础数据类型

    • 数据类型 数组,对象,数值,布尔值,字符串,null

      • 字符串必须用双引号
    • json格式数据使用//<!-- -->/**/进行注释

      • 但可以用无用属性名间接进行注释
    • 通过ajax拿到的json本身就是字符串

      • 只不过可以通过一些方法将json字符串变成json对象

        • json对象是一个普通对象的一个子集

          • 所以json对象可以看作是普通对象,它内部的数据都可以通过普通对象的方法来获取
      • JSON.parse(json字符串) 将json字符串变成json对象

      • JSON.stringify(json对象)

  • ajax的步骤

    • 得要用到Open with Live Server,而不是Open In Default Browser

      • 因为Open with Live Server是本地创建一个小型服务器

        • 数据协议为http://

          • http://127.0.0.1:5500/JS部分/day0318/ajax.html
      • Open In Default Browser是直接本地打开html文件

        • 数据协议为http://

          • file:///C:/Users/fangc/Desktop/myWork/2023_01/JS部分/day0318/ajax.html
    • 操作步骤

      1. 创建XMLHttpRequest核心对象

        • let xhr = new XMLHttpRequest();
      2. 建立连接

        • XMLHttpRequest核心对象.open(建立连接的方式请求路径是否同步异步)

          • 例子

            • xhr.open("GET", "./fang.json", false);
          • 请求路径是以引用该js代码的html文档所在目录当前路径来进行相对查找的。

          • 是否同步异步false同步

      3. 注册监听

      4. 发送数据

    • 例子

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <title>ajax</title>
        </head>
        <body></body>
        <script>
          let data = null;
      
          // 1. 第一步创建XMLHttpRequest核心对象
          let xhr = new XMLHttpRequest();
          // 2. 建立连接 open(建立连接的方式,连接路径,是否同步异步) false 同步
          xhr.open("GET", "./fang.json", false);
          // 3. 注册监听
          xhr.onreadystatechange = function () {
            //readyState 状态值---4
            //status 状态码---200
            if (xhr.readyState === 4 && xhr.status === 200) {
              console.log(xhr.response, "默认通过ajax得到的json,是字符串");
              data = JSON.parse(xhr.response)
              console.log(data, "对象");
              console.log(JSON.stringify(data), "字符串");
            }
          };
          // 4. 发送数据
          xhr.send();
        </script>
      </html>
      

ES6基础

  • 箭头函数

    • 简写

      var f1 = function (a) {
        return a + 1;
      }; //正常函数
      var f2 = (a) => {
        return a + 1;
      }; //只有一个入参
      var f3 = (a) => a + 1; //函数体内只有一条return语句
      var f4 = (a) => a + 1; // 只有一个入参 并且 函数体内只有一条return语句
      
    • 不能使用arguments

      • 用剩余运算符代替
  • 剩余运算符与展开运算符

    • 剩余运算 将零散内容,放到一块

      //剩余运算,将零散内容,放到一块
      var show = (...args) => {
        console.log(args); //[1,2,3,4]
      };
      show(1, 2, 3, 4);
      
    • 展开运算 将一个整体,变成单独个体

      //展开运算 将一个整体,变成单独个体
      var arr = [1, 2, 3, 4];
      console.log(...arr); //1 2 3 4//相当于console.log(1, 2, 3, 4);
      
  • 字符串模板

    • 符号为反引号

      • 可以换行
      • 可以加变量
      • 可以加运算表达式
      • 可以用三元运算符
      //es6字符串模板
      var name="丽丽",age=18;
      var str="我叫"+name+",今年"+18+"岁,<ul><li>11</li><li>222</li><li>3333</li></ul>";
      console.log(str);
      
      var name="丽丽",age=18;
      var str=`我叫${name},今年${age+1}岁,${age>=18?"成年":"未成年"}
      <ul>
          <li>可以换行</li>
          <li>222</li>
          <li>3333</li>
      </ul>`;
      console.log(str);
      
  • 解构赋值

    • 左右格式必须一样

      • 左边是对象,右边也是对象
      • 左边是数组,那右边也要为数组
    • 左边没对应右边的,则左边的变量对应的变量值为undefined

      • 左边变量名可以等号赋值默认值

        • 只有右边属性值为undefined时才会使用默认值
      • 左边可以通过冒号:来取别名

        //解构赋值 (对象,数组)
        var obj={
            name:"lili",
            Compotedage:18,
            job1:null,
            job4:undefined,
        }
        var {
          name = "Tom",//只有右边属性值为undefined时才会使用默认值
          Compotedage: age, // 可以通过 : 取别名
          job1 = "ceo",// 可以通过 等号 赋值默认值
          job2,//没有的解构出来为undefined
          job3 = "job3",
          job4 = "job4",//赋值默认值(undefined)
        } = obj; //左右格式必须一样,左右都为对象
        console.log(name, age, job1, job2, job3, job4);
        
    • 一般用来解构对象与数组

      //数组
      var arr=[10,20,30,49,46];
      var [a,b,c,d,e]=arr;
      console.log(a,e);//10,46
      
    • 也可以用来进行交换赋值

      //交换 a和b 的值
      // var a=10;
      // var b=20;
      // var c;
      // c=b;
      // b=a;
      // a=c;
      // console.log(a,b)
      
      
      var a=10;
      var b=20;
      [a,b]=[b,a];
      console.log(a,b);//20,10
      

瀑布流

  • 与后端数据交互

    • 客户端通过ajax发送到服务器得到json字符串数据
    • 通过JSON.parse()把得到的json字符串数据转成json对象
  • 得到json对象数据后,循环插入html中

    • 根据观察,发现数据,不适合直接渲染;修改数据

    • 对数据进行分组,根据图片大小依次反向插入对应列中

      var data=null;//存储未来获取的数据
      //注意,获取的cloumns是类数组,无法使用sort
      //******将类数组,转换为数组的方法 Array.from(类数组)
      var cloumns=Array.from(document.querySelectorAll(".cloumn"));//获取三列
      
      //1. 获取数据
      function getData(){
        var xhr=new XMLHttpRequest;
        //文件路径,以html为基准找
        xhr.open("GET","data.json",false);
        xhr.onreadystatechange=function(){
            if(xhr.readyState===4&&xhr.status===200){
              data=JSON.parse(xhr.response)
            }
        }
        xhr.send();
      }
      getData()
      
      //2.循环渲染
      function render(){
          //2.1根据观察,发现数据,不适合直接渲染 数据图片宽度300,样式图片宽度240
          //修改数据
          var newData=data.map(item=>{
              //拿出每条数据的 height(433)和width(300)
              let {width:w,height:h}=item;
              item.width=240;//将240重新覆盖原来的width
              item.height=240*h/w;//重新覆盖原来的height
              return item;//返回覆盖原来的每一项
          })
      
          var groups=[];
          for(var i=0;i<newData.length;i+=3){//i=0, i=3, i=6
            //i=0  slice(i,i+3)  slice(0,3)  [0,1,2]
            //i=3  slice(i,i+3)  slice(3,6)  [3,4,5]
            //i=6  slice(i,i+3)  slice(6,9)  [6,7,8]
            groups=newData.slice(i,i+3);
            //console.log(groups);//[0,1,2]  [3,4,5]  [6,7,8]
            //每一组数据,从大到小排序(按照高度)
            groups.sort((a,b)=>{
              return b.height-a.height
            })
            //检查一下,每组数据的高度,是否是由大到小
            //console.log(groups);
      
            //按照每列的高度,排序 小中大
            cloumns.sort((a,b)=>{
              return a.offsetHeight-b.offsetHeight
            })
      
            //检查一下,每列数据的高度,是否是 小中大
            //console.log(cloumns);
      
            //groups: [大 中 小]
            //cloumns:[小 中 大]
            //已经排好顺序,只需要按照索引下标插入就可以
            groups.forEach((item,index) => {
                let {id,pic,title,link,height,width}=item;
                let str=`<div class="item" data-id="${id}">
                    <a href="${link}"> 
                        <div class="imgbox" style="height:${height}px;width:${width}px">
                            <img src="${pic}" style="height:${height}px;width:${width}px">
                        </div>
                        <p>${title}</p>
                      </a> 
                  </div>`;
                  cloumns[index].innerHTML+=str;
            });
      
          }
      
      }
      render()
      

循环插入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>Document</title>
  </head>
  <body>
    <ul id="ulbox"></ul>

    <script>
      var data = [
        {
          id: 0,
          pic: "images/3.jpg",
          width: 300,
          height: 170,
          title:
            "泰勒·斯威夫特(Taylor Swift),1989年12月13日出生于美国宾州,美国歌手、演员。2006年出道,同年发行专辑《泰勒·斯威夫特》,该专辑获得美国唱片业协会的白金唱片认证",
          link: "https://baike.sogou.com/v1850208.htm?fromTitle=%E9%9C%89%E9%9C%89",
        },
        {
          id: 1,
          pic: "images/9.jpg",
          width: 300,
          height: 433,
          title:
            "泰勒·斯威夫特(Taylor Swift),1989年12月13日出生于美国宾州,美国歌手、演员。2006年出道,同年发行专辑《泰勒·斯威夫特》,该专辑获得美国唱片业协会的白金唱片认证",
          link: "https://baike.sogou.com/v1850208.htm?fromTitle=%E9%9C%89%E9%9C%89",
        },
        {
          id: 2,
          pic: "images/5.jpg",
          width: 300,
          height: 200,
          title:
            "泰勒·斯威夫特(Taylor Swift),1989年12月13日出生于美国宾州,美国歌手、演员。2006年出道,同年发行专辑《泰勒·斯威夫特》,该专辑获得美国唱片业协会的白金唱片认证",
          link: "https://baike.sogou.com/v1850208.htm?fromTitle=%E9%9C%89%E9%9C%89",
        },
      ];

      function render() {
        var str = "";
        data.forEach((item) => {
          let { width, height } = item;
          str += `<li>
                        <a href="#">height:${height}</a>
                        <span>width:${width}</span>
                    </li>`;
        });
        ulbox.innerHTML = str;
      }
      render();
    </script>
  </body>
</html>

进阶参考