基于vant实现一个问卷调查

实现背景 

最近学习《vue实战》,第二篇进阶篇有一个练习

刚好最近在研究vue移动端框架vant

两者结合,实现这么个小项目

实现代码

新建 vue单文件 L0529L.vue

<template>
  <div class="dom">
    <div class="tmnr">{{showtm+1}}. {{timu[showtm]['tmcontent']}}</div>
    <component0529
      :info="ziInfo"
      :showtm="showtm"
      @chooseRadio="changeAnswer"
      @chooseCheckbox="changeAnswer"
      @chooseInput="changeAnswer"
    ></component0529>
    <div class="buttondom">
      <van-button type="primary" v-show="showtm>0" @click="shangtm" :disabled="showtm===0">上一题</van-button>
      <van-button
        type="primary"
        v-show="showtm<timu.length-1"
        @click="nexttm"
        :disabled="nextdisable"
      >下一题</van-button>
      <van-button type="warning" @click="chongzhi">重置</van-button>
    </div>
  </div>
</template>

<script>
import component0529 from "./views/component0529";

export default {
  name: "",
  data() {
    return {
      showtm: 0,
      timu: [
        {
          id: 1,
          type: "radio",
          tmcontent: "题目内容1-单选",
          xx: [
            { id: "A", nr: "选项A-单选" },
            { id: "B", nr: "选项B-单选" },
            { id: "C", nr: "选项C-单选" }
          ],
          cannext: false,
          answer: ""
        },
        {
          id: 2,
          type: "checkbox",
          tmcontent: "题目内容2-复选",
          xx: [
            { id: "A", nr: "选项A", ischeck: false },
            { id: "B", nr: "选项B", ischeck: false },
            { id: "C", nr: "选项C", ischeck: false },
            { id: "D", nr: "选项D", ischeck: false }
          ],
          cannext: false,
          answer: []
        },
        {
          id: 3,
          type: "input",
          tmcontent: "题目内容3-问答",
          cannext: false,
          answer: ""
        }
      ]
    };
  },
  computed: {
    ziInfo() {
      return this.timu[this.showtm];
    },
    nextdisable() {
      var a = false;
      if (this.showtm == this.timu.length - 1) a = true;
      var t = this.timu[this.showtm]["type"];
      switch (t) {
        case "radio":
          if (this.timu[this.showtm]["answer"] == "") a = true;
          break;
        case "checkbox":
          if (
            this.timu[this.showtm]["answer"].length != 2 &&
            this.timu[this.showtm]["answer"].length != 3
          )
            a = true;
          break;
        case "input":
          var c = this.timu[this.showtm]["answer"];
          if (c.length < 100) a = true;
          break;
      }
      return a;
    }
  },
  components: {
    component0529
  },
  methods: {
    nexttm() {
      this.showtm++;
    },
    shangtm() {
      this.showtm--;
    },
    chongzhi() {
      if (this.timu[this.showtm]["type"] == "checkbox") {
        this.timu[this.showtm]["answer"].length = 0;
        for (var i = 0; i < this.timu[this.showtm]["xx"].length; i++) {
          this.timu[this.showtm]["xx"][i]["ischeck"] = false;
        }
      } else {
        this.timu[this.showtm]["answer"] = "";
      }
    },
    changeAnswer(ans) {
      this.timu[this.showtm]["answer"] = ans;
    }
  }
};
</script>

<style scoped>
.dom{
  padding: 14px;
}
.tmnr{
  margin: 10px 0px;
  text-align: left;
}
.buttondom {
  position: absolute;
  bottom: 10px;
  text-align: center;
   100%;
}
</style>

  引入组件 component0529.vue 代码:

<template>
  <ul>
    <li v-if="info.type==='checkbox'">
      <van-checkbox
        v-for="infoa in childInfo.xx"
        v-model="infoa.ischeck"
        @change="changeCheckbox"
      >{{infoa.nr}}</van-checkbox>
    </li>
    <li v-else-if="info.type==='radio'">
      <van-radio-group v-model="childInfo.answer" @change="changeRadio">
        <van-radio v-for="infoa in childInfo.xx" :name="infoa.id">{{infoa.nr}}</van-radio>
      </van-radio-group>
    </li>
    <li v-else-if="info.type==='input'">
      <van-cell-group>
        <van-field
          v-model="childInfo.answer"
          type="textarea"
          placeholder="请输入不少于100字"
          rows='1'
          autosize
          border="true"
        />
      </van-cell-group>
    </li>
  </ul>
</template>

<script>
export default {
  props: ["info", "showtm"],
  data() {
    return {};
  },
  computed: {
    childInfo() {
      var an = this.info["answer"],
        type = this.info["type"];

      if (type == "checkbox") {
        for (var i = 0; i < this.info.xx.length; i++) {
          var x = this.info.xx[i];
          if (an.join(",").indexOf(x.id) > -1) x.ischeck = true;
        }
      }

      return this.info;
    }
  },
  methods: {
    changeRadio() {
      var a = this.childInfo.answer;
      this.$emit("chooseRadio", a);
    },
    changeCheckbox() {
      var a = [];
      for (var i = 0; i < this.childInfo.xx.length; i++) {
        if (this.childInfo.xx[i]["ischeck"]) a.push(this.childInfo.xx[i]["id"]);
      }

      this.$emit("chooseCheckbox", a);
    },
    changeInput() {
      this.$emit("chooseInput", this.childInfo.answer);
    }
  },
  components: {}
};
</script>

<style scoped>
ul li .van-radio,
.van-checkbox {
  margin: 16px 0px;
}
</style>

  

实现页面展示

 

 解释逻辑

 1.在L0529L.vue 定义好相关问卷题目,设计好题目类型,内容,选项,选择或者输入的答案等

2.定义一个当前题目id==showtm,用这个参数决定当前显示的是哪道题。

3、将题目传递给子组件component0529.vue,在这里面处理显示选项信息或者输入框

4、子组件信息操作选择完成或者输入了相关信息,修改对应父组件中问题的答案

5、刚接触vue,逻辑方面有些冗余啰嗦,以后有更好的实现想法再进行修改

原文地址:https://www.cnblogs.com/pangchunlei/p/10949416.html