在vue中,封装个分类选择下拉列表

效果如下:
在这里插入图片描述
1.在components目录下新建个文件SubjectCatalog.vue组件,代码如下:

<template>
  <div class="subject-catalog">
    <div class="select">
      <span class="select-name" @click="allBook">所有绘本</span>
    </div>
    <div v-for="(item,index) in optList" :key="index" class="select">
      <span class="select-name" @click="manageUser(index)">{{ selectData[item.value] === ''? item.name :selectData[item.value] }}
        <i :class="[ 'el-icon-caret-bottom' , selectFlag === index? 'handstands' : 'handstand']" />
      </span>
      <ul :ref="item.value" :class="['select-box' ,selectFlag === index? '' : 'select-box-hide']">
        <li v-for="(item1,index1) in item.children" :key="index1" class="select-li" @click="optionClick(item1.value,item.value)">
          {{ item1.name }}
        </li>
      </ul>
    </div>
  </div>
</template>

/*
  分类选择组件
  optList: 分类列表
  choseOpt: 分类列表下选中的值
*/
<script>
export default {
  name: 'SubjectCatalog',
  props: {
    optList: {
      type: Array,
      default() {
        return []
      } },
    choseOpt: {
      type: Object,
      default() {
        return {}
      } }
  },
  data() {
    return {
      selectFlag: -1, // 当前选中的下拉框
      selectData: this.choseOpt // 选中的值
    }
  },
  methods: {
    // 展开的下拉框
    manageUser(index) {
      if (this.selectFlag === index) {
        this.selectFlag = -1
      } else {
        this.selectFlag = index
      }
    },
    // 选中的值
    optionClick(value, name) {
      this.selectData[name] = value
      this.selectFlag = -1
      // 把选中的值传递给父组件
      this.$emit('select-data', this.selectData)
    },
    // 点击所有绘本
    allBook() {
      // 遍历对象,初始化值
      Object.keys(this.selectData).forEach((key) => {
        this.selectData[key] = ''
      })
    }
  }
}
</script>

<style lang="less">
.subject-catalog {
        .vw(180);
        height: auto;
        color: #fff;
        .select {
            margin-bottom: 8px;
            .select-name {
                display: inline-block;
                .vw(150);
                .vh(50);
                .line-height(50);
                cursor: pointer;
                text-align: center;
                background-color: @BASE_DM;
            }
            .select-box {
              max-height: 15vh;
              overflow: hidden;
              transition: max-height 0.6s;
                .select-li {
                  &:hover {
                    background-color: #98A8A7 !important;
                  }
                   display: inline-block;
                   .vw(150);
                   .vh(50);
                   .line-height(50);
                   cursor: pointer;
                   text-align: center;
                   background-color: #547374;
                }
            }
            .select-box-hide {
              max-height: 0;
            }
            .handstands {
              transition:  all .3s;
            }
            .handstand {
              transform:rotate(180deg);
              transition:  all .3s;
            }
        }
    }
</style>

2.在父组件中应用封装好的组件

<template>
  <div class="picture-list-container">
    <SubjectCatalog :opt-list="optList" :chose-opt="choseOpt" @select-data="selectValue" />
  </div>
</template>

<script>
// 引入组件
import SubjectCatalog from '../../components/SubjectCatalog.vue'
export default {
  name: 'PictureList',
  components: {
    SubjectCatalog
  },
   data() {
    return {
      optList: [
        { name: '年龄',
          value: 'age',
          children: [
            {
              name: '3~6岁',
              value: '3-6'
            },
            {
              name: '6~8岁',
              value: '6-8'
            }
          ]
        },
        { name: '主题',
          value: 'theme',
          children: [
            {
              name: '音乐',
              value: '音乐'
            },
            {
              name: '艺术',
              value: '艺术'
            }
          ]
        },
        { name: '难度',
          value: 'difficulty',
          children: [
            {
              name: '一般',
              value: '一般'
            },
            {
              name: '较难',
              value: '较难'
            }
          ]
        }
      ],
      choseOpt: {
        age: '', // 年龄
        theme: '', // 主题
        difficulty: '' // 难度
      }
    }
  },
    methods: {
    // 选中的值
    selectValue(id) {
      console.log('我是选中的值', id)
    }
  }
}
</script>

注意事项:
在组件中有个selectData: this.choseOpt的赋值,看起来显得多余,但这是必须的,因为props的值是父组件传过来的,我们不能直接在子组件直接修改父组件传过来的值.这不仅会报警告,也破坏了单向数据流的设想.所以我们可以在子组件再声明一个变量,然后把父组件传过来的值赋给这个变量,我们再修改,就可以了.

发布了34 篇原创文章 · 获赞 13 · 访问量 4902

猜你喜欢

转载自blog.csdn.net/qq_40544291/article/details/104194888