Element Tag 标签

2,540 阅读1分钟

前言

这篇文章主要是记录一下,我在用tag标签的时候遇到的一些问题,因为是后端管理系统中的标签管理页面,所以只有基本的增删改查功能。。。,好了,废话不多说了,直接开始

Tag标签

因为需要进行标签的更改,所以直接使用Tag标签里面的动态编辑标签,直接把代码拿过来用

<el-tag
  :key="tag"
  v-for="tag in dynamicTags"
  closable
  :disable-transitions="false"
  @close="handleClose(tag)">
  {{tag}}
</el-tag>
<el-input
  class="input-new-tag"
  v-if="inputVisible"
  v-model="inputValue"
  ref="saveTagInput"
  size="small"
  @keyup.enter.native="handleInputConfirm"
  @blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ New Tag</el-button>

<style>
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>

<script>
export default {
  data() {
    return {
      dynamicTags: ["标签一", "标签二", "标签三"],
      inputVisible: false,
      inputValue: "",
    };
  },
  methods: {
    handleClose(tag) {
      this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
    },

    showInput() {
      this.inputVisible = true;
      this.$nextTick((_) => {
        this.$refs.saveTagInput.$refs.input.focus();
      });
    },

    handleInputConfirm() {
      let inputValue = this.inputValue;
      if (inputValue) {
        this.dynamicTags.push(inputValue);
      }
      this.inputVisible = false;
      this.inputValue = "";
    },
  },
};
</script>

这样就直接拥有了一个基本Tag标签页面

image.png

调取数据获取接口

调取自己封装好的数据接口,拿取后端返回的数据。。。。,在我看到到后端返回我的数据格式,我就知道这个页面之后的增删改查功能将会不是太好实现。。。,数据长成这样。。。。

image.png

看到数据的不断嵌套,我就感觉自己头已经有点大了。。。,啥也不说了,直接调取接口拿到数据:

  
    //获取数据
    getdata() {
      getwarninglabel({
        pageNum: this.pageNum,
        pageSize: this.pageSize,
      }).then((res) => {
        console.log(res);
        this.total = res.data.count; //分页
        this.tagtitle = res.data.results; //总数据
      });
    },

进行数据获取,而要获取标签的数据keywords,需要进行两层的嵌套循环,第一层遍历,通过item.keywords拿到每一个keywords的数据,之后再遍历item.keywords,来循环keywords里面的数据,代码如下:

<div v-for="(item, ki) in tagtitle" :key="ki" class="text item">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <span> {{ item.label_name }}</span> //标签标题
         
        </div>
        <div>
          <el-tag
            :key="indext"
            //遍历循环item.keywords,拿到标签数据
            v-for="(tag, indext) in item.keywords" 
            :disable-transitions="false"
            closable 
            @close="handleClose(tag)"
          >
            {{ tag }}
          </el-tag>

image.png

此时已经完成了页面数据的基本渲染,之后开始添加其他的功能

按钮添加

按照需求,需要在点击编辑按钮时,tag标签后面才会出现删除图标,同时编辑按钮变成保存提交按钮,因而需要对删除图标是否出现以及编辑/保存按钮的切换进行处理

  1. 添加编辑/保存以及模块删除按钮
<el-button
            @click="hangdelDelete(item.id)"
            style="float: right; padding: 3px 0; color: red"
            type="text"
            >删除</el-button
          >
          <el-button
            v-show="activeIndex != ki"
            @click="handelUpdata(item.id, ki)"
            style="float: right; padding: 3px 0"
            type="text"
            >编辑</el-button
          >
          <el-button
            v-show="activeIndex === ki"
            @click="handelUpdatat(item.id, ki)"
            style="float: right; padding: 3px 0"
            type="text"
            >保存</el-button
          >

image.png

2.控制tag标签的删除按钮是否出现 我是直接删除了tag标签自带的删除图标,也就是closable,之后自己在后面添加了一个icon图标,通过v-show来判断是否显示

<el-tag
            :key="indext"
            v-for="(tag, indext) in item.keywords"
            :disable-transitions="false"
          >
            {{ tag }}
            <i
              v-show="activeIndex === ki"
              class="el-icon-circle-close"
              @click="handleClose(tag,indext)"
            ></i>
          </el-tag>

结果如下:

image.png

遇到问题

此时已经写好了编辑/保存,删除按钮以及tag标签的删除图标,而且对它们是否显示也进行了判断,但是此时就遇到了第一个问题,也就是在点击编辑按钮时,所有的tag标签后面都出现了icon图标,同时所有的编辑按钮也变成了保存,问题展示如下:

image.png

image.png

此时,需要处理的是,如何实现点击哪一个标签模块,哪一个便签模块进行改变,而不是全部发生改变,解决办法如下:

一、定义一个字段,并给它一个初始化的值,如-1,因为index排序从0开始,所以不能赋值为0
 activeIndex: -1,
 二、将v-show是否显示的true/false判断,改成通过点击时将获取的index值赋值给activeIndex之后和index的值来进行判断,相等即为true,进行展示,不相等极为false,不进行展示

代码如下:

<div v-for="(item, ki) in tagtitle" :key="ki" class="text item"> 
<el-button
            @click="handelUpdata(item.id, ki)" //拿取渲染排序的值
            style="float: right; padding: 3px 0"
            type="text"
            >编辑</el-button
          >
      //方法
        handelUpdata(id, ki) { //ki index排序
         console.log(id);
         console.log(ki); 
         this.activeIndex = ki; //将排序值赋值给activeIndex
      }
      //使用
       <i
              v-show="activeIndex === ki" //即可进行是否显示判断
              class="el-icon-circle-close"
              @click="handleClose(tag,indext)"
            ></i>

实现功能如下:

image.png

删除功能

模块的删除功能比较简单,直接通过后端给的模块id,通过id传递给后端即可,这里主要解决的是,tag标签的删除,这些标签没有id存在,打开 Tag标签,查看一下删除功能的实现:

image.png 直接使用这个方法,但是会突然发现,后端返回的数据格式和需要的数据格式不同:

Element UI数据格式:

image.png

后端返回的数据格式:

image.png

也就是说如果使用Element UI自带的方法,那么就需要使用和它一样的数据格式,也就是相当于results[0].keywords里面的数据,如下:

image.png

通过这种比较,很容易想到通过模块的index值,在点击时,将index的值放到results[].keywords中,即可拿到每一个keywords中的数据,之后放到新定义的数组中,即可使用tag标签自带的方法:

this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1); 实现代码如下:

一、定义一个新数组

 deleIndex: [],

二、定义一个新的字段来获取模块的index值

  numberid: "",

三、拿取index值并赋值给 numberid

//编辑
handelUpdata(id, ki) { //ki index排序
    this.activeIndex = ki;
    this.numberid = ki; //获取index值
    }

四、将numberid放入到results[].keywords,即可拿取到keywords中的数据,并放到deleIndex

//获取数据
 getdata() {
   getwarninglabel({
     pageNum: this.pageNum,
     pageSize: this.pageSize,
   }).then((res) => {
     console.log(res);
     this.total = res.data.count;
     this.tagtitle = res.data.results;
      console.log(res.data.results[0].keywords);
      console.log(res.data.results[this.numberid].keywords);
      console.log(res.data.results[this.numberid].label_name);
      this.deleIndex = res.data.results[this.numberid].keywords; //赋值
      this.deletitle = res.data.results[this.numberid].label_name;
   
   });
 },

五、使用tag标签自带的删除方法

//删除方法
    handleClose(tag, indext) {
        console.log(indext)
         this.deleIndex.splice(this.deleIndex.indexOf(tag), 1);
    },

标签删除功能实现:

image.png

新增功能

新增功能实现也比较简单,唯一的麻烦就是如何将输入的字符串格式的数据转化成数组,同时将新增的标签数据与其他没有改变的数据进行合并,也就是将两个数组进行合并:、

1、新增数据格式:

image.png

name的值取出来,放到一个数组中,即可生成后端需要的数据格式,代码如下:

//新建数组,获取新增的数据
mileEdit:[]
//进行数据处理
 this.mileEdit = this.ruleForm.options;
      console.log(this.mileEdit);
      //定义一个新数组来存放处理后的数据
      const eddvalue = this.mileEdit.map((value) => { 
        return value.name;
      });

2、处理后结果如下:

image.png

3、将新增的数据与没有改变的数据一起给后端传递过去,即新增数组与原来的数组进行合并,通过concat来实现数组的合并,代码如下:

 titleEdit(id,{
        label_name: this.deletitle,
        keywords: eddvalue.concat(this.deleIndex) ,//数组合并
      }).then((res) => {
        console.log(res);
        this.$message({
          message: "新增成功!",
          type: "success",
        });

即完成了标签的增加功能

完整代码:

<template>
  <div>
    <el-button type="primary" @click="Addmunu()">新增主类</el-button>
    <div v-for="(item, ki) in tagtitle" :key="ki" class="text item">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <span> {{ item.label_name }}</span>
          <el-button
            @click="hangdelDelete(item.id)"
            style="float: right; padding: 3px 0; color: red"
            type="text"
            >删除</el-button
          >
          <el-button
            v-show="activeIndex != ki"
            @click="handelUpdata(item.id, ki)"
            style="float: right; padding: 3px 0"
            type="text"
            >编辑</el-button
          >
          <el-button
            v-show="activeIndex === ki"
            @click="handelUpdatat(item.id, ki)"
            style="float: right; padding: 3px 0"
            type="text"
            >保存</el-button
          >
        </div>
        <div>
          <el-tag
            :key="indext"
            v-for="(tag, indext) in item.keywords"
            :disable-transitions="false"
          >
            {{ tag }}
            <i
              v-show="activeIndex === ki"
              class="el-icon-circle-close"
              @click="handleClose(tag,indext)"
            ></i>
          </el-tag>
          <span v-show="activeIndex === ki">
            <el-form :inline="true" :model="ruleForm" ref="ruleForm">
              <el-form-item
                v-for="(item, index) in ruleForm.options"
                :key="index"
              >
                <el-row>
                  <el-col :span="4">
                    <el-input
                      clearable
                      style="width: 200px"
                      v-model="item.name"
                      placeholder="请输入标签名"
                    ></el-input>
                  </el-col>
                  <!-- <el-col :span="8">
                <el-button type="danger" plain @click="deleteOption(index)"
                  >删除选项</el-button
                >
              </el-col> -->
                </el-row>
              </el-form-item>
              <el-button  type="primary" plain @click="addOption(index)"
                >新增标签</el-button
              >
            </el-form>
          </span>
        </div>
      </el-card>
    </div>
    <!-- 分页 -->
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="pageNum"
      :limit.sync="pageSize"
      @pagination="getdata"
    />
    <!-- 新增主类弹窗 -->
    <el-dialog title="添加标签" :visible.sync="dialogruleForm4Visible">
      <el-form
        :model="ruleForm4"
        ref="ruleForm4"
        label-width="100px"
        class="demo-ruleForm"
      >
        <el-form-item label="标签主类" prop="title">
          <el-input v-model="ruleForm4.title"></el-input>
        </el-form-item>
        <template>
          <el-form-item
            :label="'标签' + (index + 1)"
            v-for="(item, index) in ruleForm4.options"
            :key="index"
          >
            <el-row>
              <el-col :span="16">
                <el-input
                  v-model="item.name"
                  placeholder="请输入标签名"
                  style="width: 90%"
                ></el-input>
              </el-col>
              <el-col :span="8"> </el-col>
            </el-row>
          </el-form-item>
          <el-button
            type="primary"
            style="float: left"
            plain
            @click="addppOption"
            >新增标签</el-button
          >
        </template>
        <el-form-item> </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogruleForm4Visible = false">取 消</el-button>
        <el-button type="primary" @click="checkAddppQuestion()"
          >确 定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  getwarninglabel,
  hangdleadd,
  deletedata,titleEdit
} from "@/api/label/riskwarning";
export default {
  data() {
    return {
      // 分页
      total: "",
      pageNum: 1,
      pageSize: 10,
      //题目排序
      numberid: "",
      deleteadd:"",
      isShow:false,
      deleIndex: [],
      deletitle: "",
      activeIndex: -1,
      tagtitle: [], //标签题目
      milepost: [],//新增数据处理
      mileEdit: [],//修改数据处理
      tagclosable: false,
      dynamicTags: ["标签一", "标签二", "标签三"],
      inputVisible: false,
      inputValue: "",
      //添加标签
      ruleForm: {
        options: [
          {
            name: "", //标签
          },
        ],
      },
      //添加主类
      ruleForm4: {
        title: "", //主类
        options: [
          {
            name: "", //标签
          },
        ],
      },
      dialogruleForm4Visible: false,
    };
  },
  methods: {
    //添加添加标签
    addOption(index) {
      this.ruleForm.options.push({
        name: "",
      });
     this.deleteadd = index
      console.log(888777)
    },
    getdelete(){
        console.log(99999)
         this.ruleForm.options.splice(this.deleteadd, 1);
    },
     
    //添加添加标签
    addppOption() {
      this.ruleForm4.options.push({
        name: "",
      });
    },
    //新增主类
    Addmunu() {
      this.dialogruleForm4Visible = true;
    },
    //新增
    checkAddppQuestion() {
      console.log(this.ruleForm4.options);
      this.milepost = this.ruleForm4.options;
      console.log(this.milepost);
      const checker = this.milepost.map((value) => {
        return value.name;
      });
      console.log(checker);
      hangdleadd({
        label_name: this.ruleForm4.title,
        keywords: checker,
      }).then((res) => {
        console.log(res);
        this.$message({
          message: "新增成功!",
          type: "success",
        });
        this.ruleForm4 = {
          id: 0,
          title: "",
          options: [""],
        };
        this.getdata();
      });
      this.dialogruleForm4Visible = false;
    },
    //标签新增
    
    //获取数据
    getdata() {
      getwarninglabel({
        pageNum: this.pageNum,
        pageSize: this.pageSize,
      }).then((res) => {
        console.log(res);
        this.total = res.data.count;
        this.tagtitle = res.data.results;
         console.log(res.data.results[0].keywords);
          console.log(this.numberid);
         console.log(res.data.results[this.numberid].keywords);
         console.log(res.data.results[this.numberid].label_name);
         this.deleIndex = res.data.results[this.numberid].keywords;
         this.deletitle = res.data.results[this.numberid].label_name;
         console.log(this.deleIndex)
      });
    },
    //编辑
    handelUpdata(id, ki) {
      //ki index排序
      console.log(id);
      console.log(ki);
      this.activeIndex = ki;
      this.numberid = ki;
     
      this.ruleForm = {
          id: 0,
          options: [""],
        };
         this.getdata();
        //  this.addOption();
        this.getdelete();
    },
    //保存
    handelUpdatat(id, ki) {
      console.log(id);
      console.log(ki);
      this.activeIndex = -1;
       console.log(this.ruleForm.options);
      this.mileEdit = this.ruleForm.options;
      console.log(this.mileEdit);
      const eddvalue = this.mileEdit.map((value) => {
        return value.name;
      });
      console.log(eddvalue)
       titleEdit(id,{
        label_name: this.deletitle,
        keywords: eddvalue.concat(this.deleIndex) ,
      }).then((res) => {
        console.log(res);
        this.$message({
          message: "新增成功!",
          type: "success",
        });
        this.ruleForm = {
          options: [""],
        };
        this.getdata();
      });
     this.getdata();
     
    },
    //删除主模块
    hangdelDelete(id) {
      this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        center: true,
      })
        .then(() => {
          deletedata(id).then((res) => {
            console.log(res);
            this.$message({
              type: "success",
              message: "删除成功!",
            });
            this.getdata();
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },

    //删除方法
    handleClose(tag, indext) {
        console.log(indext)
        // this.deleIndex.splice(indext, 1);
         this.deleIndex.splice(this.deleIndex.indexOf(tag), 1);
    },
  },
  mounted() {     
    console.log(88888);
    this.getdata();
  },
};
</script>

<style  scoped>
/* 卡片 */
.item {
  margin-bottom: 18px;
}

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}
.clearfix:after {
  clear: both;
}

.box-card {
  width: 100%;
}
/* 标签 */
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>