Vue实现多标签选择器

本文实例为大家分享了Vue实现多标签选择器展示的具体代码,供大家参考,具体内容如下

实现效果

实现代码

<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',

 }]
}]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue中动态设置meta标签和title标签的方法

    因为和原生的交互是需要h5这边来提供meta标签的来是来判断要不要显示分享按钮,所有就需要手动设置meta标签,标题和内容 //router内的设置 { path: '/teachers', name: 'TDetail', component: TDetail, meta: { title:"教师详情", content: 'disable' } }, { path: '/article', name: 'Article', component: Article, meta: { t

  • vue监听input标签的value值方法

    由于项目需要做实时搜查询数据,所以需要监听input标签的value,这里使用的前端框架vue <input id="materialSearch" type="text" @keyup.enter="search" @input="search($event)"/> 这里的重点是:@input="search($event)",表示当文本框有内容输入时,则调用search方法 /*模糊搜索*/

  • 关于vue v-for循环解决img标签的src动态绑定问题

    在解决这个问题上,遇到了很多错误的方案,一直没有跑通,有些是图片标记出现了,但是图片内容没有出现,这就很让人头疼了,下面,我讲解我操作成功的案例吧. 1.目录结构如下 图片放置在与src同级的static文件夹下,在这里,我放置在slider中 2.数据配置如下: 注意引入的路径,直接从static文件中对应的地方引入. data () { return { product:[ { "src":'../../static/slider/logo1.jpg', "decerat

  • 详解vue-meta如何让你更优雅的管理头部标签

    在 Vue SPA 应用中,如果想要修改HTML的头部标签,或许,你会在代码里,直接这么做: // 改下title document.title = 'what?' // 引入一段script let s = document.createElement('script') s.setAttribute('src', './vconsole.js') document.head.appendChild(s) // 修改meta信息,或者给html标签添加属性... // 此处省略一大坨代码...

  • vue-router实现tab标签页(单页面)详解

    vue-router 是 Vue.js 官方的路由插件,适合用于构建标签页应用.Vue 的标签页应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来,vue-router 会把各个组件渲染到正确的地方. 首先,.vue中的内容非常简单,<router-link>创建标签,并指定路径,<router-view>渲染路由匹配到的组件. <template> <div id="account"> <p class=&quo

  • 用v-html解决Vue.js渲染中html标签不被解析的问题

    前言 最近在工作中遇到一个问题,在网页中后台传来的json数据中包含html标签,将该json数据绑定到Vue.js中对象中,对该对象进行for循环,发现数据中的html标签不能被解析,而是当作字符显示出来. 问题如下所示: 解决方法: Vue.js中提供了v-html这个指令来解决这个问题,或者对数据对象使用{{{vm.data}}}三个大括号来包裹对象,就可以正常解析了. 代码改动如下: 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家都 学习或者工作能带来一定的帮助,如果有疑问大家

  • 详解Vue-基本标签和自定义控件

    按照国际惯例先安利:Useful-Open-Source-Android_jb51.rar 上一篇把环境搭完了,然后把默认的8080内容跑通了,这一片尝试把常用的一些标签给学习一下(按钮啊,列表,图片啥的) 整篇都是跟着官方教程学,只是加入一系列自己的理解和分析,方便以后温故 默认环境已经帮我们把包结构建好了,如下 index.html是我们的页面 main.js是让App.vue和页面产生关联的"挂载js文件"(不知道这么描述合适不合适,有问题欢迎提出) App.vue就是我们具体的

  • vue中v-for循环给标签属性赋值的方法

    1.给每个按钮添加class的属性值以及icon图标属性值,通过v-for实现自动添加样式,发现属性值无法显示,切记在属性前加上v-bind <html> <head> <meta charset="utf-8"> <title>v-for在线测试实例</title> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"> &

  • Vue.js表单标签中的单选按钮、复选按钮和下拉列表的取值问题

    Vue.js可以很方便的实现数据双向绑定,所以在处理表单,人机交互方面具有很大的优势.下面给大家介绍Vue.js表单标签中的单选按钮.复选按钮和下拉列表的取值问题. 摘要: 表单标签取值问题中,单选按钮.复选按钮和下拉列表都比较特殊.这里总结一下vue.js中关于单选按钮.复选按钮和下拉列表不同情况的取值特殊性问题. 表单标签取值问题中,单选按钮.复选按钮和下拉列表都比较特殊.这里总结一下vue.js中关于单选按钮.复选按钮和下拉列表不同情况的取值特殊性问题. 一.单选按钮 单选按钮:单选按钮用

  • 详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)

    在 vue 中,实现 Tab 切换主要有三种方式:使用动态组件,使用 vue-router 路由,使用第三方插件. 因为这次完成的功能只是简单切换组件,再则觉得使用路由切换需要改变地址略微麻烦,所以使用的是动态组件实现,如果是在大型应用上,可能使用 vue-router 会方便一些. 先看下最终实现的效果,结构比较简单,顶部的三个 Tab 标签用于切换,内容区域分别为三个子组件. 效果预览 关键代码及分析如下: <template> // 每一个 tab 绑定了一个点击事件,传入的参数对应着

随机推荐