vue - 使用vue实现自定义多选与单选的答题功能

本文介绍了如何在Vue项目中,面对特定UI设计,使用v-model实现自定义的多选和单选答题功能。文章详细讨论了实现过程中的难点,包括单选的选中状态管理、多选的样式与记录、提交逻辑等,并通过v-on:click、v-bind:class和ref等特性逐一解决。作者强调了Vue中ref特性的关键作用,以及在处理表单提交时防止多次提交的策略。
摘要由CSDN通过智能技术生成

4月底立得flag,五月底插上小旗,结果拖到六月底七月初才来执行。说什么工作忙都是借口,就是睡的比猪早,起的比猪晚。

本来实现多选单选这个功能,vue组件中在表单方面提供了一个v-model指令,非常的善解“猿”意,

能把我们的多选单选功能很完美且很强大得双向绑定起来,实现多选、单选、任意选...根本不在话下。

但是,凡事都有一个但是!

但是奈何这个项目设计稿的缘故,使用原生的表单组件是不可能使用了,请看ui图:  

可悲的是,这个项目两个月后,我才来做项目复盘,

话说也就在此时,我才发现有一种更简单的方式来实现并且应用上v-model,

为什么要为了样式放弃功能然后自己吭哧吭哧傻滴呼呼的用js来实现了类似双向绑定的感觉!!!

flag:今天先专注把我费劲巴拉手动搬得砖总结一下,明天(07-05)我再把所谓的最简单的方法做出来贴这里~

这个需求的难点在于以下几点:

1.单选点击后选中状态,需满足如下:

  a) 每次点击只能选中其中一个

  b) 当选中时再次点击其他选项需要切换选择对应点击项

  c) 选中时点击自身无显示上的反应(同样的逻辑再做一遍也无妨,即再加一遍类名也看不出来)

2.多选样式展示,需满足如下:

  a) 同时可以选中多个

  b) 多选已选中状态再次点击取消选中

3.多选选中项的记录,需满足如下:

  a) 选择几个记录几个

  b) 选中再取消时需要将本条记录的数据通时消除(依据点击事件,事件点击触发判断哪个被选中了)

4.单选选中项的记录,方便提交数据

5.未点击选项不可提交,并给提示

6.可提交状态,需满足如下:

  a) 单选选中任意一个,即可提交。再次修改对提交没有影响

  b) 多选至少选中一个可提交,再次修改需判断是不是没选东西

7.第十四题点下一题切换提交按钮

8.快速点击下一题,多次提交

9.点击下一题提交数据后,拿响应结果调取弹层提示用户选择是否正确

=============接下来一 一解决====================

 

首先先说结构

看似十道题,其实是一道题不停的换数据,所以我的外部结构就是一个form加一个空的div

别问我为什么多余一个空的,我也很无措。

form.question(v-if="state.ExamInfo")
 div

然后题目标题很傻瓜式得使用了h3

h3.qus-title(:data-id="state.ExamInfo.QuestionID") {
    {state.ExamInfo.ExamQuestionNo}} {
    {state.ExamInfo.Description}}

选项上,我使用ul>li的形式描述了多个选项

ul.qus-list
    li(v-for="(item,index) in state.ExamInfo.QuestionAnswerCode" @click="choosed(index)" v-bind:class="{'li-focus' : chooseNum==index}" ref="liId") {
    {item.Code}}、{
    {item.Description}}

 

大致几个属性

  • v-for是为了遍历题中的每一个选项,
  • click绑定了点击当前li时的事件,v-bind同步click绑定了动态的类名,用于展示选中状态。
  • 这里值得注意的一个点也是当时抓虾的一个点是,v-on:click和v-bind:class结合,
    • click的时候,每次把当前点击的li的index值传出去,
    • 然后定义一个变量chooseNum,点击函数中,将参数index赋给他
this.chooseNum = index;

靠这种间接拿到点击索引值的曲线救国方式,在v-bind的监视下,每次点击获得的索引chooseNum和这几个li中自己的index对上眼以后,就如正确的钥匙对上了合适的锁,类名绑定就成了。

也就是以上难题中的第一个难题的前半部分:单选点击后选中状态

  

 

费这么半天劲,才解决一个点啊!我不服!别急,接下来还有好戏。

但其实这个思路还是挺重要的,靠这一点“死皮赖脸”拉关系的劲头,这个法子以后还倒是可以有很多用武之地。

好戏在下一个属性,没错就是ref,这也是我步入万丈深渊一去不复返的梯子啊!

 

ref

  要知道人家可是vue里边的特殊特性,

  要知道人家可是很有能力的,

  要知道我老是连着打不出妖之道这三个字!

  好了不皮了。

官网记载:ref这个特殊特性,被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。

如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。

我的理解大白话来说,他就是给dom元素或者组件实例一个身份证号,身份证号有的特性他也就有,那就是唯一不重复。

如果配合上v-for,就能获取这一批带有ref特性所组成的数组。

通过数组下标索引出来的个体,也就是对应的dom元素本身或者组件实例本人无疑了。

就好像拿着身份证号去公安局查人一样,快速不说,还很高效有没有,一查一个准!

但需要说明的是,在created钩子中,这个特性拿不到东西,

生命周期钩子里只有在mounted里可以用(可能还有后边的钩子里也可以使用,我没用过不准确),

毕竟你想啊,身份证号虽说一出生就有了,但是只有挂载到网上你才能查得到的嘛!

所以,我究竟用它做了什么呢?那就是多选功能啊!

 

还是先回到上边说的,绑定了一个事件,并且会传递一个当前点击li的索引号,

并且前边也提到过,ref返回的是数组,有数组有索引号,简直是万事俱备啊。于是乎让我们来呼唤东风(东风别看了,就是说你呢)!

在choose点击函数中就有了这么一段:

if(this.$refs.liId[index].className.length <= 0){
    //首先先判断当前li有没有被选中,因为我这里li除了选中状态的有类名,其他没有类名,所以我就这么判断了。
    //这么看有时候舍弃一小丢丢规范的东西反而省力。

    this.$refs.liId[index].className = 'li-focus';// 添加类

}else{
    //当前li已经被选中,那么在多选的逻辑里,是允许人们选中后再取消选中的,所以前端展示层面上把样式去掉。

    this.$refs.liId[index].className = '';// 选中再取消的情况

}

好了,第二个多选样式搞定。

  

 

那么接下来,选择的结果呢,能不能来一次“趁火打劫”,趁点击的时候偷偷记录下用户的选择?答案当然是可以的啦!

首先说多选功能的趁火打劫吧,就着上边增删类名的热乎劲,紧接着在每次点击时我们记录下当前点击的是谁

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值