vue封装组件(一)标签和下拉框组合实现添加数据

news2024/11/15 8:26:19

背景: 最近接入短剧内容,需要添加短剧合作方。在详情页需要支持添加组件 方案一:标签tag加上输入框实现添加数据。图片见下 这个是刚开始做的,后来产品觉得这样会造成随意修改数据,需要改成下拉框形式添加 方案二:标签tag加上下拉框以及添加按钮实现。 这个就避免了乱添加数据,添加合作方名字需要在一个管理页面添加,然后下拉框请求自然就请求到数据了

方案一效果图:第一行 流程:点击新增后,填入数据,后台会自动检查是否存在,存在返回数据,否则保存然后返回数据。 这样做有个问题,一不小心填错数据,后台也保存下来了 方案二效果图:第二行 流程:下拉框中是已经存在的数据,然后选择添加就行。合作方需要在另外的一个管理页面增删查改。

接下来是代码实现。 注意:这两个都是封装的组件,直接掉用即可,既然是封装的组件,那么就要支持已经存在的合作方数据填入。

方案一

<template>

 <div>
<!--   {{shortPlays}}-->
   <el-tag style="margin-right: 5px" v-for="(tag,index) in shortPlaysFilter"
           :key="index" closable
           @close="close(index,tag.shortPlayName)">
     {{tag.shortPlayName}}
   </el-tag>

   <el-input
       v-if="inputVisible"
       v-model="inputValue"
       ref="ref"
       class="input-new-tag"
       size="small"
       style="width: 100px"
       @keyup.enter.native="inputConfirm"
       @blur="inputConfirm"
   ></el-input>
   <el-button v-else size="small" style="margin-left: 5px;" @click="btnClick">新增合作方</el-button>
 </div>

</template>

<script>
import * as mapRequest from "@/api/map";

export default {
  name: "ag_album_short_play_partner",
  props:{//这里外部的数据传入
    shortPlays:{
      required:true,
      default:()=>{
        return [];
      }
    }
  },
  data() {
    return {
      inputVisible:false,
      inputValue:'',
    }
  },
  created() {
  },
  methods: {
    close(index,name){
      // 注意:这里的index 不能直接拿到删除 因为这个index 是过滤后的 所以通过name找下标 然后删除
      console.log("name",name);
      let findex=this.shortPlays.findIndex(f=>f.shortPlayName==name);
      console.log("findex",findex);
      if(findex==-1 || findex<0){
        this.$message.error("删除短剧合作方失败!请联系开发人员");
        return;
      }
      //console.log(findex);
      let data=this.shortPlays[findex];
      console.log("data",data);
      if(data.id){// 存在id 说明本身就有合作方 标记删除
        this.$set(data,'delFlag',true);
        this.$emit('input',this.shortPlays);
      }else{
        this.shortPlays.splice(findex,1);
        this.$emit('input',this.shortPlays);
      }
    },
    btnClick(){
      this.inputVisible=true;
      this.$nextTick(()=>{
        this.$refs.ref.$refs.input.focus();
      })
    },
    inputConfirm(){
      let inputValue=this.inputValue;
      if(inputValue){
        mapRequest.addShortPlay({name:inputValue}).then(res=>{
          let data=res.data.data;
          this.shortPlays.push({addFlag:true,shortPlayId:data.id,shortPlayName:data.name});
          this.$emit('input',this.shortPlays);
        }).catch(err=>{
          this.$message.error("添加短剧合作方失败");
          console.log(err);
        })
      }
      this.inputVisible=false;
      this.inputValue='';
    }

  },
  computed: {
    shortPlaysFilter(){
      let obj=this.shortPlays.filter(item=>{
        if(item.delFlag&&item.delFlag==true) return false;
        return true;
      });
      return obj;
    }
  },
  watch: {},
  components: {},

}
</script>

<style scoped>

</style>

这个就是封装的组件,然后想用的时候直接引用即可。

方案二

<!--
删除逻辑:
1、原始tags中有delFlag true 这种数据不能展示,所以用 filteredTags 过滤
2、如果是本来存在的删除时可以标记delFlag true,如果时添加后(没点击提交动作,数据就没保存)又删除,这种直接删除即可 因为数据库没保存这些数据

[ { "addFlag": true, "shortPlayId": 8, "shortPlayName": "北京攸合" } ]
-->
<template>
  <div>
<!--    {{tags}}-->
    <el-tag v-for="(tag,index) in filteredTags" :key="index" closable @close="handleClose(index)">
      {{tag.shortPlayName}}
    </el-tag>
    <el-select v-model="bindModel" filterable clearable value-key="id"  placeholder="请选择短剧合作方" size="small" style="margin-left: 5px;width: 150px">
      <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item">
      </el-option>
    </el-select>
    <el-button type="primary" size="small" style="margin-left: 5px" @click="addClick">添加</el-button>
  </div>
</template>

<script>
import * as mapRequest from "@/api/map";
export default {
  name: "ag-album-short-play-partner-v2",
  props:{
    tags:{
      type:Array,
      required:true,
      default:()=>{
        return [];
      }
    }
  },
  data() {
    return {
      bindModel:{

      },
      options:[],
    }
  },
  created() {
    this.getList();
  },
  methods: {
    getList(){
      this.options=JSON.parse('[{"id":8,"name":"北京攸合","createdAt":"2023-12-26 14:26:09","updatedAt":"2023-12-26 14:26:09"},{"id":9,"name":"网易","createdAt":"2024-01-03 10:13:37","updatedAt":"2024-01-03 10:13:37"}]');
      //这里是要请求后台数据的
      // mapRequest.findShortPlayList({},{}).then(res=>{
      //   this.options=res.data.data.records;
      // }).catch(err=>{
      //   this.$message.error(err.data.message);
      // })
    },
    handleClose(index){
      const tag=this.filteredTags[index];
      // console.log("-----",tag);
      if(tag==null){
        this.$message.error("删除错误!");
        return;
      }
      const originalIndex = this.tags.findIndex(t => t === tag);
      if (originalIndex !== -1 && this.tags[originalIndex].id ) {
        this.$set(this.tags[originalIndex], 'delFlag', true);
        this.$emit('input', this.tags);
      }else if (originalIndex !=-1 && (this.tags[originalIndex].id === null || this.tags[originalIndex].id === undefined)  ){
        this.tags.splice(originalIndex,1);
      }
      // this.$set(tag,'delFlag',true);
      // console.log("data",tag,",tags:",this.tags);
      // this.$emit('input',this.tags);


    },
    addClick(){
      // 请勿重复添加
      if(this.bindModel.id){
        // console.log("@@@",this.bindModel);
        let data=this.bindModel;
        this.tags.push({addFlag:true,shortPlayId:data.id,shortPlayName:data.name});
        // console.log("---",this.tags);
        this.$emit('input',this.tags);
        this.bindModel=null;
        return;
      }else{
        this.$message.warning("请选择合作方后再添加~");
        return;
      }

    },
  },
  computed: {
    filteredTags() {
      return this.tags.filter(tag => !tag.delFlag);
    }
  },
  watch: {},
  components: {},

}
</script>

<style scoped>

</style>

最终就是外面的调用

<!--
用来写测试案例
-->
<template>
  <div>
    <ag-album-short-play-partner :short-plays="shortPlays"></ag-album-short-play-partner>
    <ag-album-short-play-partner-v2 :tags="shortPlays"></ag-album-short-play-partner-v2>
  </div>


</template>


<script>
import agAlbumShortPlayPartner from "@/views/longVideo/album/components/ag_album_short_play_partner";
import AgAlbumShortPlayPartnerV2 from "@/views/longVideo/album/components/ag_album_short_play_partner_v2";
export default {
  name:'videoDirUploadList',
  data(){
    return{
      data:{
        album:{

        }
      },
      shortPlays:[{"id":8,"albumId":44116442,"shortPlayId":9,"createdAt":"2024-01-04 15:50:59","updatedAt":"2024-01-04 15:50:59","shortPlayName":"网易","delFlag":"","addFlag":""}],

    }
  },
  created() {
  },
  methods:{
  

  },
  components:{
    AgAlbumShortPlayPartnerV2,
    agAlbumShortPlayPartner,
  }

}
</script>

<style>
</style>

ok,本期结束,关注作者不迷路~持续更新好用的组件~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1360695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【人工智能】深入了解人工智能的核心算法与应用实践

人工智能 学习AI要看的第一本书人工智能应当以人为本人工智能&#xff08;第3版&#xff09;通晓六点&#xff0c;明白人工智能是怎么回事基本概念和历史基础知识基于知识的系统高级专题现在和未来安全和编程 人工智能已经是基础学科 学习AI要看的第一本书 人工智能知识对于当…

PLC分段传送带控制示例

一、为了节约用电&#xff0c;将长长的传送带进行分段&#xff0c;哪断上有物品&#xff0c;哪断才运行 二、每一断末尾都有传感器&#xff0c;传感器能感受到物体有没有到传送带的末尾 三、这个传感器是接近开关 四、控制流程 五、IO地址分配 六、按下启动按钮后&#xff0c;…

【Linux软件包管理器】yum详解

目录 1、什么是软件包 2、yum的操作 1&#xff09;yum源 2&#xff09;三板斧 ① yum list ② yum install [软键名] ③ yum remove [软件名] 1、什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了,…

自存react crash course(1)

1.创建一个react 项目 确保有node.js 创建名为react-task-tracker的react项目 npx create-react-app react-task-tracker 启动项目 npm start2.项目结构 所有组件都是放在src下面的 3. jsx // jsx语法 和html很像&#xff0c;class用的是className来使用css的样式<div…

【unity】Obi插件架构组成(参数详细解释)——解算器四面板设置、三种更新器、参与者介绍

文章目录 一、架构&#xff08;Architecture&#xff09;1.1 Obi解算器&#xff08;ObiSolver&#xff09;1.2 ObiUpdater1.3 ObiActorBlueprint1.4 Obi参与者&#xff08;ObiActor&#xff0c;如ObiRope等&#xff09; 二、Obi解算器&#xff08;ObiSolver&#xff09;2.1 解算…

vue3学习 【2】vite起步和开发工具基本配置

vite的简介 官方文档 刚起步学习&#xff0c;所以我们只需要按照官方文档的入门流程即可。推荐阅读一下官网的为什么使用vite vite目前需要的node版本是18&#xff0c;可以参考上一篇文章的安装nvm&#xff0c;用来进行多版本的node管理。 vite安装与使用 npm create vitela…

24年初级会计资格考试报名信息采集流程共10大步骤,千万不要搞错

2024年初级会计资格考试报名信息采集流程共10大步骤&#xff0c;不要搞错哦&#xff1b; 第一步&#xff1a;输入证件号、点击登录 第二步&#xff1a;阅读采集须知 第三步&#xff1a;填写个人信息&#xff08;支付宝搜索"亿鸣证件照"或者微信搜索"随时照&q…

C# Onnx Chinese CLIP 通过一句话从图库中搜出来符合要求的图片

目录 效果 生成图片特征 查找踢足球的人 测试图片 模型信息 image_model.onnx text_model.onnx 项目 代码 Form1.cs Clip.cs 下载 C# Onnx Chinese CLIP 通过一句话从图库中搜出来符合要求的图片 效果 生成图片特征 查找踢足球的人 测试图片 模型信息 image_mod…

Java/JDK下载安装与环境配置

Java由Sun Microsystems&#xff08;现在是Oracle的子公司&#xff09;于1995年首次发布。它是一种面向对象的编程语言&#xff0c;广泛应用于Web开发、移动应用程序开发、桌面应用程序开发和企业级应用程序开发等领域。 Java语言的主要特点是跨平台、可移植性强、安全性高和具…

【AI视野·今日Sound 声学论文速览 第三十九期】Tue, 2 Jan 2024

AI视野今日CS.Sound 声学论文速览 Tue, 2 Jan 2024 Totally 7 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Enhancing Pre-trained ASR System Fine-tuning for Dysarthric Speech Recognition using Adversarial Data Augmentation Authors Huimen…

《微机原理与应用》期末考试题库(附答案解析)

第1章 微型计算机概述 1.微型计算机的硬件系统包括___A _____。 A&#xff0e;控制器、运算器、存储器和输入输出设备 B&#xff0e;控制器、主机、键盘和显示器 C&#xff0e;主机、电源、CPU和输入输出 D&#xff0e;CPU、键盘、显示器和打印机 2.微处…

LLM Agent零微调范式 ReAct Self Ask

前三章我们分别介绍了思维链的使用&#xff0c;原理和在小模型上的使用。这一章我们正式进入应用层面&#xff0c;聊聊如何把思维链和工具使用结合得到人工智能代理。 要回答我们为什么需要AI代理&#xff1f;代理可以解决哪些问题&#xff1f;可以有以下两个视角 首先是我们…

算法训练day60|单调栈part0

参考&#xff1a;代码随想录 84.柱状图中最大的矩形 要求当前柱形的左右两边第一个比他小的位置 对于高度为5的柱子&#xff08;index为2&#xff09; mid 他的左边第一个比他小的柱子为1&#xff0c;index为1 left 他的右边第一个比他小的柱子高度为2&#xff0c;index为4…

Springcloud 微服务实战笔记 Eureka

服务治理 服务注册 在服务治理框架中&#xff0c;通常都会构建一个注册中心&#xff0c;每个服务单元向注册中心登记自己提供的服务&#xff0c;将主机与端口号、版本号、通信协议等一些附加信息告知注册中心&#xff0c;注册中心按服务名分类组织服务清单。当服务启动后&…

DBeaver 连接mysql 报错 Public Key Retrieval is not allowed

问题描述 一段时间没有用本地数据库&#xff0c;使用dbeaver连接mysql报错&#xff1a;Public Key Retrieval is not allowed 原因分析&#xff1a; Public Key Retrieval is not allowed&#xff1a;不允许进行公钥检索。 解决方案&#xff1a; 在编辑连接中找到allowPu…

swift ——多行文字前面内容省略

首先来说一说ios中的 lineBreakModelineBreakMode : 设置文字过长时的显示截断样式 可选值如下 byWordWrapping &#xff1a; 以单词为单位换行&#xff0c;以单词为单位截断。byCharWrapping &#xff1a;以字符为单位换行&#xff0c;以字符为单位截断。byClipping &#x…

Note: A Journey Across Canada

A Journey Across Canada 一场横穿加拿大的旅行 across journey After a quiz last autumn, Kuang crossed the continent eastward to Toronto to visit his schoolmate, the distance measuring approximately 5000 kilometers. 去年秋天一次考试后&#xff0c;Kuang向东穿…

计算机毕业设计 基于SpringBoot的公司资产网站的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

MyBatis-Plus框架学习笔记

先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;❤️ ❤️ ❤️ 文章码字不易&#xff0c;如果喜欢可以关注我哦&#xff01; ​如果本篇内容对你有所启发&#xff0c;欢迎访问我的个人博客了解更多内容&#xff1a;链接地址 MyBatisPlus &#xff08;简称…

CodeWave智能开发平台--03--目标:应用创建--03页面子页面设计

摘要 本文是网易数帆CodeWave智能开发平台系列的第06篇&#xff0c;主要介绍了基于CodeWave平台文档的新手入门进行学习&#xff0c;实现一个完整的应用&#xff0c;本文主要完成页面子页面设计 CodeWave智能开发平台的06次接触 CodeWave参考资源 网易数帆CodeWave开发者社…