20230401----重返学习-冒泡相关事件-拖拽-放大镜

这篇具有很好参考价值的文章主要介绍了20230401----重返学习-冒泡相关事件-拖拽-放大镜。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

day-040-forty-20230401-冒泡相关事件-拖拽-放大镜

冒泡相关事件

mouseenter/mouseleave与mouseover/mouseout

  • mouseover/mouseout 有冒泡,忽略层级之间的关系

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>冒泡机制</title>
        <style>
          * {
            margin: 0;
            padding: 0;
          }
          #parent {
            height: 500px;
            width: 500px;
            background-color: red;
          }
          #son {
            height: 300px;
            width: 300px;
            background-color: blue;
          }
        </style>
      </head>
      <body>
        <div id="parent">
          <div id="son"></div>
        </div>
      </body>
    </html>
    <script>
      let parent = document.getElementById("parent");
      let son = document.getElementById("son");
      parent.onmouseover =function(){
        console.log('parent移入-onmouseover')
      }
      parent.onmouseout =function(){
        console.log('parent移出-onmouseout')
      }
      son.onmouseover =function(){
        console.log('son移入-onmouseover')
      }
      son.onmouseout =function(){
        console.log('son移出-onmouseout')
      }
    </script>
    
  • mouseenter/mouseleave 没冒泡,不会忽略层级之间的关系

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>冒泡机制</title>
        <style>
          * {
            margin: 0;
            padding: 0;
          }
          #parent {
            height: 500px;
            width: 500px;
            background-color: red;
          }
          #son {
            height: 300px;
            width: 300px;
            background-color: blue;
          }
        </style>
      </head>
      <body>
        <div id="parent">
          <div id="son"></div>
        </div>
      </body>
    </html>
    <script>
      let parent = document.getElementById("parent");
      let son = document.getElementById("son");
      parent.onmouseenter =function(){
        console.log('parent移入-onmouseenter')
      }
      parent.onmouseleave =function(){
        console.log('parent移出-onmouseleave')
      }
      son.onmouseenter =function(){
        console.log('son移入-onmouseenter')
      }
      son.onmouseleave =function(){
        console.log('son移出-onmouseleave')
      }
    </script>
    

事件委托

  • 事件委托: 也叫事件代理,将绑定的事件委托给祖先元素,祖先元素监听事件,并利用e.target来分配给当前元素
    • 原理是: 事件冒泡机制
  • 事件委托的好处
    1. 减少事件数量,提高性能

    2. 预测未来元素,新添加的元素仍然可以触发该事件

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <title>2.事件委托</title>
        </head>
        <body>
          <ul class="ulBox">
            <li>001</li>
            <li>002</li>
            <li>003</li>
            <p>ppp</p>
            <li>004</li>
            <li>005</li>
          </ul>
        </body>
      </html>
      <script>
        // let ulBox = document.querySelector(".ulBox");
        // let newli1 = document.createElement("li");
        // newli1.innerHTML = "aaa";
        // ulBox.appendChild(newli1);
        // let lis = document.querySelectorAll("li");
        // for (let i = 0; i < lis.length; i++) {
        //   lis[i].onclick = function () {
        //     console.log(i);
        //   };
        // }
        // let newli2 = document.createElement("li");
        // newli2.innerHTML = "bbb";
        // ulBox.appendChild(newli2);//这个默认没事件
      
        let ulBox = document.querySelector(".ulBox");
        let newli1 = document.createElement("li");
        newli1.innerHTML = "aaa";
        ulBox.appendChild(newli1);
        ulBox.onclick = function (e) {
          if (e.target.tagName === "LI") {
            console.log(e.target);
          }
        };
        let newli2 = document.createElement("li");
        newli2.innerHTML = "bbb";
        ulBox.appendChild(newli2); //这个依旧有事件
      </script>
      
    3. 避免内存外泄,在低版本的IE中,防止删除元素而没有移除事件而造成的内存溢出

点击案例

点击按钮会打印出内部data-type属性的值

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>3.点击事件</title>
</head>
<body>
  <div class="box">
    <button data-type="+">+</button>
    <button data-type="-">-</button>
    <button data-type="*">*</button>
    <button data-type="/">/</button>
  </div>
</body>
</html>
<script>
  let box = document.querySelector('.box')
  box.onclick=function(e){

    if(e.target.tagName==='BUTTON'){
      const theDataType = e.target.getAttribute('data-type')
      console.log(theDataType)
    }
  }
</script>

拖拽

简版

  1. 对小盒子绑定一个mousedown鼠标点击事件
    1. 移入到小盒子里面按下时,通过e.offsetX与e.offsetY获取鼠标相对于当前盒子中的初始坐标
    2. 对window绑定一个mouseup事件。在整个页面,按着鼠标移动,抬起的瞬间求结束坐标
      • mouseup事件事件中,通过e.pageX与e.pageY拿到鼠标相对于文档的终点坐标,之后修改小盒子的top与left。
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>拖拽</title>
    <style>
      .box {
        height: 100px;
        width: 100px;
        background-color: skyblue;

        position: absolute;
        top: 0px;
        left: 0px;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
  </body>
</html>
<script>
  let box = document.querySelector(".box");
  let startX=0, startY=0, endX=0, endY=0;
  box.onmousedown = function (e) {
    //移入到小盒子里面按下获取初始坐标
    startX = e.offsetX;
    startY = e.offsetY;
    console.log(startX, startY);

    //在整个页面,按着鼠标移动,抬起的瞬间求结束坐标
    window.addEventListener("mouseup", move);
  };

  const move = function move(e) {
    //结束坐标
    endX = e.clientX;
    endY = e.clientY;

    //盒子最后的位置  结束坐标-初始坐标
    box.style.left = endX - startX + "px";
    box.style.top = endY - startY + "px";

    //抬起结束后,要移除抬起事件,否则盒子就一直还跟着鼠标
    window.removeEventListener("mouseup", move);
  };
</script>

有限制版

  • 鼠标在当前元素中的坐标替换

    • e.offsetX可以用e.clientX-box.offsetLeft代替

    • e.offsetY可以用e.clientY-box.offsetTop

      box.onmousedown=function(e){//进入盒子按下的一瞬间,获取初始坐标
        startX=e.offsetX;
        startY=e.offsetY;
        //再整个文档中移动鼠标,抬起瞬间获取结束坐标
      }
      //等价于
      box.onmousedown = function (e) {
        startX = e.clientX - box.offsetLeft;
        startY = e.clientY - box.offsetTop;
      };
      
  • 在小盒子点击后,添加了window的mousemove事件。

    • 用于让小盒子在鼠标没松开时,一直跟随着鼠标移动。
      • 同时对于小盒子的移动范围进行了限制,让其只能在视口中出现
        • 视口用的客户端宽度document.documentElement.clientWidth减去当前小盒子宽度box.offsetWidth来计算得出的
  • 在小盒子移动后,依旧使用window的mouseup事件移除mousemove对应函数及mouseup对应事件函数文章来源地址https://www.toymoban.com/news/detail-402685.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>拖拽3</title>
    <style>
      .box {
        height: 100px;
        width: 100px;
        background-color: skyblue;

        position: absolute;
        top: 0px;
        left: 0px;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
  </body>
</html>
<script>
  let box = document.querySelector(".box");
  let startX, startY;
  box.onmousedown = function (e) {
    // //移入到小盒子里面按下获取初始坐标
    // startX = e.offsetX;
    // startY = e.offsetY;
    // 假设无法通过offsetX/offsetY获取初始坐标
    startX = e.clientX - this.offsetLeft;
    startY = e.clientY - this.offsetTop;

    console.log(startX, startY);

    //在整个页面,按着鼠标移动,抬起的瞬间求结束坐标
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseup", up);
  };

  const move = function move(e) {
    let html = document.documentElement || document.body;
    let maxWidth = html.clientWidth - box.offsetWidth;
    let maxHeight = html.clientHeight - box.offsetHeight;

    //结束坐标
    let endX = e.clientX;
    let endY = e.clientY;

    let resX = endX - startX;
    resX = Math.max(0, resX);
    resX = Math.min(maxWidth, resX);

    let resY = endY - startY;
    resY = Math.max(0, resY);
    resY = Math.min(maxHeight, resY);

    //盒子最后的位置  结束坐标-初始坐标
    box.style.left = resX + "px";
    box.style.top = resY + "px";
  };
  const up = function up(e) {
    window.removeEventListener("mousemove", move);
    window.removeEventListener("mouseup", up);
  };
</script>

多盒拖拽

  1. 每个盒子都有自己的起始坐标,结束坐标,范围值,多个盒子之间互不影响…
  2. 思路是:
    • 给每个盒子添加 私有的属性值
      • 在mousedown事件中使用this来给每个盒子添加需要用到的私有属性值
        • 如果是事件,也要修改this指向
          • 修改this指向,可以使用函数原型__proto__上的call()、apply()、bind()。这里主要使用bind()。
    • 在小盒子点击后,添加了window的mousemove事件,用于让小盒子跟随鼠标移动。
    • 在小盒子移动后,依旧使用window的mouseup事件移除mousemove对应函数及mouseup对应事件函数。
<!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>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      #box {
        height: 100px;
        width: 100px;
        background-color: pink;
        position: fixed;
        left: 0;
        top: 0;
      }
      #boxtwo {
        height: 200px;
        width: 200px;
        background-color: aqua;
        position: fixed;
        left: 0;
        top: 200px;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <div id="boxtwo"></div>
  </body>
</html>
<script>
  let html = document.documentElement || document.body;
  //每个盒子都有自己的起始坐标,结束坐标,范围值...
  //给每个盒子添加 私有的属性值
  function down(e) {
    this.startX = e.offsetX;
    this.startY = e.offsetY;

    //修改this指向 call apply bind
    this._move = move.bind(this);
    this._up = up.bind(this);

    window.addEventListener("mousemove", this._move);
    window.addEventListener("mouseup", this._up);
  }

  function move(e) {
    //console.log(this);//window
    //console.log(e.target);
    this.endX = e.clientX;
    this.endY = e.clientY;

    this.resultX = this.endX - this.startX;
    this.resultY = this.endY - this.startY;

    this.maxW = html.clientWidth - this.offsetWidth;
    this.maxH = html.clientHeight - this.offsetHeight;

    this.resultX = this.resultX >= this.maxW ? this.maxW : this.resultX <= 0 ? 0 : this.resultX;
    this.resultY = this.resultY >= this.maxH ? this.maxH : this.resultY <= 0 ? 0 : this.resultY;

    this.style.left = this.resultX + "px";
    this.style.top = this.resultY + "px";
  }

  function up() {
    window.removeEventListener("mousemove", this._move);
    window.removeEventListener("mouseup", this._up);
  }

  box.addEventListener("mousedown", down);
  boxtwo.addEventListener("mousedown", down);
</script>

放大镜

放大镜简版

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      .box {
        width: 700px;
        margin: 50px auto;
        height: 400px;
        display: flex;
      }
      .leftbox {
        width: 300px;
        height: 300px;
        position: relative;
      }
      .leftbox img {
        width: 300px;
        height: 300px;
      }
      .leftbox .mark {
        display: none;
        width: 100px;
        height: 100px;
        background-color: red;
        opacity: 0.5;
        position: absolute;
        left: 0;
        top: 0;
      }
      .rightbox {
        display: none;
        width: 400px;
        height: 400px;
        overflow: hidden;
        position: relative;
      }
      .rightbox img {
        /* width:1200px;
        height:1200px;   */
        position: absolute;
        left: 0;
        top: 0;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="leftbox">
        <img src="images/1.jpg" alt="" />
        <div class="mark"></div>
      </div>
      <div class="rightbox">
        <img src="images/2.jpg" alt="" />
      </div>
    </div>
  </body>
</html>
<script>
  (function () {
    //1.求出大图片的高度和宽度
    let leftbox = document.querySelector(".leftbox"); //左侧盒子
    let mark = document.querySelector(".mark"); //遮罩层
    let rightbox = document.querySelector(".rightbox"); //右侧盒子
    let bigimg = document.querySelector(".rightbox img"); //大图片

    function getwh(ele, attr) {
      return parseFloat(window.getComputedStyle(ele)[attr]);
    }

    //左侧盒子 高度和宽度
    let leftboxW = leftbox.offsetWidth;
    let leftboxH = leftbox.offsetHeight;

    //右侧盒子 高度和宽度
    //隐藏的盒子无法通过offsetWidth/offsetHeight 求值,默认为0
    let rightboxW = getwh(rightbox, "width");
    let rightboxH = getwh(rightbox, "height");

    //遮罩层 高度和宽度
    let markW = getwh(mark, "width");
    let markH = getwh(mark, "height");

    //设置大图片的高度和宽度
    bigimg.style.width = (rightboxW / markW) * leftboxW + "px";
    bigimg.style.height = (rightboxH / markH) * leftboxH + "px";

    //移入盒子,mark和右侧盒子显示
    leftbox.onmouseenter = function () {
      mark.style.display = "block";
      rightbox.style.display = "block";
    };
    //移出盒子,mark和右侧盒子隐藏
    leftbox.onmouseleave = function () {
      mark.style.display = "none";
      rightbox.style.display = "";
    };

    //鼠标在左侧小盒移动,mark也移动
    leftbox.onmousemove = function (e) {
      let cx = e.clientX;
      let cy = e.clientY;
      let maxW = leftboxW - markW;
      let maxH = leftboxH - markH;

      let resX = cx - markW / 2 - leftbox.offsetLeft;
      let resY = cy - markH / 2 - leftbox.offsetTop;

      resX = resX < 0 ? 0 : resX > maxW ? maxW : resX;
      resY = resY < 0 ? 0 : resY > maxH ? maxH : resY;

      //移动红色遮罩层
      mark.style.left = resX + "px";
      mark.style.top = resY + "px";

      //移动大图片---按照比率
      bigimg.style.left = "-" + (rightboxW / markW) * resX + "px";
      bigimg.style.top = "-" + (rightboxH / markH) * resY + "px";
    };
  })();
</script>

个人优化版

  • 用了css变量,在容器上放置了相对定位对放大镜用了绝对定位。
    • 进一步优化,.left-box为容器,大图片盒子放在.left-box里,去除.box这一层级。
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      .box {
        --min-image-width: 300px;
        --min-image-height: 300px;
        --mark-width: 100px;
        --mark-height: 100px;
        --scale: 4;
        margin: 250px;
        display: flex;
        position: relative;
      }
      .box .left-box {
        width: var(--min-image-width);
        height: var(--min-image-height);
        position: relative;
      }
      .box .left-box img {
        width: var(--min-image-width);
        height: var(--min-image-height);
      }
      .box .left-box .mark {
        display: none;
        width: var(--mark-width);
        height: var(--mark-height);
        background-color: red;
        opacity: 50%;
        position: absolute;
        left: 0px;
        top: 0px;
      }
      .box .right-box {
        display: none;
        width: calc(var(--mark-width) * var(--scale));
        height: calc(var(--mark-height) * var(--scale));
        overflow: hidden;
        position: absolute;
        left: var(--min-image-width);
        top: 0px;
      }
      .box .right-box img {
        width: calc(var(--min-image-width) * var(--scale));
        height: calc(var(--min-image-height) * var(--scale));
        position: absolute;
        left: 0px;
        top: 0px;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="left-box">
        <!-- <img src="./images/1.jpg" alt="小图"> -->
        <img
          src="https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1672220519.85821941.png"
          alt="大图"
        />
        <div class="mark"></div>
      </div>
      <div class="right-box">
        <img
          src="https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1672220519.85821941.png"
          alt="大图"
        />
      </div>
    </div>
  </body>
  <script>
    (function () {
      //1. 未出图片的高度和宽度
      let box = document.querySelector(".box");
      let leftBox = box.querySelector(".left-box");
      let mark = leftBox.querySelector(".mark");
      let rightBox = box.querySelector(".right-box");
      let bigImage = rightBox.querySelector("img");

      //左侧盒子 高度和宽度
      let leftBoxWidth = leftBox.offsetWidth;
      let leftBoxHeight = leftBox.offsetHeight;

      const getWH = function getWH(ele, attr) {
        // console.log(window.getComputedStyle(ele)[attr]);
        return parseInt(window.getComputedStyle(ele)[attr]) || 0;
      };

      //右侧盒子 高度和宽度
      // 隐藏的盒子无法通过offsetWidth/offsetHeight求值,默认为0
      let rightBoxWidth = getWH(rightBox, "width");
      let rightBoxHeight = getWH(rightBox, "height");

      let markWidth = getWH(mark, "width");
      let markHeight = getWH(mark, "height");

      let bigImageWidth = (rightBoxWidth / markWidth) * leftBoxWidth;
      let bigImageHeight = (rightBoxHeight / markHeight) * leftBoxHeight;
      // console.log(bigImageWidth, bigImageHeight);

      bigImage.style.width = `${bigImageWidth}px`;
      bigImage.style.height = `${bigImageHeight}px`;

      leftBox.onmouseenter = function () {
        mark.style.display = "block";
        rightBox.style.display = "block";
      };
      leftBox.onmouseleave = function () {
        mark.style.display = "none";
        rightBox.style.display = "none";
      };

      leftBox.onmousemove = function (e) {
        let cx = e.clientX;
        let cy = e.clientY;

        let maxWidth = leftBoxWidth - markWidth;
        let maxHeight = leftBoxHeight - markHeight;

        let resX = cx - markWidth / 2 - leftBox.getBoundingClientRect().left;
        let resY = cy - markHeight / 2 - leftBox.getBoundingClientRect().top;
        console.log(cx, cy, resX, resY, maxWidth, maxHeight);

        resX = resX < 0 ? 0 : resX > maxWidth ? maxWidth : resX;
        resY = resY < 0 ? 0 : resY > maxHeight ? maxHeight : resY;

        mark.style.left = `${resX}px`;
        mark.style.top = `${resY}px`;

        bigImage.style.left = `-${resX * (rightBoxWidth / markWidth)}px`;
        bigImage.style.top = `-${resY * (rightBoxHeight / markHeight)}px`;
      };
    })();
  </script>
</html>

进阶参考

到了这里,关于20230401----重返学习-冒泡相关事件-拖拽-放大镜的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入理解JavaScript的事件冒泡与事件捕获

    JavaScript中提供了很多操作DOM的API。 事件冒泡 和 事件捕获 是指浏览器中处理DOM元素上事件的两种不同方式。事件冒泡和事件捕获都是 JavaScript事件模型 中的一部分,可以用来 处理事件 。 对于这个问题,在实际开发中,并不是非常重要,因为在工作中我们基本上不会直接操

    2024年02月10日
    浏览(36)
  • JavaScript中的事件冒泡和事件捕获机制

    JavaScript中的事件冒泡和事件捕获机制是开发中非常重要的概念,掌握了这两种机制,可以更好地理解事件处理和DOM操作。本文将深入探讨JavaScript中的事件冒泡和事件捕获机制,包括它们的工作原理、如何使用它们、以及它们的优缺点。 一、什么是事件冒泡和事件捕获机制?

    2024年02月03日
    浏览(26)
  • 20230712----重返学习-权限校验

    无权限直接移除需权限校验的视图v-if版 登录时拿到用户所有的权限标识列表并保存到vuex中。 v-if中判断vuex中权限标识列表是否包含有当前v-if对应按钮或视图的权限标识,没有就直接移除。 无权限直接移除需权限校验的视图-自定义指令版 登录时拿到用户所有的权限标识列表

    2024年02月15日
    浏览(22)
  • 20230602----重返学习-React路由

    新版的是react-router-dom是6版本,而旧版的是5版本。 基于前端路由实现SPA单页面应用,其核心在于:构建路由表(构建路由匹配机制)。 每一次 路由切换 (包含 刚开始第一次渲染页面 ),都会拿 当前的地址 (或者 哈希值 )去路由表中进行查找匹配,找到相匹配的组件。 包含

    2024年02月07日
    浏览(21)
  • 20230406----重返学习-AJAX

    AJAX全称async javascript and xml。 以前的数据一般是xml,现在大多是json。 AJAX不是一种新的技术,而一个与后端通信的方式。 特色: 异步获取数据,局部更新页面。 数据渲染 服务器渲染 客户端渲染----(局部更新页面) 服务器渲染 [外链图片转存失败,源站可能有防盗链机制,建议将图

    2023年04月10日
    浏览(21)
  • 20230428----重返学习-vue项目

    配置开发服务器 如果没有后端接口,可以直接通过浏览器控制台看到别人网站的接口。 Shift+Control+I打开浏览器控制台,点击Network查看网络请求,点击Fetch/XHR,查看当前页面发送的请求。 触发请求,可以看到浏览器向别人的后端发送的请求及请求信息。 复制一下请求路径和

    2024年02月01日
    浏览(21)
  • uniapp阻止事件冒泡

    在 UniApp 中,阻止事件冒泡的方式与普通的前端开发类似,可以使用 @click.stop 或 @tap.stop 事件修饰符来阻止事件的进一步传播。 以下是在 UniApp 中阻止事件冒泡的示例:   在上面的示例中,当点击内部按钮时,通过 @click.stop 修饰符阻止了事件冒泡,因此不会触发外部按钮的点

    2024年02月08日
    浏览(23)
  • Vue中阻止事件冒泡

    vue中阻止时间冒泡: @click.stop : 阻止事件冒泡 @click.prevent : 阻止事件默认行为 @click.self : 事件只作用在元素本身,而不是其子元素。

    2024年02月13日
    浏览(26)
  • 事件冒泡和捕获

    在JS中,我们管事件发生的顺序叫“事件流”,当触发某个事件时,会发生一系列的连锁反应 如果给每个标签都绑定一个事件,当点击a标签时,会发现绑定在div和p标签上的事件也会被触发,这是为什么呢?为了解答这个问题,微软和网景公司提出了两种不同的概念:事件捕

    2024年02月09日
    浏览(23)
  • WPF鼠标、键盘、拖拽事件、用行为封装事件

    本文主要介绍了WPF中常用的鼠标事件、键盘事件以及注意事项,同时使用一个案例讲解了拓展事件。除此之外,本文还讲述如何用行为(Behavior)来封装事件。 Windows中的事件通过消息机制来完成,也就是Windows系统来捕获用户输入(如鼠标点击、键盘输入),然后Windows发送一

    2024年01月23日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包