真正开发微信小程序时。
你才会发现它连最基本的一些轮子都要自己去造
在上一个答题的项目中,被一个非常小的功能折腾了整整三天
当用户在选择题库后,系统随机从后台返回20道题目由用户作答,代码如下:
queryMultiQuestionBank.find({ success: function (results) { console.log("共查询到 " + results.length + " 条记录"); for (var i = 0; i < results.length; i++) { multiQuestionList.push(results[i]) } var newMultiQuestionList = that.getRandomSingleChoice(multiQuestionList, 20) for(i=0;i<20;i++){ newMultiQuestionList[i].attributes.userChose = "空"; } that.setData({ newMultiQuestionList: newMultiQuestionList, loading:false }); }, error: function (error) { console.log("查询失败: " + error.code + " " + error.message); } });
其中我将随机选中的每道题的.userChose属性定义为空,而在用户每答一道题时,就会将此属性赋值为用户的选项,从而和正确答案进行判断用户的对错和得分。
具体的逻辑就是 用户选择题库 → 进入作答页面(后台返回相应题库的随机20道题)→ 解答第一道题(将对象数组中第一个对象的.userChose赋值)→ 自动跳转至第二道题(并在跳转的过程中将更改过的包含20道题目的对象数组传至下一题)→ 解答第二道题(将对象数组中第而个对象的.userChose赋值)…….
最终答题结束进入交卷页面,系统对比用户每道题的选项和答案从而判卷。
作为corder的你看到这一逻辑,第一时间会想到其中的难点就是对包含20道题的对象数组进行处理及传递,经过我的入坑填坑,共有三种方式实现小程序中跨页面传递对象数组
1.由页面跳转事件传参
2.将每次进行过更改的对象数组均上传至服务器,然后进入下一页面再由服务器传至本地
3.将对象数组存储到全局变量中,一切操作均在全局变量完成
首先大部分人按照正常的开发逻辑都会选择第一种方式,我也不例外,但是当我轻松的写完几句代码编译后才发现事情并没有我想的那么简单…
wx.navigateTo({ url: '../questionDetail/questionDetail?questionList=' + questionList });
解释一下上句代码,在跳转至questionDetail这个页面时,将本页面的questionList这一变量带到下一页面并赋值给questionList。
但是编译后我在下一页面并没有接收到相应的数据,并且很坑的是编译器居然不报错,导致我刚开始花了大量时间排查,最终多次测试才发现问题出现在对象数组这里,小程序不支持这种传递对象数组的方式。
于是我想到了更暴力的方式,对象数组不支持,字符串总支持吧,我在传递前将对象数组用JSON.stringify方法转成字符串,并在下一个页面接收到后再用JSON.parse转回去。
但是编译后依然不行,log下确实是成功的进行了格式转换,但是就是刷新不到页面上去,于是这个方法也堵死了。
接着脑海里闪过第二个方法,将数据放到服务器处理,但是这一邪恶的想法立马被pass,答题这种高频的行为是,如果对数据进行服务端的存入取出那耗费的资源将远大于放在临时内存中。
所以只能采取第三种方式,其实说实话第三种方式反而比第一种更省资源一些,至少在跳转页面时会更流畅。
globalData: { singleChoiceAnswerNow:[], multiChoiceAnswerNow: [], }
首先在app.js的全局变量中定义两个空数组分别存储单选和多选。
getApp().globalData.singleChoiceAnswerNow = that.data.questionList;
然后在做答完后将对象数组赋值给全局变量。
其实代码写多了,拿到一个需求后基本上大脑就可以条件反射出一种以上的实现方法。
初级程序员的职业素养分三级,第一级是想到第一个办法就网上撸代码,什么时间复杂度都不管实现功能就行;
第二级是用最简单的方法实现功能,这里的简单是针对于自己的,例如刚才提到的第二种解决办法,功能实现,自己写着舒服就行不管用户用着难不难受。
第三级是至少罗列出三种以上的实现方法,并逐条分析其资源占用、时间复杂度、代码量以及用户体验等等因素,从中选择出最适宜的方法去实现。
这也就是我一直的理念,产品经理可以不会但是不能不懂技术,软件开发的一个各阶段相互紧密交织的流程,是不能绝对的说“精细化分工效率更高”的。
产品和程序员撕逼的最大原因就是产品把需求全部下沉到技术那里。
另外在最终的答题卡页面我觉得逻辑设计很复杂,因为首先要显示得分数据,包括超过人数、得分率等等,最棘手的是在点击作答题目后,进入相应题目的做答页面,并包括用户选项、得分及每一题的解析,并且可以直接在此页面进行上下题的切换。
注意我是将单选和多选分别放入两个不同的对象数组中,所以还存在临界值切换问题(即从单选最后一题跳至多选第一题,以及在只查看错题时的单选多选跳转)
把此页面的代码开源一下,供大家参考,因为本文主要解决的是跳转页面传对象数组的问题,所以就不对下述代码进行解析了。
var that; var Bmob = require('../../utils/bmob.js'); Page({ data: { score:0, choseQuestionBank:'', singleQuestionList: [], multiQuestionList: [], loading:true, defeatNumber: 0, averageScore: 0, correctRate: 0 }, onLoad: function (options) { that=this; var choseQuestionBank = getApp().globalData.choseQuestionBank; that.setData({ choseQuestionBank: choseQuestionBank }); var currentUser = Bmob.User.current(); var currentUserId = currentUser.id; var getSingleQuestionList = getApp().globalData.singleChoiceAnswerNow; var getMultiQuestionList = getApp().globalData.multiChoiceAnswerNow; console.log(getSingleQuestionList); for (var i = 0; i < 20; i++) { getSingleQuestionList[i].attributes.number = i + 1; } for (var j = 0; j < 20; j++) { getMultiQuestionList[j].attributes.number = j + 1; } var score = getApp().globalData.score; that.setData({ score: score, singleQuestionList: getSingleQuestionList, multiQuestionList: getMultiQuestionList, }); console.log(getSingleQuestionList); var saveSingleQuestionList=new Array(); var saveMultiQuestionList =