WEB前端之项目实战(一)vue - 多选功能

问题 : 最初做多选功能时发现,当多选的题数超过一个时,选择一个选项那么所有题的该选项都会被选中,这是因为用v-for遍历的时候都绑定了同一个事件。
解决 : 给每一题设置不同的名字,那么他们的选项就不会发生联动了。

js 参考博文链接地址:https://blog.csdn.net/shaonaozu/article/details/12704951

软件:vscode

技术:vue + Elementui + 事件绑定

需求:多组选择,每组之间互不影响。每组均可多选,第一次单击选中且改变颜色,第二次单击不选中且颜色默认

主内容如下:

一、在 src/utils/创建 xxx.js 文件

  1. 要使用哪个函数,就一定要export;
  2. 本例中export add 和 remove。
const separator = ","//字符串分隔符  
const baforeInsert = false//字符串追加方式,默认false是在后面添加,true在追加到前面  
const isRepeat = false//追加的字符串是否可重复添加  
const isDeleteAll = true//删除所有匹配的字符串

//左边添加分隔符
function lInsertSeparator(operateString) {
  if(operateString.indexOf(separator)  == 0){
    return operateString;
  }
  return separator + operateString;  
}

//右边添加分隔符 
function rInsertSeparator (operateString) {
  if(operateString.lastIndexOf(separator)  == (operateString.length - separator.length))  
    return operateString;  
  return operateString + separator;   
}

//去除左边分隔符 
function lSeparatorTrim (operateString) {
  if(operateString.indexOf(separator)  == 0)  
    return operateString.substring(1);  
  return operateString;  
}

//去除右边的分隔符 
function rSeparatorTrim (operateString) {
  if(operateString.lastIndexOf(separator)  == (operateString.length - separator.length))  
    return operateString.substring(0,operateString.length-1);  
  return operateString;  
}

// 追加字符串,将str字符串 追加到operateString中
export function add(operateString, str) {
  if( str  && str != ""){
    if(isRepeat){//重复追加
      if(baforeInsert){//追加在开头
         return rSeparatorTrim(lSeparatorTrim(str + separator + operateString));
      }
      return rSeparatorTrim(lSeparatorTrim(operateString + separator + str));
    }else{
      //开头和结尾都添加分隔符
      operateString =	lInsertSeparator(rInsertSeparator(operateString));
      if(operateString.indexOf(separator + str + separator) == -1){
        if(baforeInsert){
          return rSeparatorTrim(lSeparatorTrim(str + operateString));
        }else{
          return rSeparatorTrim(lSeparatorTrim(operateString + str));
        }
      }
      return rSeparatorTrim(lSeparatorTrim(operateString));
    }
  }
}

// 删除指定字符串
export function remove(operateString, str) {
  if(operateString && str && operateString != "" && str != ""){
    //开头和结尾都添加分隔符
    operateString =	lInsertSeparator(rInsertSeparator(operateString));
    if(isDeleteAll){
      operateString = operateString.replace(new RegExp(separator,"g"),separator + separator);
      //删除所有匹配的字符串
      operateString =	 operateString.replace(new RegExp(separator + str +separator,"g"),separator);
      operateString = operateString.replace(new RegExp(separator+"{2,}","g"),separator);
    }else{
      operateString =	 operateString.replace(new RegExp(separator + str + separator),separator);
    }
    return rSeparatorTrim(lSeparatorTrim(operateString));
  }
}

二、在 src/views/xxx/创建.vue文件

  1. 将上述创建的.js文件引入 (script标签中引);
  2. 注意一定要import 且 如果想在其余地方多次使用该.js文件,可以在当前.vue文件引入时起一个别名;
  3. 本例中 add as addOption。
  4. 先布局 | 再遍历样式 | 然后给每一题设置不同的 id | 再分别设置每一题每一个选项 | 同时绑定事件
<template>
   <div class="total">
    <el-row :span="10">
       <!-- 题型 -->
      <div class="multititle">多选题</div>
      <el-row
        class="multitlcard"
        v-for="(multi, index) in MultiQuestionList"
        :key="index"
      >
        <!-- 题目 -->
        <el-row class="question">
          <span :id="multi.id">{{ index + 1 }}</span>
          <span class="questiontitle">.{{ multi.title }}</span>
        </el-row>
        <!-- 选项 -->
        <el-row class="items">
          <div class="item" :id="`${multi.id},a`" @click="setMultilAnswer">
            <span
              :class="multi.answer.indexOf('a') != -1 ? 'active' : 'noactive'"
              >A</span
            >
            <span>{{ multi.item_a }}</span>
          </div>
          <div class="item" :id="`${multi.id},b`" @click="setMultilAnswer">
            <span
              :class="multi.answer.indexOf('b') != -1 ? 'active' : 'noactive'"
              >B</span
            >
            <span>{{ multi.item_b }}</span>
          </div>
          <div class="item" :id="`${multi.id},c`" @click="setMultilAnswer">
            <span
              :class="multi.answer.indexOf('c') != -1 ? 'active' : 'noactive'"
              >C</span
            >
            <span>{{ multi.item_c }}</span>
          </div>
          <div class="item" :id="`${multi.id},d`" @click="setMultilAnswer">
            <span
              :class="multi.answer.indexOf('d') != -1 ? 'active' : 'noactive'"
              >D</span
            >
            <span>{{ multi.item_d }}</span>
          </div>
        </el-row>
      </el-row>
    </el-row>
  </div>
</template>
<script>
 import {add as addOption,remove as removeOption} from "@/刚创建的.js的路径" 
 export default {
  data() {
    return {
      MultiQuestionList: [
        {
          id: 111,
          title: "这是第一道多选题",
          type: "multi",
          item_a: "1-选项一",
          item_b: "1-选项二",
          item_c: "1-选项三",
          item_d: "1-选项四",
          answer: "",
        },
        {
          id: 112,
          title: "这是第二道多选题",
          type: "multi",
          item_a: "2-选项一",
          item_b: "2-选项二",
          item_c: "2-选项三",
          item_d: "2-选项四",
          answer: "",
        },
      ],
    };
  },

  methods: {
    setMultilAnswer(e) {
      // 获取当前触发事件
      var element = e.currentTarget;
      // 用,切割.上述遍历的时候时question,item
      var arr = element.id.split(",");
      var multiId = arr[0];
      var item = arr[1];
      for (var i = 0; i < this.MultiQuestionList.length; i++) {
        if (this.MultiQuestionList[i].id == multiId) {
          if (this.MultiQuestionList[i].answer.indexOf(item) != -1) {
            this.MultiQuestionList[i].answer = removeOption(
              this.MultiQuestionList[i].answer,
              item
            );
          } else {
            this.MultiQuestionList[i].answer = addOption(
              this.MultiQuestionList[i].answer,
              item
            );
          }
          return;
        }
      }
      return;
    },
  },
};
</script>

<style scoped>
.total {
  margin: 10px;
}
.multititle {
  width: 100%;
  height: 30px;
  line-height: 30px;
  background-color: beige;
}
.multitlcard {
  margin-top: 10px;
}
.question {
  font-size: 16px;
}
.item {
  margin: 10px;
}
.item > span {
  display: inline-block;
}
.noactive {
  border: 1px solid #004f00;
  width: 22px;
  height: 22px;
  line-height: 22px;
  text-align: center;
  cursor: pointer;
}
.active {
  border: 1px solid #004f00;
  width: 22px;
  height: 22px;
  line-height: 22px;
  text-align: center;
  color: #fff;
  background-color: darkorange;
  cursor: pointer;
}
</style>

三、运行结果

  1. 多选且变色
    WEB前端之项目实战(一)vue - 多选功能

  2. 取消则默认
    WEB前端之项目实战(一)vue - 多选功能

上一篇:那个“炫酷狂拽”的数据可视化利器AntV 11.22版全新发布啦


下一篇:Makefile:26: *** missing separator. Stop.解决办法