选项菜单自动换行的简单实现(Vue)

在做列表筛选的时候经常会按照不同的维度来过滤筛选数据,多标签可供选择就比较常见,但是标签较多时,就涉及到选项标签的展开与折叠,这与展示区域、选项个数有关系,下面的实现就是解决了页面宽度不确定、标签个数不确定、标签宽度不确定时的自动折叠。

效果示意

实现思路:

  • 选项展示区采用flex布局,允许换行;
  • 选项高度固定,默认状态下,选强展示区的高度就是单个选项的高度;
  • 采用展示区域的max-height来控制展开、收起状态;
  • 监听到选项数组变化、浏览器窗口大小变化时,重新判断是否需要展示“更多”
  • 采用子选项的长度总和与选项展示区域宽度比较的方式确定选项是否换行,是否要显示“更多”

主要特点:
1.不需要考虑选项的个数,即展开、收起操作时,选项数组不会变化,不需要干预;
2.采用CSS实现样式的控制,选项宽度无限制,按需修改样式可实现等宽、不等宽的需求;
3.可实时按照浏览器窗口大小来调整布局,并按需展示“更多”;
4.不同的需求,包括PC、手机的不同要求,可用css来调整。

主要实现如下(示例代码是作为一个可复用组件方式实现的):

<template>
  <div class="searchbar-container">
    <span class="condition-title">{{ title }}</span>

    <div ref="search-option-container" :class="['search-option-container', isExpand ? 'search-option-container-expand' : '']">

      <div class="condition-option-frame">
        <span :class="['condition-option', value == '' ? 'condition-option-selected' : '']" @click="handleSelect('')">全部</span>
      </div>

      
        <div class="condition-option-frame" v-for="(op, index) in options" :key="index" :content="op"  @click="handleSelect(`${op}`)">
          <span :class="[`${optionClassName}`, 'condition-option', (optionValueKey ? op[optionValueKey] : op) === value ? 'condition-option-selected' : '' ]">{{ optionlabelKey ? op[optionlabelKey] : op }}</span>
        </div>

    </div>

    <div class="condition-option-more">
      <div v-if="showToggle" @click="handleMore">
        {{ isExpand ? '收起' : '更多'}}<i :class="[isExpand ? 'el-icon-arrow-up' : 'el-icon-arrow-down']"></i>
      </div>
    </div>
  </div>
</template>
<script>

export default {
  name: 'SearchOptionsAutoFold',
  props: {
    title: {
      type: String,
      default: '工业大类'
    },
    prop: {
      type: String,
      default: ''
    },
    value: {
      type: String,
      default: ''
    },
    optionClassName: {
      type: String,
      default: ''
    },
    options: {
      type: Array,
      default: function () {
        return ["煤炭开采和洗选业", "石油和天然气开采业", "黑色金属矿采选业", "有色金属矿采选业", "非金属矿采选业", "其他采矿业", "农副食品加工业", "食品制造业", "饮料制造业", "烟草制品业", "纺织业", "纺织服装、鞋、帽制造业", "皮革、毛皮、羽毛(绒)及其制品业", "木材加工及木、竹、藤、棕、草制品业", "家具制造业", "造纸及纸制品业", "印刷业和记录媒介的复制", "文教体育用品制造业", "石油加工、炼焦及核燃料加工业", "化学原料及化学制品制造业", "医药制造业", "化学纤维制造业", "橡胶制品业", "塑料制品业", "非金属矿物制品业", "黑色金属冶炼及压延加工业", "有色金属冶炼及压延加工业", "金属制品业", "通用设备制造业", "专用设备制造业", "交通运输设备制造业", "电气机械及器材制造业", "通信设备、计算机及其他电子设备制造业", "仪器仪表及文化、办公用机械制造业", "工艺品及其他制造业", "废弃资源和废旧材料回收加工业", "电力、热力的生产和供应业", "燃气生产和供应业", "水的生产和供应业"];
      }
    },
    optionlabelKey: {
      type: String,
      default: ''
    },
    optionValueKey: {
      type: String,
      default: ''
    },
  },
  data() {
    return {
      showToggle: false,
      isExpand: false
    }
  },
  watch: {
    options(val, oldVal) {
      if (val.length > 0) {
        this.refreshViews();
      }
    }
  },
  mounted() {
    if (this.options.length > 0) {
      this.refreshViews();
    }
    window.onresize = () => {
      this.refreshViews();
    }
  },
  methods: {
    handleMore() {
      this.isExpand = !this.isExpand
    },
    handleSelect(value) {
      this.$emit('handleSelect', this.prop, value)
    },
    refreshViews() {
      this.$nextTick(() => { // 页面渲染完成后的回调

        let containerClientWidth = this.$refs['search-option-container'].clientWidth;
        let length = this.$refs['search-option-container'].children.length;

        console.log('containerClientWidth==>' + containerClientWidth)
        console.log('length==>' + length)
        let totalWidth = 0;
        for (let i = 0; i < length; i++) {
          totalWidth = totalWidth + this.$refs['search-option-container'].children[i].clientWidth
        }
        // 存在更多选项
        this.showToggle = totalWidth > containerClientWidth;
      })
    }
  }
}
</script>
<style scoped>
.searchbar-container {
  padding: 4px 0px;
  display: flex;
  align-items: center;
}
.condition-title {
  font-weight: bold;
  width: 5em;
  flex-shrink: 0;
}
.search-item-container {
  flex-grow: 1;
  display: flex;
  flex-wrap: wrap;
}

.search-option-container {
  flex-grow: 1;
  display: flex;
  flex-wrap: wrap;
  max-height: 30px;
  overflow: hidden;
}

.search-option-container-expand {
  max-height: 500px;
}

.condition-option-frame {
  padding: 0px 8px;
  margin: 0px;
  height: 30px;
  display: flex;
  align-items: center;
}

.condition-option {
  /* 是否需要等长 */
  width: 5em;
  display: -webkit-box !important;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-all;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  text-align: center;
  cursor: pointer;
}
/* 单个字母 */
.condition-option-letter {
  width: 1em;
}

.condition-option-selected {
  color: var(--color-primary);
  font-weight: bold;
}

.condition-option-more {
  padding-top: 5px;
  width: 66px;
  align-self: baseline;
  flex-shrink: 0;
  color: var(--color-primary);
}
.condition-option-more > div {
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

/* 窄屏设备 */
@media only screen and (max-width: 992px) {
}
</style>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,961评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,444评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,009评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,082评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,101评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,271评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,738评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,395评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,539评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,434评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,481评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,160评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,749评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,816评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,038评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,548评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,140评论 2 341

推荐阅读更多精彩内容