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