真正開發微信小程序時。
你才會發現它連最基本的一些輪子都要自己去造
在上一個答題的項目中,被一個非常小的功能折騰了整整三天
當用戶在選擇題庫后,系統隨機從后臺返回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 =