React.js小項目——隨機出題模組
功能簡介:
如下圖,在網頁上出一張試卷,該試卷由簡單題、一般題、難題按比例組成,並且每題是從對應題庫中隨機抽取,且答對的題目不會再出現。
實現思路:
確定模組:開始按鈕、試卷組件、題目組件、提交按鈕
確定模組結構: 開始按鈕 (調用) 試卷組件 (調用) 題目組件
試卷組件 (調用) 提交按鈕 (調用) 開始按鈕
具體流程:
1. 首先是建立三個用於測試的題庫,建立三個js檔案,在其中聲明二維數組,分別用於存放不同難度的題目(easyQuestions, simpleQuestions, hardQuestions),如圖為簡單題的題庫:
let easyQuestions = [ [ 'easyQuestion1', //問題 'A', //選項 'B', 'C', 'D', 'A' ], //答案 [ 'easyQuestion2', 'A', 'B', 'C', 'D', 'A' ], [ 'easyQuestion3', 'A', 'B', 'C', 'D', 'A' ], [ 'easyQuestion4', 'A', 'B', 'C', 'D', 'A' ], [ 'easyQuestion5', 'A', 'B', 'C', 'D', 'A' ]];
2.將題庫引入,接下來的問題就是如何做到隨機出題。在此我建立了一個專門用於產生隨機數數組的函數,並且產生的隨機數數組長度不超過題庫中題目的數量,根據隨機數數組中的數字來索引題庫中的題目,思路如圖:
代碼如下:
/* 函數功能:產生隨機數數組,通過該隨機數數組來擷取題庫中題目 */ function setRandomArr(arrIndex) { let originalArr = []; for (let i = 0; i < arrIndex.length; ++i){ originalArr[i] = i; } originalArr.sort(function() { return 0.5 - Math.random(); }); return originalArr; } //產生對應不同難度題庫的隨機數數組 let randomNumbersOfEasyQuestions = setRandomArr(easyQuestions); let randomNumbersOfSimpleQuestions = setRandomArr(simpleQuestions); let randomNumbersOfHardQuestions = setRandomArr(hardQuestions);
3.產生題目組件,將題目按照格式展示到網頁上,此處的題目組件只是做出了樣式,並沒有綁定展示的題目,展示的題目在產生試卷模組時決定,代碼如下:
class Question extends React.Component { constructor(props){ super(props); } render() { return ( <div className="questions" id = {this.props.id}> <p>({this.props.order}){this.props.questionsType}</p> <form action=""> <div className = "option"> <input type="radio" name={this.props.name} value="A"/> A </div> <div className = "option"> <input type="radio" name={this.props.name} value="B"/> B </div> <div className = "option"> <input type="radio" name={this.props.name} value="C"/> C </div> <div className = "option"> <input type="radio" name={this.props.name} value="D"/> D </div> </form> </div> ); } } Question.propTypes = { id : React.PropTypes.number.isRequired, //為每一個題目設定一個id order: React.PropTypes.number.isRequired, //設定每個題目的序號 questionsType : React.PropTypes.string.isRequired, //設定題目類型,簡單題/中等題/難題 name : React.PropTypes.string.isRequired //將每題的選項綁定一個name,防止題目選項勾選出問題 };
4.產生試卷模組,這一個模組的功能比較多,主要有:
(1)對應著隨機數組中的隨機數序列索引題庫中的題目,實現隨機出題
(2)調用上面的Question組件,將索引出的題目按照格式展現在網頁上
(3)產生提交按鈕組件
(4)點擊提交按鈕後,將提交的答案與正確答案比較
(5)比較完畢後,將每題的正誤情況返回,展示在網頁上,並調用開始測試按鈕,方便使用者進行下一輪測試
(6)在使用者正確答題的情況下,將該題在隨機數數組中的對應的隨機數索引刪除,保證該題下次不再出現
代碼如下:
//設定簡單題的數量const easyQuestionsLength = 2; //設定中等題的數量 const simpleQuestionsLength = 1;//設定難題的數量 const hardQuestionsLength = 1; //三組題目需要一個共同的計數單位 let nCount = 0; //暫且設定正確答案為A,若想對應到每題具體的答案,可以在submitAnswers()中將其改變成對應題目數組中的答案 let correctAnswer = "A"; class Paper extends React.Component { constructor(props){ super(props); this.initialPaper = this.initialPaper.bind(this); } initialPaper(questionArr, length, questionType, randomNumbersOfQuestionType) { for (let i = 0; i < length; ++i) { questionArr.push( <Question id = {nCount} order = {nCount + 1} questionsType = {questionType[randomNumbersOfQuestionType[i]][0]} name = {"question" + nCount} key = {nCount} />); ++nCount; } } submitAnswers() { nCount = 0; //提交答案的時候將nCount清零,用於下一次產生試卷時計數 let questionLength = (easyQuestionsLength + simpleQuestionsLength + hardQuestionsLength); let answers = []; //用於儲存使用者選擇的答案 let resultsArr = [];//用於儲存使用者選擇的答案的正誤 //向answers數組中push已經被選中的答案 for (let i = 0; i < questionLength; ++i) { let options = document.getElementsByName("question" + i); for (let j = 0; j < options.length; ++j) { if (options[j].checked) { answers.push(options[j].value); break; } } } //將answers數組中的答案與正確答案比較,向resultsArr中push最終結果 let easyCount, simpleCount, hardCount = 0; for (let i = 0; i < questionLength; ++i) { if (answers[i] == correctAnswer) { resultsArr.push(<p key={i} className="results">第{i+1}題:正確</p>); //答題正確則刪除相應題庫隨機數組中的序號,保證下次出題不再出現 if (i < easyQuestionsLength) { randomNumbersOfEasyQuestions.splice(i - easyCount, 1); ++easyCount; } else if(easyQuestionsLength <= i && i < (easyQuestionsLength + simpleQuestionsLength)) { randomNumbersOfSimpleQuestions.splice(i - simpleCount - easyQuestionsLength, 1); ++simpleCount; } else { randomNumbersOfHardQuestions.splice(i - hardCount - easyQuestionsLength - simpleQuestionsLength, 1); ++hardCount; } }else { resultsArr.push(<p key={i} className="results">第{i+1}題:錯誤</p>); } } //將答案渲染到網頁上 ReactDOM.render( <div> {resultsArr} <StartButton/> </div>, document.getElementById("container") ); } render() { let questionArr = []; this.initialPaper(questionArr, easyQuestionsLength, easyQuestions, randomNumbersOfEasyQuestions); this.initialPaper(questionArr, simpleQuestionsLength, simpleQuestions, randomNumbersOfSimpleQuestions); this.initialPaper(questionArr, hardQuestionsLength, hardQuestions, randomNumbersOfHardQuestions); return ( <div> {questionArr} <button id = "submitButton" onClick = {this.submitAnswers}>提交答案</button> </div> ); }}
5.產生開始按鈕組件,現在主體模組以及完成,接下來就是產生一個開始按鈕組件調用試卷組件就行啦,代碼如下:
class StartButton extends React.Component { constructor(props){ super(props); this.showPaper = this.showPaper.bind(this); } showPaper() { ReactDOM.render( <Paper/>, document.getElementById("container") ); } render() { return( <button id = "startButton" onClick = {this.showPaper}>開始測試</button> ); } }
6.渲染入口,將開始測試按鈕渲染到頁面上,代碼如下:
ReactDOM.render( <StartButton/>, document.getElementById("container") );
要查看完整的代碼請點擊此github倉庫連結