打造极致体验的Dropdown下拉菜单:智能高亮当前项,数据溢出时自动滚动定位至视野焦点

2,695 阅读5分钟

嘿,前端小伙伴们!今天我们来聊聊熟悉的朋友—— Element 中的 el-dropdown 下拉菜单。这个小家伙可不简单,它可帮助我们实现许多实用的功能。下面就让我为大家系统梳理一下它的潜力吧

一、基础功能

  1. 触发方式多样:el-dropdown 支持多种触发方式,既可以 点击(click)也可以 悬停(hover),灵活得让你随心所欲!。
  2. 菜单项展示:使用 组件可以轻松展示多个菜单项,每个菜单项用 定义,简单高效!

二、交互功能

  1. 命令值传递:在<el-dropdown-item>上通过command属性设置命令值,当点击某个菜单项时,会触发command事件,并将命令值作为参数传递给事件处理函数。这允许开发者根据用户的选择执行相应的操作。
  2. 下拉菜单可见性变化监听:通过监听visible-change事件,可以获取下拉菜单的可见性状态变化,从而执行相应的逻辑,如动态加载数据等。

三、高级功能

  1. 当前项高亮:虽然Element的Dropdown组件本身没有直接提供当前项高亮的功能,但可以通过编程方式实现。例如,在表格中使用Dropdown时,可以根据当前行的数据动态设置菜单项的样式,从而实现高亮效果。
  2. 智能滚动定位:当菜单项过多导致出现滚动条时,可以通过编程方式实现智能滚动定位。例如,可以监听某个事件(如点击某个按钮或选中某个选项),然后自动滚动到指定的菜单项位置(比如每次打开下拉菜单时,滚动条滚到当前选中的那一项)。这可以通过操作DOM元素的滚动属性或使用Vue的ref属性来实现。
  3. 自定义内容:通过插槽(slot)机制,可以自定义Dropdown下拉菜单的内容,使其更加灵活和个性化。例如,可以在菜单项中嵌入图片、按钮或其他组件。
  4. 与后端交互:在点击菜单项时,可以触发与后端的交互操作,如发送请求获取数据或更新数据。这可以通过在handleCommand函数中编写相应的逻辑来实现。

今天主要是来唠唠第三项,Dropdown下拉菜单的高级功能

一、 当前项高亮实现

  1. 数据绑定

    • data函数中定义一个selectedCommand变量(变量名自定义,你爱叫啥叫啥),该变量用于存储当前选中的下拉菜单项的值。
    • 定义下拉框的数据(实际项目中从接口取)
data() { 
return { 
    selectedCommand: '', // 初始化selectedCommand变量
    //定义下拉框的数据(实际项目中从接口取)
    selectOptions: [ 
    { name: '选项1', value: 'option1' }, 
    { name: '选项2', value: 'option2' }, 
    { name: '选项3', value: 'option3' },
    { name: '选项4', value: 'option4' },
    { name: '选项5', value: 'option5' },
    { name: '选项6', value: 'option6' },
    // 更多选项... 
     ] 
    }; 
   },
  1. 模板中的条件类名
    • <el-dropdown-item>元素上使用:class绑定,根据selectedCommand与当前项的value是否相等来动态添加highlight(高亮的类名,名字随便取)类。
<el-dropdown-item
  v-for="(item, index) in selectOptions"
  :key="index"
  :command="item.value"
  :class="{ highlight: selectedCommand === item.value }"
>
  {{ item.name }}
  <!-- 其他内容 -->
</el-dropdown-item>

详解: :class="{ highlight: selectedCommand === item.value }"是一个对象,它告诉Vue,如果selectedCommand与当前项的item.value相等,则添加highlight类到<el-dropdown-item>元素上。

  1. 样式定义
    • <style>标签中定义.highlight类的高亮样式。当.highlight类被添加到某个<el-dropdown-item>元素上时,该元素就会应用这个样式,从而实现高亮效果。
.highlight { 
  background-color: #f0f0f0; /* 示例高亮背景色 */ 
   /* 可以添加其他高亮样式,比如字体颜色、边框等 */ 
    }
  1. 事件处理
    • 在el-dropdown标签上绑定@command事件,并调用方法例:(@command="handleCommand"
    • 当用户选择一个下拉菜单项时,handleCommand方法会被触发,并将选中的项的值赋给selectedCommand
//@command事件绑定方法
<el-dropdown @command="handleCommand">
......
</el-dropdown>
handleCommand(command) {
//把当前点击的项赋值给selectedCommand
  this.selectedCommand = command;
}

以上代码即可实现,当用户选择一个下拉菜单项时,selectedCommand会更新,对应的<el-dropdown-item>元素会根据:class绑定的条件应用.highlight类,从而实现当前项的高亮显示。

二、 智能滚动定位

实现智能滚动定位的步骤可以分为以下几个:

1. 处理下拉菜单可见性变化:

  • 给el-dropdown绑定@visible-change事件。
 <el-dropdown @command="handleCommand4" @visible-change="handleVisibleChange">
 ......
 </el-dropdown>
  • 在事件绑定的方法(例:handleVisibleChange)中,当下拉菜单显示时,调用滚动定位方法。
    handleVisibleChange (isVisible) {
      if (isVisible) {
        this.scrollToHighlightedItem()
      }
    },

2: 定义滚动定位方法

  • 创建一个方法(例如scrollToHighlightedItem),该方法会在下拉菜单显示时被调用。
//该方法会在下拉菜单显示时被调用。
scrollToHighlightedItem () {
      this.$nextTick(() => {
        const dropdownMenu = this.$refs.dropdownMenu.$el
        const highlightedItem = dropdownMenu.querySelector('.highlight')
        
        if (highlightedItem) {
            //console.log('highlightedItem.offsetTop:', highlightedItem.offsetTop); //打印的是`.highlight`元素的顶部边缘到其最近的具有定位属性的父元素(`offsetParent`)的顶部边缘的距离。如果没有任何定位的父元素,那么它将相对于整个文档的顶部边缘。
            //console.log('dropdownMenu.offsetTop:', dropdownMenu.offsetTop); //打印的是下拉菜单元素(`dropdownMenu`)的顶部边缘到其最近的具有定位属性的父元素(`offsetParent`)的顶部边缘的距离。同样,如果没有定位的父元素,那么它将相对于整个文档的顶部边缘。
            //console.log('dropdownMenu.scrollTop before:', dropdownMenu.scrollTop);//打印的是下拉菜单元素(`dropdownMenu`)的滚动条的当前位置。这个值表示从顶部边缘到当前可见内容顶部的距离。
    
            // 后面拼接的数字是高亮那些相对于下拉框顶部的距离
          dropdownMenu.scrollTop =highlightedItem.offsetTop - dropdownMenu.offsetTop + 110
        }
      })
    },

3: 设置下拉菜单最大高度,打开滚动条

.custom-dropdown-menu { 
  max-height: 300px; /* 设置最大高度 */ 
  overflow-y: auto; /* 启用垂直滚动条 */ 
    }

三、 自定义内容(通过插槽slot)

  • solt可以在菜单中插入图片,按钮,或者其他组件,我这里主要演示在菜单的每一项前面插入图片:
<template slot="icon"> 
    <img :src="你的图片路径" style="width: 24px; height: 24px;" alt="Item icon"> 
</template>

四、 与后端交互

  • 交互的逻辑直接写在上面的handleCommand函数里面就好,根据你的业务需求写逻辑

最后的完整代码

  • 这样,你的下拉菜单就拥有了智能高亮与滚动定位功能!以及可以自定义插槽和写交互逻辑啦!以下是完整的代码示例,随便复制使用!记得把图片路径换成你自己的
<template> 
<div> 
<el-dropdown 
@command="handleCommand" 
@visible-change="handleVisibleChange" 
> 
<span class="el-dropdown-link"> 
下拉菜单
<i class="el-icon-arrow-down el-icon--right"></i> </span> 
<el-dropdown-menu ref="dropdownMenu" class="custom-dropdown-menu"> 
<el-dropdown-item 
v-for="(item, index) in selectOptions" 
:key="index" 
:command="item.value" 
:class="{ highlight: selectedCommand === item.value }" 
> 
<template slot="icon"> 
    <img :src="你的图片路径" style="width: 24px; height: 24px;" alt="Item icon"> 
</template>
{{ item.name }} 
</el-dropdown-item> 
</el-dropdown-menu> 
</el-dropdown> 
</div> 
</template> 

<script> 
export default { 
data() { 
return { 
selectedCommand: '', // 初始化selectedCommand变量 
selectOptions: [ 
{ name: '选项1', value: 'option1' }, 
{ name: '选项2', value: 'option2' }, 
{ name: '选项3', value: 'option3' }, 
{ name: '选项4', value: 'option4' }, 
{ name: '选项5', value: 'option5' }, 
{ name: '选项6', value: 'option6' }, 
// 更多选项...
  ], 
 }; 
}, 
methods: { 
handleCommand(command) { 
// 把当前点击的项赋值给selectedCommand 
this.selectedCommand = command; 
//如需与后端交互的,可在这里根据你的业务需求写逻辑
}, 
handleVisibleChange(isVisible) { 
if (isVisible) { 
this.scrollToHighlightedItem(); 
 } 
}, 
scrollToHighlightedItem() { 
this.$nextTick(() => { 
const dropdownMenu = this.$refs.dropdownMenu.$el; 
const highlightedItem = dropdownMenu.querySelector('.highlight'); 
// 滚动到高亮项的位置,110是调整值,可以根据需要调整 
if (highlightedItem) { 
        //console.log('highlightedItem.offsetTop:', highlightedItem.offsetTop); //打印的是`.highlight`元素的顶部边缘到其最近的具有定位属性的父元素(`offsetParent`)的顶部边缘的距离。如果没有任何定位的父元素,那么它将相对于整个文档的顶部边缘。 
        //console.log('dropdownMenu.offsetTop:', dropdownMenu.offsetTop); //打印的是下拉菜单元素(`dropdownMenu`)的顶部边缘到其最近的具有定位属性的父元素(`offsetParent`)的顶部边缘的距离。同样,如果没有定位的父元素,那么它将相对于整个文档的顶部边缘。 
        //console.log('dropdownMenu.scrollTop before:', dropdownMenu.scrollTop);//打印的是下拉菜单元素(`dropdownMenu`)的滚动条的当前位置。这个值表示从顶部边缘到当前可见内容顶部的距离。 
    
        // 后面拼接的数字是高亮那些相对于下拉框顶部的距离
  dropdownMenu.scrollTop = highlightedItem.offsetTop - dropdownMenu.offsetTop + 110; 
     } 
   }); 
  }, 
 }, 
}; 
</script> 

<style scoped> 
.custom-dropdown-menu { 
    max-height: 300px; /* 设置最大高度 */ 
    overflow-y: auto; /* 启用垂直滚动条 */ 
    } 
.highlight { 
    background-color: #f0f0f0; /* 示例高亮背景色*/ 
    /* 可以添加其他高亮样式,比如字体颜色、边框等 */ 
} 

</style>

点击此到下拉菜单的官方文档

最后的最后,如果有什么问题可以直接评论或者私我哦