Vue2实现试题组件封装,锚点点击题目序号跳到对应试题处,粘贴可用

- Vue2实现试题组件封装,锚点点击题目序号跳到对应试题处,

-  锚点实现点击题目序号跳到对应试题处

-父组件

<!-- 父组件 -->
<template>
  <div ref="toTopRef" class="box">
    <!-- 题目序号部分 -->
    <div class="anchorsWrap">
      <h3>题目序号</h3>
      <div>
        <h3 
          v-for="item in subjectList" 
          :class="`${item.classStyle}` === '2' ? 'red' : ''"
          @click="anchorJump(`${item.type}`)"
        >
          {{ item.type }}
        </h3>
      </div>
    </div>
    <!-- 试题部分 -->
    <div class="contentWrap">
      <h3>试题</h3>
      <div v-for="(item, index) in anserObj" :key="index">
        <testRes ref="t" :id="item.key" :anserObj="item" @sendVal="sendVal"></testRes>
      </div>
    </div>
  </div>
</template>

<script>
import testRes from './child/testRes.vue'
export default {
  name: 'myhtmlName',
  components: { testRes },
  data() {
    return {
      subjectList: [
        {
          type: "1",
          classStyle: '1',
        },
        {
          type: "2",
          classStyle: '1',
        },
        {
          type: "3",
          classStyle: '1',
        }, {
          type: "4",
          classStyle: '1',
        },
        {
          type: "5",
          classStyle: '1',
        },
        {
          type: "6",
          classStyle: '1',
        }
      ],
      anserObj: [
        {
          key: 'as1',
          subjectNum: '题目1: 你是什么蛋?',
          getVal: false,
          anserList: [
            { num: 'A', cont: '我是大笨蛋' },
            { num: 'B', cont: '我是大坏蛋' },
            { num: 'C', cont: '我是大傻蛋' },
            { num: 'D', cont: '我是大笨瓜' },
          ],
        },
        {
          key: 'as2',
          subjectNum: '题目2: 你是什么蛋?',
          getVal: false,
          anserList: [
            { num: 'A', cont: '我是大笨蛋' },
            { num: 'B', cont: '我是大坏蛋' },
            { num: 'C', cont: '我是大傻蛋' },
            { num: 'D', cont: '我是大笨瓜' },
          ]
        },
        {
          key: 'as3',
          subjectNum: '题目3: 你是什么蛋?',
          getVal: false,
          anserList: [
            { num: 'A', cont: '我是大笨蛋' },
            { num: 'B', cont: '我是大坏蛋' },
            { num: 'C', cont: '我是大傻蛋' },
            { num: 'D', cont: '我是大笨瓜' },
          ]
        },
        {
          key: 'as4',
          subjectNum: '题目4: 你是什么蛋?',
          getVal: false,
          anserList: [
            { num: 'A', cont: '我是大笨蛋' },
            { num: 'B', cont: '我是大坏蛋' },
            { num: 'C', cont: '我是大傻蛋' },
            { num: 'D', cont: '我是大笨瓜' },
          ],
        },
        {
          key: 'as5',
          subjectNum: '题目5: 你是什么蛋?',
          getVal: false,
          anserList: [
            { num: 'A', cont: '我是大笨蛋' },
            { num: 'B', cont: '我是大坏蛋' },
            { num: 'C', cont: '我是大傻蛋' },
            { num: 'D', cont: '我是大笨瓜' },
          ]
        },
        {
          key: 'as6',
          subjectNum: '题目6: 你是什么蛋?',
          getVal: false,
          anserList: [
            { num: 'A', cont: '我是大笨蛋' },
            { num: 'B', cont: '我是大坏蛋' },
            { num: 'C', cont: '我是大傻蛋' },
            { num: 'D', cont: '我是大笨瓜' },
          ]
        },
      ],
    };
  },
  methods: {
    // 接收子组件传回来的方法
    sendVal(val) {
      this.subjectList.map((item, index) => {
        // 绑定ref获取当前ref有值时,题目序号为已答题状态,反之为未答题状态
        if (this.$refs.t[index].value) {
          this.subjectList[index].classStyle = '2'
        } else {
          this.subjectList[index].classStyle = '1'
        }
      })
    },
    // 根据每道题的id,点击题目序号跳到对应题目位置
    anchorJump(which) {
      let num = "#as" + which; // 给id加上井号
      // 给对应dom滚动到对应锚点,使之出现在视图中
      document.querySelector(num).scrollIntoView({
        behavior: "smooth", // 定义过渡动画 instant立刻跳过去 smooth平滑过渡过去
        block: "start", // 定义垂直滚动方向的对齐 start顶部(尽可能)  center中间(尽可能)  end(底部)
        inline: "center", // 定义水平滚动方向的对齐
      });
    },
  },
};
</script>

<style lang="less" scoped>
.box{
  width: 100%;
  height: 100%;
  padding: 24px;
  box-sizing: border-box;
  overflow-y: auto;
  .contentWrap{
    width: 80%;
  }
  .anchorsWrap {
    right: 480px;
    position: fixed;
      width: 100px;
    text-align: center;
    .toTop{
      width: 100px;
      height: 100px;
      border: 1px solid gray;
      line-height: 100px;
    }
    div{
      width: 120px;
      display: flex;
      flex-wrap: wrap;
      text-align: center;
      h3{
        width: 20px;height: 20px;
        border: 1px solid gray;
        border-radius: 20px;
        line-height: 20px;
        margin: 5px;
      }
    }
  }
}
.red {
  color: red
}

</style>

 - 试题组件封装

正则表达式实现输入框只允许输入A-D的大写字母

-父组件

<!-- 子组件 -->
<template>
  <div>
    <div class="title">
      {{ anserObj.subjectNum }}
      <!-- 输入框只能输入A-D的大写字母 -->
      <el-input
        style="width: 60px;"
        size="small"
        @change="sendVal"
        v-model="value"
        maxlength="1"
        oninput="value=value.replace(/[^A-D]/g,'');"
      ></el-input>
    </div>
    <ul>
      <li 
        class="liStyle" 
        v-for="ite in anserObj.anserList" 
        :key="ite.num"
        @click="selectFn(ite)"
      >
        {{ `${ite.num}.${ite.cont} ` }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "testRes",
  props: {
    subjectNum: {
      type: String,
      default: '22'
    },
    anserObj: {
      type: Object,
      default: () => {
        return {
          key: '',
          subjectNum: '',
          getVal: false,
          anserList: [
            { num: 'A', cont: '我是大笨蛋' },
          ]
        }
      }
    }
  },
  data() {
    return {
      // 输入框显示值
      value: '',
    };
  },
  methods: {
    // 点击选项触发
    selectFn(val) {
      this.value = val.num
      this.$emit('sendVal', val.num)
    },
    // 输入框输入答案触发
    sendVal(val) {
      this.$emit('sendVal', val)
    }
  },
};
</script>
<style>
.title {
  margin: 10px 0;
}
.liStyle{
  width: 120px;
  border: 1px solid #eee; 
  margin-top: 5px;
}
</style>

记笔记,理思路。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值