zoukankan      html  css  js  c++  java
  • 一个简单H5投票页面的踩坑记录

    一个简单H5投票页面的踩坑记录

    前端时间公司要做一个投票相关的传统H5页面,要求对于每组投票要有限制,但又不能完全限制。听到这里我就懵逼了,这怎么做呢。最后制定的规则是:每人每天只能投10票。感觉好像这样的功能都在后端,前端只需要处理用户的操作逻辑就ok了。最后证明自己很傻很天真!

    魔怔开启

    后端同学说需求方不需要用户登录,你直接Cookie存一下就可以了。开始我以为是让我把Cookie附带传给他呢,就因为这最后接口写好后发现他的意思是我在前端存储这些信息!!!既然这样,没办法就自己吭哧吭哧搞呗。

    重新梳理需求&制定方案

    既然要存储数据,那就从头至尾重新梳理下需求:
    1.不需要用户登录,要求每个人限投10票(其实只有用设备来识别)
    2.投完票后再次进入页面要显示“已投票”
    3.奖项列表页和公司详情页投票有关联性
    基于以上的需求,以及后端同学给的数据结构。拟定的前端存储的数据结构
    后端给的数据结构是这样的

    奖项投票数据

    {
        "reward_name": "奖项7",
        "reward_id": 1222,
        "votes_count": 10, #  可投票的候选数
        "candidates": [
            [
                "产品68",  # 公司名称
                "16856",   # candidate_id
                "23" # 投票数
            ],
            [
                "公司67",
                "16854",
                "1"
            ],
            [
                "产品66",
                "16852",
                "4252"
            ]
         ]
    }
    

    公司详情投票

    {
        "candidate_id": 16894,
        "rewards": [
            [
                "2017最受机构青睐私募基金公司·股票型",   #奖项名称
                "77",                               #奖项ID
                "0",                                #奖项可参与投票的公司数量,为0时,不可投票
                "32"                                # 被投票数
            ]
        ],
        "products": [
            {
                "name": "兴业信托•朱雀18期",
                "candidate_id": 16900,
                "rewards": [
                    [
                        "2017最具人气私募基金·股票型(三年期)",
                        "80",
                        "10",                       # 结构及其含义 同上
                        "32"                        # 被投票数
                    ]
                ]
            }
        ],
        "candidate_name": "上海朱雀资产管理公司"
    }
    

    说实话,这样的数据结构在我看来相当不友好。要不是后端同学当面说明真是完全不知所以,沟通了一下发现需求方给的数据更加扯淡,最后能抽象成这样已经很不错了。没办法,既然接口好了,那就将就一下吧。
    想了想如果用Cookie的话,对于简单的数据结构还可以。但是显然这这里不太适合,因为最后的这数据结构不可能太简单。我设计的前端数据存储结构是这样:

    {
    	"rewards_id": 23, //奖项id
      "count": 10, //可投票数
      "candidates":[45, 34, 44, 32] //已投公司
    }
    

    这样的话准备用localStorage来进行存储,但是明天怎么清空本地存储记录呢。那同样存个时间戳,每次登陆的时候去检测是否超过一天,如果超过就全部清空本地存储。看来这样可行。
    每次投完票,就去遍历localstore。查看rewards_id是否存在,存在则去检索其中的candidates是否有id,没有就加进去,票数-1,发送请求。否则就return false
    代码如下

    	//投票操作
      $('.presents-box').on('click', '.js-vote', function() {
      	var that = $(this);
        var rewards_id = that.parents().parents().parents().attr('reward_id');
      	var candidates_id = that.attr('candidates_id');
        var flag = true;
    
        localArr = JSON.parse(localStorage.getItem('presents'));
        if(localArr != null) {
          for(var i in localArr) {
            if(localArr[i].rewards_id == rewards_id) {
              if(localArr[i].count > 0) {
                localArr[i].candidates.push(candidates_id);
                localArr[i].count -= 1;
                localStorage.setItem('presents', JSON.stringify(localArr));
              } else {
                alert('您已不能再投票!');
                return false;
              }
              flag = false;
            }
          }
          if(flag) {console.log((parseInt($('.detail-votes').attr('count')) - 1))
            var obj = {
              rewards_id: parseInt(rewards_id),
              count: (parseInt($('.detail-votes').attr('count')) - 1),
              candidates:[candidates_id]
            };
            localArr.push(obj);
            localStorage.setItem('presents', JSON.stringify(localArr));
          }
        }
    
      	//投票请求
      	$.ajax({
      		type: 'post',
      		url: 'http://www.nbd.com.cn/activity/jdj2/votes?reward_id='+rewards_id+'&candidate_id='+candidates_id,
      		success: function(res) {
      			that.parents().parents().addClass('voted');
            that.removeClass('js-vote');
            that.text('已投票');
      		}
      	});
      });
    

    重刷新要显示已投结果,就用上面存储的本地数据去操作dom。这样需求就基本实现了,收工。
    投票后的结果如图,
    投票后结果

    刷新后结果不变,跳转到公司详情页的投票页,已投也会显示。如图,
    投票后结果

    开始踩坑

    第一脚坑

    这样测试了几个数据,没什么问题。但当真是数据上去之后就出现了问题,投票好像老是不对。开始快速查原因,从逻辑开始,好像逻辑没有问题,只有一步一步打印结果。最后发现这个坑是我自己造成的
    代码

    代码

    就是字段的名字给写错了,真是自己的坑自己填。

    第二脚坑

    在安卓上没有任何问题,当在ios上记录存储数据好像就有些问题了,刷新后不能记录。一开始我以为是平台差异性,在操作dom上会有些许差异。然后真机测试发现没有问题。那是怎么回事呢?设备上不好调试,但这种现象又只出现在真机设备上。之后copy一份在真机上调试打印数据,一点一点排查最终发现问题所在。
    代码

    oldTime是存储的本地时间,当第一次时localStorage是null,并且在iOS上是string。而在Android上是null,所以在Android上没问题,在iOS上每次都是true。所以都会清除掉存储的本地数据。然后就做了如下修改,

    var arr = JSON.parse(localStorage.getItem('presents')),
        nowTime = nowTime = new Date().getDate(),
        oldTime = JSON.parse(localStorage.getItem('time')),
        newArr = [];
    
    //iOS上
    oldTime = !!(navigator.userAgent).match(/(i[^;]+;( U;)? CPU.+Mac OS X/) && (oldTime == 'null') ? null : oldTime;
    
    //固定时间间隔清除localStorage
    if(Math.abs(nowTime - oldTime) >= 1 || oldTime == null ) {
      localStorage.clear();
      arr = JSON.parse(localStorage.getItem('presents'));
    }
    

    其实说坑也算不上很大,但是遇到的时候也是蛮坑人的。还有就是写代码变量名一定要明晰,造成不必要的麻烦。

  • 相关阅读:
    【转】Dalvik虚拟机的启动过程分析
    【转】Android 之ActivityThead、ActivityManagerService 与activity的管理和创建
    【转】应用程序的入口是ActivityThread
    【转】Android中Application类用法
    【转】360浏览器极速与兼容模式的解释
    操作系统学习(七)--操作系统之外设显示器和键盘
    操作系统学习(六)-- 虚拟内存(页面置换算法)
    操作系统学习(五)-- 操作系统之内存管理
    操作系统学习(四)-- 操作系统之进程同步和死锁
    数据库系统学习(八)-SQL语言与数据库完整性和安全性
  • 原文地址:https://www.cnblogs.com/marvinemao/p/7562238.html
Copyright © 2011-2022 走看看