Vue3选择器(Select)

该组件已发布到npm,使用时直接安装即可:yarn add vue-amazing-selector

// global use
import Vue from 'vue'
import VueAmazingSelector from 'vue-amazing-selector'
Vue.use(VueAmazingSelector)// local use
import { VueAmazingSelector } from 'vue-amazing-selector'
export default {components: {VueAmazingSelector}
}

可自定义设置以下属性:

  • 选项数据(options),类型:Array,默认值[]

  • 选择器字典项的文本字段名(label),类型:string,默认 'label'

  • 选择器字典项的值字段名(value),类型:string,默认 'value'

  • 选择框默认文字(placeholder),类型:string,默认 '请选择'

  • 是否禁用下拉(disabled),类型:boolean,默认 false

  • 是否支持清除(allowClear),类型:boolean,默认false

  • 选择框宽度(width),类型:number,默认200px

  • 选择框高度(height),类型:number,默认36px

  • 下拉面板最多能展示的下拉项数,超过后滚动显示(num),类型:number,默认 6

  • 当前选中的option条目(selectedValue)v-model,类型:string | number,默认 null

效果图如下:

展开图如下:

①创建选择器组件VueAmazingSelector.vue:

<template><div class="m-amazing-select" :style="`height: ${height}px;`"><div:class="['m-select-wrap', {'hover': !disabled, 'focus': showOptions, 'disabled': disabled}]":style="`width: ${width - 2}px; height: ${height - 2}px;`"tabindex="0"@mouseenter="onInputEnter"@mouseleave="onInputLeave"@blur="activeBlur && !disabled ? onBlur() : e => e.preventDefault()"@click="disabled ? e => e.preventDefault() : openSelect()"><div:class="['u-select-input', {'placeholder': !selectedName}]":style="`line-height: ${height - 2}px;width: ${width - 37}px; height: ${height - 2}px;`":title="selectedName">{{ selectedName || placeholder }}</div><svg :class="['triangle', {'rotate': showOptions, 'show': !showClose}]" viewBox="64 64 896 896" data-icon="down" aria-hidden="true" focusable="false"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg><svg @click.stop="onClear" :class="['close', {'show': showClose}]" focusable="false" data-icon="close-circle" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></div><transition name="fade"><divv-show="showOptions"class="m-options-panel"@mouseenter="onEnter"@mouseleave="onLeave":style="`top: ${height + 6}px; line-height: ${height - 12}px; max-height: ${ num * (height - 2) }px; width: ${width}px;`"><pv-for="(option, index) in options" :key="index":class="['u-option', {'option-selected': option[label]===selectedName, 'option-hover': !option.disabled&&option[value]===hoverValue, 'option-disabled': option.disabled }]":title="option[label]"@mouseenter="onHover(option[value])"@click="option.disabled ? e => e.preventDefault() : onChange(option[value], option[label], index)">{{ option[label] }}</p></div></transition></div>
</template>
<script>
export default {name: 'VueAmazingSelector',model: {prop: 'selectedValue',event: 'model'},props: {options: { // 选项数据type: Array,default: () => []},label: { // 选择器字典项的文本字段名type: String,default: 'label'},value: { // 选择器字典项的值字段名type: String,default: 'value'},placeholder: { // 选择框默认文字type: String,default: '请选择'},disabled: { // 是否禁用下拉type: Boolean,default: false},allowClear: { // 是否支持清除type: Boolean,default: false},width: { // 选择框宽度type: Number,default: 200},height: { // 选择框高度type: Number,default: 36},num: { // 下拉面板最多能展示的下拉项数,超过后滚动显示type: Number,default: 6},selectedValue: { // 当前选中的option条目(v-model)type: [Number, String],default: null}},data () {return {selectedName: null,hoverValue: null, // 鼠标悬浮项的value值activeBlur: true, // 是否激活blur事件showClose: false, // 清除按钮显隐showOptions: false // options面板}},watch: {options () {this.initSelector()console.log('options')},selectedValue () {this.initSelector()console.log('selectedValue')}},mounted () {this.initSelector()},methods: {initSelector () {if (this.selectedValue) {const target = this.options.find(option => option[this.value] === this.selectedValue)if (target) {this.selectedName = target[this.label]this.hoverValue = target[this.value]} else {this.selectedName = this.selectedValuethis.hoverValue = null}} else {this.selectedName = nullthis.hoverValue = null}},onBlur () {if (this.showOptions) {this.showOptions = false}},onInputEnter () {// console.log('input enter')if (this.allowClear && this.selectedName) {this.showClose = true}},onInputLeave () {// console.log('input leave')if (this.allowClear && this.showClose) {this.showClose = false}},onHover (value) {this.hoverValue = value},onEnter () {this.activeBlur = false},onLeave () {this.hoverValue = nullthis.activeBlur = true},openSelect () {this.showOptions = !this.showOptionsif (!this.hoverValue && this.selectedName) {const target = this.options.find(option => option[this.label] === this.selectedName)this.hoverValue = target ? target[this.value] : null}},onClear () {this.showClose = falsethis.selectedName = nullthis.hoverValue = null},onChange (value, label, index) { // 选中下拉项后的回调if (this.selectedValue !== value) {this.selectedName = labelthis.hoverValue = valuethis.$emit('model', value)this.$emit('change', value, label, index)}this.showOptions = false}}
}
</script>
<style lang="less" scoped>
@themeColor: #1890ff; // 自定义主题色
P {margin: 0;
}
.m-amazing-select {position: relative;display: inline-block;font-size: 14px;font-weight: 400;color: rgba(0,0,0,.65);
}
.fade-enter-active, .fade-leave-active {transform: scaleY(1);transform-origin: 0% 0%;opacity: 1;transition: all .3s;
}
.fade-enter {transform: scaleY(0.8);transform-origin: 0% 0%;opacity: 0;
}
.fade-leave-to {transform: scaleY(1);opacity: 0;
}
.m-select-wrap {position: relative;display: inline-block;border: 1px solid #d9d9d9;border-radius: 4px;cursor: pointer;transition: all .3s cubic-bezier(.645,.045,.355,1);.u-select-input {display: block;text-align: left;margin-left: 11px;margin-right: 24px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}.placeholder {color: #bfbfbf;}.triangle {position: absolute;top: 0;bottom: 0;margin: auto 0;right: 12px;width: 12px;height: 12px;fill: rgba(0,0,0,.25);opacity: 0;pointer-events: none;transition: all 0.3s ease-in-out;}.rotate {transform: rotate(180deg);-webkit-transform: rotate(180deg);}.close {opacity: 0;pointer-events: none;transition: all 0.3s ease-in-out;position: absolute;top: 0;bottom: 0;margin: auto 0;right: 12px;width: 12px;height: 12px;fill: rgba(140, 140, 140, 0.6);&:hover {fill: rgba(100, 100, 100,.8);}}.show {opacity: 1;pointer-events: auto;}
}
.hover { // 悬浮时样式&:hover {border-color: @themeColor;}
}
.focus { // 激活时样式border-color: @themeColor;box-shadow: 0 0 0 2px fade(@themeColor, 20%);
}
.disabled { // 下拉禁用样式color: rgba(0,0,0,.25);background: #f5f5f5;user-select: none;cursor: not-allowed;
}
.m-options-panel {position: absolute;z-index: 999;overflow: auto;background: #FFF;padding: 4px 0;border-radius: 4px;box-shadow: 0 2px 8px rgba(0,0,0,15%);.u-option { // 下拉项默认样式text-align: left;position: relative;display: block;padding: 5px 12px;font-weight: 400;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;cursor: pointer;transition: background .3s ease;}.option-selected { // 被选中的下拉项样式font-weight: 600;background: #fafafa;}.option-hover { // 悬浮时的下拉项样式// background: #e6f7ff;background: saturate(fade(@themeColor, 12%), 30%);}.option-disabled { // 禁用某个下拉选项时的样式color: rgba(0,0,0,.25);user-select: none;cursor: not-allowed;}
}
</style>

②在要使用的页面引入:

<VueAmazingSelector:options="options"label="label"value="value"placeholder="请选择城市":disabled="false":width="160":height="36":num="6"allowClearv-model="selectedValue"@change="onChange" />
data () {return {options: [{label: '北京市',value: 1},{label: '上海市上海市上海市上海市',value: 2,disabled: true},{label: '郑州市',value: 3},{label: '纽约市纽约市纽约市纽约市',value: 4},{label: '旧金山',value: 5},{label: '悉尼市',value: 6},{label: '伦敦市',value: 7},{label: '巴黎市',value: 8}],selectedValue: 1}
},
watch: {selectedValue (to) {console.log('selectedValue:', to)}
},
mounted () {setTimeout(() => { // 模拟接口调用this.selectedValue = 3}, 1000)
},
methods: {onChange (value, label, index) {console.log('item:', value, label, index)}
}

Vue2选择器(Select)相关推荐

  1. CSS选择器(select)

    ■开发中经常需要找到特定的网页元素进行        ■什么是css选择器 设置样式                       □按照一定的规则选出符合的元素,为之添加css样式 ■思考:如何找到特 ...

  2. Python爬虫实例(3)--BeautifulSoup的CSS选择器

    Python爬虫实例 紧接着上一讲的内容. 我们初步了解了bs4这个解析库. 但是bs4难道只有find,find_all了吗? 如果层次比较深,相似的元素比较多,和可能会写的比较长. 最主要的是很难 ...

  3. vue项目架构搭建-3

    前言 在前面两篇文章中已经把基础工作环境构建完成,也已经把后台核心的登录和权限问题完成了,现在手摸手,一起进入实操. Element 去年十月份开始用 vue 做管理后台的时候毫不犹豫的就选择了 el ...

  4. 以下用于数据存储领域的python第三方库是-『爬虫四步走』手把手教你使用Python抓取并存储网页数据!...

    第一步:尝试请求 首先进入b站首页,点击排行榜并复制链接 https://www.bilibili.com/ranking?spm_id_from=333.851.b_7072696d61727950 ...

  5. python爬虫获取的网页数据为什么要加[0-python爬虫解析页面数据的三种方式

    re模块 re.S表示匹配单行 re.M表示匹配多行 使用re模块提取图片url,下载所有糗事百科中的图片 普通版 import requests import re import os if not ...

  6. python爬虫详细步骤-Python爬虫的两套解析方法和四种爬虫实现过程

    对于大多数朋友而言,爬虫绝对是学习 python 的最好的起手和入门方式.因为爬虫思维模式固定,编程模式也相对简单,一般在细节处理上积累一些经验都可以成功入门.本文想针对某一网页对 python 基础 ...

  7. NIO中的SelectionKey

    转载自: 秦汉邮侠 https://www.jianshu.com/p/d33f2f6cdba0 要点 是一个抽象类,表示selectableChannel在Selector中注册的标识.每个Chan ...

  8. 【Python基础】Python爬虫的两套解析方法和四种信息提取方式

    Python爬虫 Author:Iouwill Machine Learning Lab 分享一篇往日旧文章,非常实用. 对于大多数朋友而言,爬虫绝对是学习python的最好的起手和入门方式.因为爬虫 ...

  9. 『爬虫四步走』手把手教你使用Python抓取并存储网页数据!

    爬虫是Python的一个重要的应用,使用Python爬虫我们可以轻松的从互联网中抓取我们想要的数据,本文将基于爬取B站视频热搜榜单数据并存储为例,详细介绍Python爬虫的基本流程.如果你还在入门爬虫 ...

最新文章

  1. Java获取系统日期时间
  2. java 中启动线程的正确方式
  3. 怎么利用计算机计算潮流计算,电力系统潮流计算的目的是什么
  4. 沃尔沃挖机计算机故障,沃尔沃挖掘机常见故障及原因总结,用户们可以看看
  5. 万用表怎么测量电池容量_万用表检测光电耦合器的常用技巧
  6. Bootstrap 高亮某个菜单项
  7. 23、90秒快速“读懂”STP(生成树)工作原理
  8. 2014025675 《嵌入式系统程序设计》第七周学习总结
  9. Asp.net Core之TagHelper
  10. 手机游戏上线前的准备
  11. 【过关斩将】如何制作高水平简历-原则篇
  12. 凸优化(一)绪论与凸集
  13. 联想的高清壁纸蛮不错的,速提!
  14. python基础知识补充
  15. 计算机视觉领域常见期刊和会议
  16. mysql dba工具_Github推荐:MySQL DBA不可错过的五大开源管理工具!
  17. 关于Linux的那些事儿--系统状态检测命令
  18. 国内首家,阿里云发布Redis全球多活版
  19. 整站优化提升排名工具_百度快速排名教程【常见问题】
  20. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递

热门文章

  1. uni-app和微信原生小程序的工具请求文件
  2. word中更改表格的边框粗细
  3. 京东众筹双色球中奖号计算方法
  4. 最全自学黑客技术学习路线,少走弯路
  5. iwebshop 0.9.2发布 新增运费模板功能
  6. 先出报表还是先计提所得税_先结转损益还是先计提所得税
  7. Tableau可视化(神仙般绘图)——糖潮丽子的博客
  8. 史上最污技术解读,让你秒懂IT术语(转载)
  9. Android WebView 加载网页只显示空白页不显示网页
  10. pytorch 图像预处理之减去均值,除以方差