真正開發(fā)微信小程序時(shí)。
你才會(huì)發(fā)現(xiàn)它連最基本的一些輪子都要自己去造
在上一個(gè)答題的項(xiàng)目中,被一個(gè)非常小的功能折騰了整整三天
當(dāng)用戶在選擇題庫后,系統(tǒng)隨機(jī)從后臺(tái)返回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);
}
});
其中我將隨機(jī)選中的每道題的.userChose屬性定義為空,而在用戶每答一道題時(shí),就會(huì)將此屬性賦值為用戶的選項(xiàng),從而和正確答案進(jìn)行判斷用戶的對(duì)錯(cuò)和得分。
具體的邏輯就是 用戶選擇題庫 → 進(jìn)入作答頁面(后臺(tái)返回相應(yīng)題庫的隨機(jī)20道題)→ 解答第一道題(將對(duì)象數(shù)組中第一個(gè)對(duì)象的.userChose賦值)→ 自動(dòng)跳轉(zhuǎn)至第二道題(并在跳轉(zhuǎn)的過程中將更改過的包含20道題目的對(duì)象數(shù)組傳至下一題)→ 解答第二道題(將對(duì)象數(shù)組中第而個(gè)對(duì)象的.userChose賦值)…….
最終答題結(jié)束進(jìn)入交卷頁面,系統(tǒng)對(duì)比用戶每道題的選項(xiàng)和答案從而判卷。
作為corder的你看到這一邏輯,第一時(shí)間會(huì)想到其中的難點(diǎn)就是對(duì)包含20道題的對(duì)象數(shù)組進(jìn)行處理及傳遞,經(jīng)過我的入坑填坑,共有三種方式實(shí)現(xiàn)小程序中跨頁面?zhèn)鬟f對(duì)象數(shù)組
1.由頁面跳轉(zhuǎn)事件傳參
2.將每次進(jìn)行過更改的對(duì)象數(shù)組均上傳至服務(wù)器,然后進(jìn)入下一頁面再由服務(wù)器傳至本地
3.將對(duì)象數(shù)組存儲(chǔ)到全局變量中,一切操作均在全局變量完成
首先大部分人按照正常的開發(fā)邏輯都會(huì)選擇第一種方式,我也不例外,但是當(dāng)我輕松的寫完幾句代碼編譯后才發(fā)現(xiàn)事情并沒有我想的那么簡(jiǎn)單…
wx.navigateTo({
url: '../questionDetail/questionDetail?questionList=' + questionList
});
解釋一下上句代碼,在跳轉(zhuǎn)至questionDetail這個(gè)頁面時(shí),將本頁面的questionList這一變量帶到下一頁面并賦值給questionList。
但是編譯后我在下一頁面并沒有接收到相應(yīng)的數(shù)據(jù),并且很坑的是編譯器居然不報(bào)錯(cuò),導(dǎo)致我剛開始花了大量時(shí)間排查,最終多次測(cè)試才發(fā)現(xiàn)問題出現(xiàn)在對(duì)象數(shù)組這里,小程序不支持這種傳遞對(duì)象數(shù)組的方式。
于是我想到了更暴力的方式,對(duì)象數(shù)組不支持,字符串總支持吧,我在傳遞前將對(duì)象數(shù)組用JSON.stringify方法轉(zhuǎn)成字符串,并在下一個(gè)頁面接收到后再用JSON.parse轉(zhuǎn)回去。
但是編譯后依然不行,log下確實(shí)是成功的進(jìn)行了格式轉(zhuǎn)換,但是就是刷新不到頁面上去,于是這個(gè)方法也堵死了。
接著腦海里閃過第二個(gè)方法,將數(shù)據(jù)放到服務(wù)器處理,但是這一邪惡的想法立馬被pass,答題這種高頻的行為是,如果對(duì)數(shù)據(jù)進(jìn)行服務(wù)端的存入取出那耗費(fèi)的資源將遠(yuǎn)大于放在臨時(shí)內(nèi)存中。
所以只能采取第三種方式,其實(shí)說實(shí)話第三種方式反而比第一種更省資源一些,至少在跳轉(zhuǎn)頁面時(shí)會(huì)更流暢。
globalData: {
singleChoiceAnswerNow:[],
multiChoiceAnswerNow: [],
}
首先在app.js的全局變量中定義兩個(gè)空數(shù)組分別存儲(chǔ)單選和多選。
getApp().globalData.singleChoiceAnswerNow = that.data.questionList;
然后在做答完后將對(duì)象數(shù)組賦值給全局變量。
其實(shí)代碼寫多了,拿到一個(gè)需求后基本上大腦就可以條件反射出一種以上的實(shí)現(xiàn)方法。
初級(jí)程序員的職業(yè)素養(yǎng)分三級(jí),第一級(jí)是想到第一個(gè)辦法就網(wǎng)上擼代碼,什么時(shí)間復(fù)雜度都不管實(shí)現(xiàn)功能就行;
第二級(jí)是用最簡(jiǎn)單的方法實(shí)現(xiàn)功能,這里的簡(jiǎn)單是針對(duì)于自己的,例如剛才提到的第二種解決辦法,功能實(shí)現(xiàn),自己寫著舒服就行不管用戶用著難不難受。
第三級(jí)是至少羅列出三種以上的實(shí)現(xiàn)方法,并逐條分析其資源占用、時(shí)間復(fù)雜度、代碼量以及用戶體驗(yàn)等等因素,從中選擇出最適宜的方法去實(shí)現(xiàn)。
這也就是我一直的理念,產(chǎn)品經(jīng)理可以不會(huì)但是不能不懂技術(shù),軟件開發(fā)的一個(gè)各階段相互緊密交織的流程,是不能絕對(duì)的說“精細(xì)化分工效率更高”的。
產(chǎn)品和程序員撕逼的最大原因就是產(chǎn)品把需求全部下沉到技術(shù)那里。
另外在最終的答題卡頁面我覺得邏輯設(shè)計(jì)很復(fù)雜,因?yàn)槭紫纫@示得分?jǐn)?shù)據(jù),包括超過人數(shù)、得分率等等,最棘手的是在點(diǎn)擊作答題目后,進(jìn)入相應(yīng)題目的做答頁面,并包括用戶選項(xiàng)、得分及每一題的解析,并且可以直接在此頁面進(jìn)行上下題的切換。
注意我是將單選和多選分別放入兩個(gè)不同的對(duì)象數(shù)組中,所以還存在臨界值切換問題(即從單選最后一題跳至多選第一題,以及在只查看錯(cuò)題時(shí)的單選多選跳轉(zhuǎn))
把此頁面的代碼開源一下,供大家參考,因?yàn)楸疚闹饕鉀Q的是跳轉(zhuǎn)頁面?zhèn)鲗?duì)象數(shù)組的問題,所以就不對(duì)下述代碼進(jìn)行解析了。
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 =