watch 与 computed 区别

案例:考试

后端 server

安装 express 和 nodemon

npm init -y

npm i express -S

npm i nodemon -g

更改 package.json

"dev": "nodemon ./src/index.js"

创建 data

src/data/question.json

[
  {
    "id": 1,
    "question": "1 + 1 = ?",
    "items": ["2", "5", "4", "3"],
    "answer": 0
  },
  {
    "id": 2,
    "question": "1 + 2 = ?",
    "items": ["5", "2", "4", "3"],
    "answer": 3
  },
  {
    "id": 3,
    "question": "1 + 3 = ?",
    "items": ["2", "4", "5", "3"],
    "answer": 2
  },
  {
    "id": 4,
    "question": "1 + 4 = ?",
    "items": ["3", "2", "5", "4"],
    "answer": 2
  }
]

编写 app

const express = require('express');
const bodyParser = require('body-parser');
const { readFileSync } = require('fs');
const { resolve } = require('path');
const app = express();

let myResult = [];

// 具备POST请求能力
app.use(bodyParser.urlencoded({ extended: false }));
// extended:false 方法内部使用querystring模块处理请求参数的格式
// extended:true 方法内部使用第三方模块qs处理请求参数的格式
app.use(bodyParser.json());

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,POST');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

app.post('/getQuestion', function(req, res) {
  const order = req.body.order;
  const questionData = JSON.parse(readFileSync(resolve(__dirname, 'data/question.json'), 'utf8'));
  const questionResult = questionData[order];
  if (questionResult) {
    const { id, question, items } = questionResult;
    res.send({
      errorCode: 0,
      msg: 'OK',
      data: {
        id,
        question,
        items
      }
    });
  } else {
    res.send({
      errorCode: 1,
      msg: 'NO_DATA',
      data: myResult
    });

    myResult = [];
  }
});

app.post('/uploadAnswer', function(req, res) {
  const { order, myAnswer } = req.body;
  const questionData = JSON.parse(readFileSync(resolve(__dirname, 'data/question.json'), 'utf-8'));
  const { id, question, items, answer } = questionData[order];
  myResult.push({
    qid: id,
    question,
    myAnswer: items[myAnswer], // myAnswer 是下标
    rightAnswer: items[answer],
    isRight: myAnswer == answer,
  });

  res.send({
    errorCode: 0,
    msg: 'OK'
  });
  // res.send(myResult);
});

app.listen(8888, function() {
  console.log('Welcome to use Express on 8888');
});

运行

npm run dev

前端

main.js

/**
 * [
  * {
  *   id: 1,
  *     question: 'xxxx',
  *     items: [2,3,4,5],
  *     answer: 2
  * }
 * ]
 * 
 * data: {
 *  order: 0,
 *  questionData: 试题数据,
 *  myAnswer: items index,
 *  myResults: [
 *    {
 *      qid,
 *      question,
 *      myAnswer: items[index],
 *      rightAnswer: items[index],
 *      isRight: myAnswer == answer
 *     }
 *  ]
 * }
 * 
 * 视图:什么时候显示试题(切换)?什么时候显示答案集
 * myResults.length
 * 
 * 试题
 * 
 * 编号
 * 题目
 * 4个选项(点击)-> selectAnswer -> 取到index -> 赋值给order
 * 切换order -> 上传该题的order myAnswer -> 获取新order对应的题
 * 如果切换到最后一道 -> 返回myResults
 */

// import qs from 'qs';

const App = {
  data() {
    return {
      order: 0,
      questionData: {},
      myAnswer: -1,
      myResults: []
    }
  },
  template: `
    <div>
      <div v-if="myResults.length > 0">
        <h1>考试结果</h1>
        <ul>
          <li v-for="(item, index) of myResults"
            :key="item.qid">
            <h2>编号:{{ item.qid }}</h2>
            <p>题目:{{ item.question }}</p>
            <p>你的答案:{{ item.myAnswer }}</p>
            <p>正确答案:{{ item.rightAnswer }}</p>
            <p>正确:{{ isRightText(item.isRight) }}</p>
          </li>
        </ul>
      </div>
      <div v-else>
        <h1>编号{{ questionData.id }}</h1>
        <p>{{ questionData.question }}</p>
        <div>
          <button
            v-for="(item, index) of questionData.items"
            :key="item"
            @click="selectAnswer(index)"
          >{{ item }}</button>
        </div>
      </div>
    </div>
  `,
  mounted() {
    this.getQuestion(this.order);
  },
  computed: {
    isRightText() {
      return function(isRight) {
        return isRight ? '是' : '否';
      }
    }
  },
  watch: {
    order(newOrder, oldOrder) {
      this.uploadAnswer(oldOrder, this.myAnswer);
      this.getQuestion(newOrder);
    }
  },
  methods: {
    getQuestion(order) {
      axios.post(
        '<http://localhost:8888/getQuestion>',
        { order },
      ).then(res => {
        if (res.errorCode) {
          this.myResults = res.data;
          console.log(this.myResults);
          return;
        }

        this.questionData = res.data;
      });
    },
    uploadAnswer(order, myAnswer) {
      axios.post('<http://localhost:8888/uploadAnswer>', {
        order,
        myAnswer
      }).then(res => {
        console.log(res);
      });
    },
    selectAnswer(index) {
      this.myAnswer = index;
      this.order += 1;
    },
  }
};

const vm = Vue.createApp(App).mount('#app');

watch 实现