基于Vue和Element-UI中Select 选择器的分组全选以及样式修改问题

Posted c.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Vue和Element-UI中Select 选择器的分组全选以及样式修改问题相关的知识,希望对你有一定的参考价值。

文章目录

基于Vue和Element-UI中Select 选择器的分组全选以及样式修改问题

首先我们来看看最终表现出来的效果图

本人前端写的比较少,因为有需求是需要做到如上图所示的效果,所以特意研究了一下。

Select选择器分组

关于el-select 选择器分组这个,在element-ui的官网也给出了简单的demo了,所以本博文也是基于这个demo的基础上进行改造的。

<template>
  <el-select v-model="value" placeholder="请选择">
    <el-option-group
      v-for="group in options"
      :key="group.label"
      :label="group.label">
      <el-option
        v-for="item in group.options"
        :key="item.value"
        :label="item.label"
        :value="item.value">
      </el-option>
    </el-option-group>
  </el-select>
</template>

<script>
  export default 
    data() 
      return 
        options: [
          label: '热门城市',
          options: [
            value: 'Shanghai',
            label: '上海'
          , 
            value: 'Beijing',
            label: '北京'
          ]
        , 
          label: '城市名',
          options: [
            value: 'Chengdu',
            label: '成都'
          , 
            value: 'Shenzhen',
            label: '深圳'
          , 
            value: 'Guangzhou',
            label: '广州'
          , 
            value: 'Dalian',
            label: '大连'
          ]
        ],
        value: ''
      
    
  
</script>

Select选择器分组加全选

至于全选的问题,其实就是加上checkbox,然后在select框change的时候,还有checkBox勾选的时候去处理全选的逻辑。所以我们需要在<el-select>上加上@change的事件,还有在<el-checkbox>上加上@change的事件。

  1. <el-select>@change的事件处理:当分组下的全部选项勾选的时候,全选框需要对应勾选,当分组下的全部选项取消勾选的时候,全选框需要取消对应勾选

  2. <el-checkbox>@change的事件处理:当勾选全选框的时候,需要把分组下的全部选项都选择,当全选框取消勾选的时候,需要把分组下的全部选项取消勾选。

为此我们的data的数据需要加上checked的标记位来标志该选择项有没有被勾选。数据如下:

[
        id: 1,
        label: '热门城市',
        checked: false,
        options: [
          value: 'Shanghai',
          label: '上海'
        , 
          value: 'Beijing',
          label: '北京'
        ]
      , 
        id: 2,
        label: '城市名',
        checked: false,
        options: [
          value: 'Chengdu',
          label: '成都'
        , 
          value: 'Shenzhen',
          label: '深圳'
        , 
          value: 'Guangzhou',
          label: '广州'
        , 
          value: 'Dalian',
          label: '大连'
        ,
        
          value: 'Huizhou',
          label: '惠州'
        ]
      ,
      
        id: 3,
        label: '城市名2',
        checked: false,
        options: [
          value: 'Chengdu2',
          label: '成都2'
        , 
          value: 'Shenzhen2',
          label: '深圳2'
        , 
          value: 'Guangzhou2',
          label: '广州2'
        , 
          value: 'Dalian2',
          label: '大连2'
        ,
        
          value: 'Huizhou2',
          label: '惠州2'
        ]
      ,
      
        id: 4,
        label: '城市名3',
        checked: false,
        options: [
          value: 'Chengdu3',
          label: '成都3'
        , 
          value: 'Shenzhen3',
          label: '深圳3'
        , 
          value: 'Guangzhou3',
          label: '广州3'
        , 
          value: 'Dalian3',
          label: '大连3'
        ,
        
          value: 'Huizhou3',
          label: '惠州3'
        ]
      ]

接下来就是处理的代码了

 <template>
  <div>
    <el-select v-model="value" placeholder="请选择" @change="changeSelect" style="width: 400px"  clearable multiple collapse-tags
               popper-class="productGroupSelector">
      <el-option-group class="productGroupSelector-group"
                       v-for="group in options"
                       :key="group.label"
                       :label="group.label">
        <div style="display: flex; align-items: start;">
          <div style="display: flex;align-items: center; padding-top: 8px; padding-left: 5px">
            <el-checkbox v-model="group.checked" @change='selectAll($event,group.id)'></el-checkbox>
          </div>
          <div style="width: 400px">
            <el-option class="productGroupSelector-option"
                       v-for="item in group.options"
                       :key="item.value"
                       :label="item.label"
                       :value="group.label + '-' + item.value">
            </el-option>
          </div>
        </div>
      </el-option-group>
    </el-select>
  </div>
</template>
<script>
export default 
  name: 'SelectorComponent',
  data () 
    return 
      options: [
        id: 1,
        label: '热门城市',
        checked: false,
        options: [
          value: 'Shanghai',
          label: '上海'
        , 
          value: 'Beijing',
          label: '北京'
        ]
      , 
        id: 2,
        label: '城市名',
        checked: false,
        options: [
          value: 'Chengdu',
          label: '成都'
        , 
          value: 'Shenzhen',
          label: '深圳'
        , 
          value: 'Guangzhou',
          label: '广州'
        , 
          value: 'Dalian',
          label: '大连'
        ,
        
          value: 'Huizhou',
          label: '惠州'
        ]
      ,
      
        id: 3,
        label: '城市名2',
        checked: false,
        options: [
          value: 'Chengdu2',
          label: '成都2'
        , 
          value: 'Shenzhen2',
          label: '深圳2'
        , 
          value: 'Guangzhou2',
          label: '广州2'
        , 
          value: 'Dalian2',
          label: '大连2'
        ,
        
          value: 'Huizhou2',
          label: '惠州2'
        ]
      ,
      
        id: 4,
        label: '城市名3',
        checked: false,
        options: [
          value: 'Chengdu3',
          label: '成都3'
        , 
          value: 'Shenzhen3',
          label: '深圳3'
        , 
          value: 'Guangzhou3',
          label: '广州3'
        , 
          value: 'Dalian3',
          label: '大连3'
        ,
        
          value: 'Huizhou3',
          label: '惠州3'
        ]
      ],
      value: ''
    
  ,
  methods: 
    onChange (value) 
      console.log(value)
      console.log(this.value)
    ,
    selectAll (val, id) 
      const selectOption = this.options.find(f => f.id === id)
      const arr = selectOption.options.map(m => selectOption.label + '-' + m.value)
      if (val) 
        arr.forEach(item => 
          if (!this.value.includes(item)) 
            this.value.push(item)
          
        )
       else 
        this.value.forEach((item, index) => 
          if (arr.includes(item)) 
            this.value.splice(index, 1, '')
          
        )
      
      this.value = this.value.filter(f => f !== '')
    ,
    changeSelect (val) 
      this.options.forEach(item => 
        const arr = item.options.map(m => item.label + '-' + m.value)
        item.checked = arr.every((v) => 
          return val.some(s => s === v)
        )
      )
    
  

</script>

然后分组和全选的功能就完成了。

Select 选择器的样式修改问题

接下来就是比较头疼的样式修改问题。

element-ui文档中给出了两个有用的属性,能帮助我们修改样式。

样式总是修改不成功的问题主要是因为:通过Dom元素可以发现,官方Select选择器下拉框是直接插入body标签中,与最外级div同级,所以在Vue中无论怎么写css都无法覆盖到下拉框样式。

所以解决方法主要有两个了。

  1. 设置:popper-append-to-body="false",之后我们就可以从Dom元素中可以看出,下拉框元素被直接插入到 el-select 标签内,可以编写css或者用深度选择器去覆盖样式了。
  2. 使用全局样式去覆盖样式

我这里选择了第二种,然后使用popper-class属性给select 下拉框设置了一个class, 然后用css选择器给下拉框元素设置样式。

下面是全部的代码和样式:

<template>
  <div>
    <el-select v-model="value" placeholder="请选择" @change="changeSelect" style="width: 400px"  clearable multiple collapse-tags
               popper-class="productGroupSelector">
      <el-option-group class="productGroupSelector-group"
                       v-for="group in options"
                       :key="group.label"
                       :label="group.label">
        <div style="display: flex; align-items: start;">
          <div style="display: flex;align-items: center; padding-top: 8px; padding-left: 5px">
            <el-checkbox v-model="group.checked" @change='selectAll($event,group.id)'></el-checkbox>
          </div>
          <div style="width: 400px">
            <el-option class="productGroupSelector-option"
                       v-for="item in group.options"
                       :key="item.value"
                       :label="item.label"
                       :value="group.label + '-' + item.value">
            </el-option>
          </div>
        </div>
      </el-option-group>
    </el-select>
  </div>
</template>
<script>
export default 
  name: 'SelectorComponent',
  data () 
    return 
      options: [
        id: 1,
        label: '热门城市',
        checked: false,
        options: [
          value: 'Shanghai',
          label: '上海'
        , 
          value: 'Beijing',
          label: '北京'
        ]
      , 
        id: 2,
        label: '城市名',
        checked: false,
        options: [
          value: 'Chengdu',
          label: '成都'
        , 
          value: 'Shenzhen',
          label: '深圳'
        , 
          value: 'Guangzhou',
          label: '广州'
        , 
          value: 'Dalian',
          label: '大连'
        ,
        
          value: 'Huizhou',
          label: '惠州'
        ]
      ,
      
        id: 3,
        label: '城市名2',
        checked: false,
        options: [
          value: 'Chengdu2',
          label: '成都2'
        , 
          value: 'Shenzhen2',
          label: '深圳2'
        , 
          value: 'Guangzhou2',
          label: '广州2'
        , 
          value: 'Dalian2',
          label: '大连2'
        ,
        
          value: 'Huizhou2',
          label: '惠州2'
        ]
      ,
      
        id: 4,
        label: '城市名3',
        checked: false,
        options: [
          value: 'Chengdu3',
          label: '成都3'
        , 
          value: 'Shenzhen3',
          label: '深圳3'
        , 
          value: 'Guangzhou3',
          label: '广州3'
        , 
          value: 'Dalian3',
          label: '大连3'
        ,
        
          value: 'Huizhou3',
          label: '惠州3'
        ]
      ],
      value: ''
    
  ,
  methods: 
    onChange (value) 
      console.log(value)
      console.log(this.value)
    ,
    selectAll (val, id) 
      const selectOption = this.options.find(f => f.id === id)
      const arr = selectOption.options.map(m => selectOption.label + '-' + m.value)
      if (val) 
        arr.forEach(item => 
          if (!this.value.includes(item)) 
            this.value.push(item)
          
        )
       else 
        this.value.forEach((item, index) => 
          if (arr.includes(item)) 
            this.value.splice(index, 1, '')
          
        )
      
      this.value = this.value.filter(f => f !== '')
    ,
    changeSelect (val) 
      以上是关于基于Vue和Element-UI中Select 选择器的分组全选以及样式修改问题的主要内容,如果未能解决你的问题,请参考以下文章

基于Vue和Element-UI自定义分组以及分组全选Select 选择器

基于Vue和Element-UI自定义分组以及分组全选Select 选择器

element-ui中el-select与el-tree的结合使用实现下拉菜单

elment表格多选变色 vue Element-ui 表格多选 修改选中行背景色

Vue:解决 element-ui 下拉框过多导致卡顿问题

vue element-ui select框选中回显