基于Vue实现多标签选择器

简介: 基于Vue实现多标签选择器

实现效果

d24.2.png


实现代码

<html lang="en">

<head>
    <title>Document</title>

    <!-- 引入本地组件库 -->
    <link rel="stylesheet" href="static/element-ui/index.css">
    <script src="static/element-ui/vue.js"></script>
    <script src="static/element-ui/index.js"></script>

    <!-- 引入CDN样式 -->
    <!-- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
    <!-- <script src="https://unpkg.com/element-ui/lib/index.js"></script> -->

    <style>
        .not-active {
            display: inline-block;
            font-size: 12px;
            margin: 5px 8px;
        }
        
        span {
            margin: 0 2px;
        }
    </style>
</head>

<body>

    <div id="app">
        <!-- 待选标签 -->
        <div v-for='(category, categoryIndex) in categories' :key="category.id">
            <!-- 分类  -->
            <span class="not-active">{
        {category.name}}:</span>

            <template>
                <span  v-if="category.count"class="not-active" @click="clearCategory(category, categoryIndex)"> 不限</span>
                <my-tag v-else>不限</my-tag>
            </template>

            <!-- 标签  -->
            <template v-for='(child, childIndex) in category.children'>
                <my-tag  v-if="child.active" :closable='true'  @click-child='clickChild(category, categoryIndex, child, childIndex)'>
                    {
        { child.name }}
                </my-tag>
                <span v-else class="not-active" @click='clickChild(category, categoryIndex, child, childIndex)'>{
        { child.name }}</span>
            </template>
        </div>

        <!-- 已选标签 -->
        <div v-if='conditions.length'>
            <span class="not-active" @click="clearCondition">清空已选:<span>
                
            <el-tag
            v-for='(condition, index) in conditions' 
            :key="condition.id"
            type="primary"
            :closable="true"
            size="small"
            :disable-transitions="true"
            @close='removeCondition(condition, index)'
            @click='removeCondition(condition, index)'>
                {
        {condition.name}}
            </el-tag>
        </div>
    </div>

    <script src="./data.js"></script>

    <script>
        // 简单封装一个公用组件
        Vue.component('my-tag', {
            template: "<el-tag v-bind='$attrs' v-on='$listeners' effect='dark' size='small' :disable-transitions='true' @click='clickChild' @close='clickChild'><slot></slot></el-tag>",

            methods: {
                clickChild() {
                    this.$emit("click-child")
                }
            }
        });

        var app = new Vue({
            el: '#app',
            data() {
                return {
                    categories, // 分类标签,可从外部加载配置
                    conditions: [] // 已选条件
                }
            },

            watch: {
                // 监听条件变化,按照请求接口拼装请求参数
                conditions(val){
                    let selectedCondition = {};

                    for(let categorie of this.categories){
                        let selected_list = [];
                        for(let child of categorie.children){
                            if(child.active){
                                selected_list.push(child.name);
                            }
                        }
                        selectedCondition[categorie.name] = selected_list.join("|")
                    }
                    console.log(selectedCondition);
                }
            },

            methods: {
                // 处理标签点击事件,未选中则选中,已选中则取消选中
                clickChild(category, categoryIndex, child, childIndex) {
                    let uid = `${categoryIndex}-${childIndex}`
                    child.uid = uid;
                    console.log(uid)
                    
                    // 取消选择
                    if (child.active === true) {
                        category.count--;
                        child.active = false;
                        this.conditions.forEach((conditionChild, index) => {
                            if (conditionChild.uid === child.uid) {
                                this.conditions.splice(index, 1);
                            }
                        });
                    // 选择
                    } else {
                        category.count++;
                        child.active = true;
                        this.conditions.push(child);
                    }
                },
            
                // 清除已选整个类别标签
                clearCategory(category, categoryIndex) {
                    category.count = 0;
                    
                    // 可选列表均为未选中状态
                    category.children.forEach(child => {
                        child.active = false;
                    })

                    // 清空该类已选元素
                    for (let index = this.conditions.length - 1; index >= 0; index--) {
                        const conditionChild = this.conditions[index];
                        if (conditionChild.uid.startsWith(categoryIndex)) {
                            this.conditions.splice(index, 1);
                        }
                    }
                },
                
                // 移除一个条件
                removeCondition(condition, index) {
                    let categoryIndex = condition.uid.split("-")[0];
                    this.categories[categoryIndex].count --;

                    this.conditions.splice(index, 1)
                    condition.active = false;
                },

                // 清空所有条件
                clearCondition() {
                    for(let i = this.conditions.length-1; i >=0 ; i--){
                        this.removeCondition(this.conditions[i], i);
                    }
                }
            }
        });
    </script>

</body>

</html>

标签筛选的数据格式

data.js

var categories = [{

name: '品牌',
count: 0,
children: [{
name: '联想',
}, {
name: '小米',

}, {
name: '苹果',

}, {
name: '东芝',

}]
}, {
name: 'CPU',
count: 0,
children: [{
name: 'intel i7 8700K',

}, {
name: 'intel i7 7700K',

}, {
name: 'intel i9 9270K',

}, {
name: 'intel i7 8700',

}, {
name: 'AMD 1600X',


}]
}, {
name: '内存',
count: 0,
children: [{
name: '七彩虹8G',

}, {
name: '七彩虹16G',

}, {
name: '金士顿8G',

}, {
name: '金士顿16G',

}]
}, {
name: '显卡',
count: 0,
children: [{
name: 'NVIDIA 1060 8G',

}, {
name: 'NVIDIA 1080Ti 16G',

}, {
name: 'NVIDIA 1080 8G',

}, {
name: 'NVIDIA 1060Ti 16G',

}]
}]


            </div>
目录
相关文章
|
人工智能 API 决策智能
Modelscope结合α-UMi:基于Modelscope的多模型协作Agent
基于单个开源小模型的工具调用Agent,由于模型容量和预训练能力获取的限制,无法在推理和规划、工具调用、回复生成等任务上同时获得比肩大模型等性能。
|
机器学习/深度学习 IDE 开发工具
超越笔记本:JupyterLab 的功能扩展
【8月更文第29天】随着数据科学和机器学习的发展,交互式计算环境的需求也日益增长。Jupyter Notebook 作为这一领域的领头羊,已经得到了广泛的应用。然而,为了满足更加复杂的工作流需求,Jupyter 开发者们推出了 JupyterLab —— 一个下一代的交互式计算环境。本文将探讨 JupyterLab 相对于传统 Jupyter Notebook 的增强功能,并通过具体示例展示这些新特性如何提升工作效率。
627 1
|
安全 数据库 开发者
鸿蒙5开发宝藏案例分享---应用架构实战技巧
本文深入探讨鸿蒙应用架构设计与线程通信实战技巧,涵盖分层架构(产品定制层、基础特性层、公共能力层)的实际应用,通过代码示例讲解如何降低耦合、实现多端复用。同时解析子线程安全更新UI的实现方式,利用 `TaskDispatcher` 和 `Emitter` 进行线程间通信。此外,还分享模块化设计中 HAP、HAR、HSP 的选择与动态加载技巧,以及官方文档未明确提及的开发经验。帮助开发者将理论转化为实践,提升应用性能与可维护性。
|
9月前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
小程序 前端开发 定位技术
简单快速搭建出适配于多平台的小程序
随着移动互联网的深入发展,小程序以其轻量、便捷、即用即走的特点,逐渐成为企业与用户沟通的重要桥梁。在当今数字化时代,随着各大平台纷纷推出小程序,小程序已成为企业与用户交互的重要工具,跨平台开发更是成为开发者们关注的焦点。作为开发者来说,为了满足不同用户的需求,我们需要能够快速搭建出适配于多平台的小程序,那么本文就来聊一聊小程序的优势、如何实现一站式开发多平台的小程序,以及对于小程序功能模块集成能力的期望。
441 2
简单快速搭建出适配于多平台的小程序
|
网络虚拟化 网络架构
不同网段通过静态路由实现互通
静态路由是一种需要管理员手工配置的特殊路由。静态路由比动态路由使用更少的带宽,并且不占用CPU资源来计算和分析路由更新。但是当网络发生故障或者拓扑发生变化后,静态路由不会自动更新,必须手动重新配置。静态路由有5个主要的参数:目的地址和掩码、出接口和下一跳、优先级。 使用静态路由的好处是配置简单、可控性高,当网络结构比较简单时,只需配置静态路由就可以使网络正常工作。在复杂网络环境中,还可以通过配置静态路由改进网络的性能,并且可以为重要的应用保证带宽。
492 0
不同网段通过静态路由实现互通
|
机器学习/深度学习 定位技术
GEE(CCDC-2)——根据以获取的研究区CCDC系数进行土地覆被分类分析
GEE(CCDC-2)——根据以获取的研究区CCDC系数进行土地覆被分类分析
449 0
|
Ubuntu Python
python3安装clickhouse_sqlalchemy(greenlet) 失败
如果上述方法仍然无法解决问题,建议查阅相关错误信息和官方文档,以获取更详细的帮助。确保你的Python环境和依赖库都在最新版本,有时问题可能会因为版本不兼容而导致安装失败。
538 0
|
网络虚拟化
|
Ubuntu Linux Windows
Ventoy -- 一个U盘装多个系统镜像
Ventoy -- 一个U盘装多个系统镜像
1123 0