使用JavaScript的动态测验-添加“返回”按钮

gudnpqoy  于 2023-04-10  发布在  Java
关注(0)|答案(2)|浏览(153)

我是一名业余程序员,正在构建一个动态测验,作为javascriptissexy's blog初学者课程的一部分。
我有一堆问题存储在这样的数组中:

var allQuestions = [
{question: "Which of the following is true about a cat's whiskers?", choices: ["Unlike fur, they don't shed at all", "Defend against predators", "They work as sensors", "They serve no purpose at all"], correctAnswer: 2},
{question: "How are cats different from dogs?", choices: ["Cats have the ability to move in the air", "Cats are highly social animals", "Dogs are independent but cats are the opposite", "Dogs love children but cats dont"], correctAnswer: 0},
{question: "What is a sure way of getting a cat's attention if you don't have treats?", choices: ["Call its name", "Stimulate the cat's curiousity", "Cats never pay attention to humans", "Serve some vegetarian food"], correctAnswer: 1},
];

选项被设置为单选输入。问题和选项一次显示一个。当用户单击“下一步”时,页面将显示数组中的下一组问题和选项。如果用户未进行选择就单击“下一步”,则页面不会更新-将弹出一个警告,通知用户选择选项。在最后一个问题处,“下一步”按钮将更改为“提交”,当用户单击“提交”时,显示总得分。
我的问题是,我试图添加一个“上一个”按钮,这样当点击时,用户可以查看上一个问题(直到第一个问题)沿着他们所做的选择,也可以更改他们的答案。我很难定义处理函数并跟踪上一个问题的答案。我是否需要使用一个闭包?
下面是到目前为止我的代码的链接:fiddle

rnmwe5a2

rnmwe5a21#

有很多方法可以在这里工作,但这里有一个方法。首先,跟踪用户提交的答案:

function collectUserAnswer() {
    allQuestions[pos].userAnswer =
        document.querySelector('input[name="choice"]:checked').value; 
}

然后,当你向后看时,你需要确保你填写了用户的答案,如果他们选择了一个:

function createChoices() {
    for(var i = 0; i < 4; i++) {
        var choice = document.getElementsByTagName("p")[i];
        var option = "<input id='ans_" + i 
            + "' type='radio' name='choice' value='" 
            + i + "'";

        if ( i == allQuestions[pos].userAnswer ) {
            option += " checked='checked'";   
        }
        option +=  ">" + allQuestions[pos].choices[i] 
               + "</input>";

        choice.innerHTML = option;
    }
}

当你计算分数时,不需要记录累计分数会更容易。使用累计分数,当用户向前导航时,你需要一组逻辑,当用户向后导航时,你需要一组不同的逻辑。相反,我们可以使用一组逻辑,每次只计算整个分数:

function calcScore() {
    var score = 0;
    for ( var i = 0; i < allQuestions.length; i++ ) {
        if ( allQuestions[i].userAnswer == allQuestions[i].correctAnswer ) {
            score++;
        }
    }
    this.totalScore = score;
}

接下来,你必须根据当前选择的问题复制创建正确按钮的逻辑,并将其放在updatePrevious()函数中。但是每当我看到代码重复时,我认为这是一个很好的机会,可以将重复的代码拆分到自己的函数中,这样我就可以重用它而不重复它。这样,如果你在代码中发现一个bug,你不需要找到你复制bug的所有地方,然后在所有这些地方修复它。所以,我会像这样分解它:

function updateNavigationButtons() {
    if(pos < len) {
        createQuestion();
        createChoices();
        submitButton.innerHTML = '<input id="next" type="button" name="nextbutton" value="Next Question" onclick="updateNext();"><input id="back" type="button" name="backbutton" value="Previous Question" onclick="updatePrevious();">';
    }
    if(pos == len-1) {
        submitButton.innerHTML = '<input id="submit" type="button" name="submitbutton" value="Submit Quiz" onclick="updateNext();"><input id="back" type="button" name="backbutton" value="Previous Question" onclick="updatePrevious();">';
    }
    if(pos == len) {
        while(firstDiv.hasChildNodes()) {
            firstDiv.removeChild(firstDiv.lastChild);
        }
        submitButton.innerHTML = "Your total score: " + this.totalScore; 
    }
}

最后,您需要确保previous和next按钮处理程序调用新的updateNavigationButtons()函数:

//update when user clicks next question
function updateNext() {
    displayAlert();  
    collectUserAnswer();
    calcScore();
    pos++;
    updateNavigationButtons();
};

//update when user clicks previous question
function updatePrevious() {
    displayAlert();  
    collectUserAnswer();
    calcScore();
    pos--;
    updateNavigationButtons();
}

updateNext()updatePrevious()看起来几乎相同,除了它们对pos变量所做的事情;因此,您可能希望找到一种方法来消除代码重复。在开始之前,我注意到向后导航仍然存在一个错误-如果没有选择答案,则会发生错误。
但希望这能让你更接近我的修改。可以在here中找到我的修改。

xhv8bpkk

xhv8bpkk2#

让我们创建一个对象,它被设计为

var tempStorage = {};

设其键为allQuestions的索引(即**pos**),值为相应单选按钮的值。
在下面的方法中,插入以pos为键的值

function calcScore() {
    var userAns = document.querySelector('input[name="choice"]:checked').value; 
    var correctAns = allQuestions[pos].correctAnswer;
    tempStorage[pos]  = userAns;   // LIKE THIS
    if(userAns == correctAns) {
        this.totalScore++;
    }
}

然后在上一个按钮中单击,将值设置回(在**updatePrevious()**中)

// Iterate through each radio element and based on value
// change the checked attribute

var radioButtons = document.getElementsByName("choice");
for (var x = 0; x < radioButtons.length; x++) {
    if (radioButtons[x].value === tempStorage[pos]) {
        radioButtons[x].checked = true;
    }
}

签入此JSFIddle1
如果你对jQuery感兴趣

// LIKE THIS, here I used jQuery 
$('input[name="choice"][value="'+tempStorage[pos]+'"]"').attr('checked', true)

检查此JSFIddle2

相关问题