zoukankan      html  css  js  c++  java
  • 原生JS结合cookie实现商品评分组件

    组件样式效果:

    再次访问记录用户上次操作:

    开发思路如下:

    1.利用JS直接操作DOM的方式开发商品评分组件,主要实现功能有:显示评价评分的样式以及将用户操作后对应的数据返回到主页面
    2.主页面引入商品评分组件的js文件并根据规定格式的数据,生成对应的组件元素并插入页面
    3.主页面利用侦听事件接收组件抛发的数据并保存,每次有组件抛发事件都会覆盖上次抛发的数据,直到页面关闭,将最后一次抛发的数据保存到cookie中。
    4.当再次打开主页面时,先判断cookie中是否有对应的数据,如果有提取cookie其中的数据,先根据页面数据生成对应的组件元素,再将cookie中数据传入对应组件元素中重新渲染,最后将元素插入主页面

    注意点:

    因为当再次打开页面,用户可能不一定会修改所有的组件元素,这样组件抛出的数据就不完整,不会是所有元素的数据,当我们在保存数据的时候需要和上一次保存的数据进行比对,只覆盖和上一次保存数据不同的属性,保证数据的完整性。

    主页面JS部分代码如下:

        import Star from "./js/Star.js";
        var data=["商品符合度","店家服务态度","快递配送速度","快递员服务","快递包装"];
        var cookieStorage={};
        // 初始化加载先拿到cookie,切割好数据之后,在初始化创建渲染完评分数据对象之后,再通过setData的方法修改数据
        var hository=JSON.parse(document.cookie.split("=")[1]);
        data.forEach((item)=>{
          var star=new Star(item);
          star.addEventListener("change",changeHandler);
          if(JSON.stringify(hository)!=="{}"){//判断cookie中是否有对应的数据
            star.setData(hository[item])
          }
          star.appendTo(".ShowStarList");
        })
        cookieStorage=hository;
        function changeHandler(e){
          for(var prop in e.StarList){//因为当再次打开页面,用户可能不一定会修改所有的组件元素,这样抛出的数据就不完整不会是所有元素的数据
            cookieStorage[prop]=e.StarList[prop];
          }
        }
        //页面点击操作之后,将数据存放到cookieStorage中,当下一次再点击时将cookieStorage中的数据覆盖
        // 直到页面被关闭时,触发下述事件,将cookieStorage+时间段的方式存储到cookie中
        window.onbeforeunload=closeHandler;
        function closeHandler(){
          var date=new Date();
          date.setFullYear(2021);
          document.cookie="cookieStorage="+JSON.stringify(cookieStorage)+";expires="+date.toUTCString();
        }
    

    商品评分组件JS部分代码如下:

    import Base from "./Base.js";
    export default class Star extends Base{
      static StarList = {};//用来存储数据选中的评分数据到时候返回页面
      label;
      starCon = [];
      pos=-1
      labelWrap;
      starWrap;
      face;
      scoreWrap;
    
      constructor(_label) {
        // 第一次创建是用label生成的对象,后面都是用StarList去渲染对象
        super();
        this.label = _label;
        this.elem.setAttribute("class", "StarCon");
        this.createStarCon();
        this.setStyle();
      }
      //创建评分组件的HTML结构
      createStarCon() {
        this.labelWrap = document.createElement("span");
        this.labelWrap.textContent = this.label;
        this.starWrap = document.createElement("div");
        for (let i = 0; i < 5; i++){
          let singleStar = document.createElement("div");
          singleStar.setAttribute("class", "singleStar");
          this.starWrap.appendChild(singleStar);
          this.starCon.push(singleStar);
        }
        this.face = document.createElement("div");
        this.starWrap.appendChild(this.face);
        this.scoreWrap = document.createElement("span");
        this.scoreWrap.textContent = "0分";
        this.labelWrap.setAttribute("class", "label");
        this.starWrap.setAttribute("class", "star");
        this.face.setAttribute("class", "face");
        this.scoreWrap.setAttribute("class", "score");
        this.elem.appendChild(this.labelWrap);
        this.elem.appendChild(this.starWrap);
        this.elem.appendChild(this.scoreWrap);
        this.starWrap.addEventListener("mouseover",e=>this.mouseHandler(e));
        this.starWrap.addEventListener("click",e=>this.mouseHandler(e));
        this.starWrap.addEventListener("mouseleave",e=>this.mouseHandler(e));
      }
    
      mouseHandler(e) {
        // click和mouseover都要不停渲染星星样式,所以都要通过遍历识别鼠标当前指向的是哪个e.target,从而通过for循环渲染星星
        // 其中点击事件和鼠标移动事件不同的地方在于
        // 点击事件会记录下一个全局变量pos表示选中该数据,且会抛出事件传递包括同页面其他实例对象的数据给页面
        // 鼠标移动事件则是利用相同原理除了渲染星星外,还要渲染分数和笑脸
        switch (e.type) {
          case "mouseover":
            let index = this.starCon.indexOf(e.target);
            if (index < 0) return;
            this.changeScore(index + 1);
            this.changeFace(index);
            this.changeStar(index);
            break;
          case "click":
            let index1 = this.starCon.indexOf(e.target);
            if (index1 < 0) return;
            this.pos = index1;
            this.dispatch();
            this.changeStar(index1);
            break;
          case "mouseleave":
            this.changeStar(this.pos);
            this.changeScore(this.pos + 1);
            this.changeFace(-1);
            break;
        }
      }
      //根据分数改变星星样式
      changeStar(n){
          for(var i=0;i<this.starCon.length;i++){
              if(i<=n || i<=this.pos){
                this.starCon[i].style.backgroundPositionY="-16px";
              }else{
                this.starCon[i].style.backgroundPositionY="0px";
              }
          }
      }
      //根据分数改变分数样式
      changeScore(n){
          this.scoreWrap.textContent=n+"分";
          if(n===0){
            this.scoreWrap.style.color="#999";
          }else{
            this.scoreWrap.style.color="#e4393c";
          }
      }
      //根据分数改变笑脸样式
      changeFace(n){
          if(n<0){
              this.face.style.display="none";
              return
          }
        var index=5-n-1
        // 鼠标移动时,笑脸的div位置和其背景图的位置都要同时移动
        // 鼠标离开或者点击之后,笑脸消失
        this.face.style.display="block";
        this.face.style.backgroundPositionX=-index*20+"px";
        this.face.style.left=this.starCon[n].offsetLeft+"px";
      }
      //每次点击后抛发改变后的实例化组件元素群组的数据
      dispatch() {
        Star.StarList[this.label]=this.pos+1;
        var evt=new Event("change");
        evt.score=this.pos+1;
        evt.label=this.label;
        evt.StarList=Star.StarList;
        this.dispatchEvent(evt);
      }
      //根据cookie传入的数据重新渲染组件元素
      setData(historyScore) {
        if (historyScore < 1) return;
        this.pos = historyScore-1;
        this.changeStar(historyScore-1);
        this.changeScore(historyScore);
      }
      //设置实例化组件的样式
      setStyle() {
        Utils.addCSS(".label",{
          float: "left",
          height: "16px",
          font: '12px / 150% tahoma, arial, "Microsoft YaHei", "Hiragino Sans GB", 宋体, sans-serif',
          marginRight: "10px",
          overflow: "hidden",
          whiteSpace: "nowrap",
          textOverflow: "ellipsis",
          color: "rgb(102, 102, 102)",
        });
        Utils.addCSS(".star",{
          float: "left",
          height: "16px",
          position: "relative",
          marginTop: "1px",
        });
        Utils.addCSS(".singleStar",{
          float: "left",
          height: "16px",
           "16px",
          backgroundImage: "url(../img/commstar.png)",
          backgroundPositionY: "0px",
        });
        Utils.addCSS(".face",{
          height: "16px",
           "16px",
          backgroundImage: "url(../img/face-red.png)",
          position:"absolute",
          top:"-16px",
          display: "none",
          backgroundPositionX:"0px",
          left:"0px",
        });
        Utils.addCSS(".score",{
          position:"relative",
          "30px",
          height:"16px",
          top:"-2px",
          marginLeft: "10px",
          font: '12px / 150% tahoma, arial, "Microsoft YaHei", "Hiragino Sans GB", 宋体, sans-serif',
          textAlign:"right",
          color:"#999",
        });
    
      }
    }
    
  • 相关阅读:
    Access导入MSSQL SERVER
    Centos8停用、启用、查看当前启用的端口
    CentOS下使用VI
    CentOS关机与重启命令
    华为云CentOS8安装FTP
    华为云CentOS8安装JDK
    华为云CentOS8安装Nginx
    华为云CentOS8安装Redis
    华为云CentOS8安装MYSQL
    oracle 本地导入imp bat的写法
  • 原文地址:https://www.cnblogs.com/myErebos/p/13911660.html
Copyright © 2011-2022 走看看