内容简介:当选项过多时,使用下拉菜单展示并选择内容。代码实例地址:Select 实例
当选项过多时,使用下拉菜单展示并选择内容。
- 数据双向绑定,下拉列表变动时,选中项如何回显;
- 单选、多选的区分,以及对应处理。
1. 实例
代码
<fat-select v-model="inputValue"> <fat-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" >{{ item.label }}</fat-option> </fat-select> 复制代码
实例地址:Select 实例
代码地址: Github UI-Library
2. 原理
Select组件的基本结构如下
主要可分为两个部分:
- 显示框:用来展示已经选中项,包含取消按钮;
- 下拉框:包含已选中的高亮项,禁用项,默认选择选项等,具备点击选中,再次点击取消的操作;
- 确保每个下拉项唯一,即使存在相同 label 的情况。
fat-select 显示框:
<template> <div :class="['select-wrapper', { 'is-disabled': disabled }]" tabindex="0" @click.stop="isOpen = !disabled && !isOpen" @blur="handleBlur" > <div class="select-top-part"> <template v-if="!selectItems.length"> <span class="placeholder">{{ placeholder }}</span> </template> <template v-else> <div>{{ selectItems[0].label }}</div> </template> </div> <!-- 下拉框 --> <div class="select-bottom-part" v-show="isOpen"> <slot></slot> </div> </div> </template> <script> export default { props: { placeholder: { type: String, default: "请选择" }, optionKey: { type: String, default: "value" }, value: { type: [String, Object, Number, Array] } }, model: { prop: "value", event: "input" }, data() { return { isOpen: false, selectValue: [], selectItems: [] }; }, provide() { return { fatSelect: this }; }, watch: { value: { handler(value) { const { multiple } = this; const init = value ? value : multiple ? [] : ""; this.selectValue = multiple ? [...init] : init; }, immediate: true }, selectValue: { handler(value) { this.selectItems = []; } } }, methods: { handleDelete(item) { const { value } = item; this.selectValue = this.selectValue.filter(item => item !== value); this.$emit("input", this.selectValue); this.$emit("change", this.selectValue); }, handleBlur(event) { this.isOpen = false; this.$emit('blur', event); } ... } }; </script> 复制代码
利用 tabIndex
属性使得最外层的 div
能够触发 blur
事件,如果失焦就收起下拉框。
<div :class="['select-wrapper', { 'is-disabled': disabled }]" tabindex="0" @click.stop="isOpen = !disabled && !isOpen" @blur="handleBlur" > ... <!-- 下拉框 --> <div class="select-bottom-part" v-show="isOpen"> <slot></slot> </div> </div> handleBlur(event) { this.isOpen = false; this.$emit('blur', event); } 复制代码
组件实现数据双向绑定,当 v-model
对应的值变动时, Select 组件的值也会发生改变,但是显示框内所呈现的是选中项的 label
属性,所以将选中值 selectValue
和选中项 selectItems
进行区分。
同时配置 v-model
相关属性,同时监测 watch
相关 value
具体如下
model: { prop: "value", event: "input" }, watch: { value: { handler(value) { const { multiple } = this; const init = value ? value : multiple ? [] : ""; this.selectValue = multiple ? [...init] : init; }, immediate: true } } 复制代码
同时利用 provide
向其所有下拉框注入一个依赖,用于访问 selectValue
和 selectItems
等 prop 和 data 。
provide() { return { fatSelect: this }; } 复制代码
默认 optionKey: { type: String, default: "value" }
作为下拉项的唯一标识,默认值为 value ,也可自定义。
fat-option 下拉框:
利用插槽将下拉框插入 Select 组件中,其具体定义如下
<template> <div :class="['select-option-wrapper', { 'is-selected': isSelect }, { 'is-disabled': disabled }]" @click.stop="handleClick" > <slot></slot> </div> </template> <script> export default { props: { value: { type: [Object, String, Number], required: true }, label: { type: String }, disabled: { type: Boolean, defa: false } }, inject: ["fatSelect"], computed: { isSelect() { const { fatSelect: { optionKey, selectItems } } = this; const key = this[optionKey] || this.$attrs[optionKey]; return selectItems.find(item => item.key === key); } }, watch: { ["fatSelect.selectValue"]: { handler(newValue) { const { value, label, fatSelect: { optionKey, multiple, selectValue } } = this; const key = this[optionKey] || this.$attrs[optionKey]; if ( newValue === value || (Array.isArray(newValue) && newValue.find(item => item === value)) ) { if (!multiple) { this.fatSelect.selectItems = [ { key, label, value } ]; } else { this.fatSelect.selectItems.push({ key, label, value }); } } }, immediate: true } }, methods: { ... } }; </script> 复制代码
利用 inject: ["fatSelect"]
将上述 provide
的 Select 组件注入到当前选项中,
通过 this.fatSelect
来访问父组件的 selectItems
来判断,当前选项是否为选中项。
isSelect() { const { fatSelect: { optionKey, selectItems } } = this; const key = this[optionKey] || this.$attrs[optionKey]; return selectItems.find(item => item.key === key); } 复制代码
同时watch fatSelect.selectValue
也就是选中值,之前说过该组件实现数据的双向绑定,当 Select 组件 v-model
绑定的值变动时,需要同步到下拉项。
["fatSelect.selectValue"]: { handler(newValue) { const { value, label, fatSelect: { optionKey, multiple, selectValue } } = this; const key = this[optionKey] || this.$attrs[optionKey]; if ( newValue === value || (Array.isArray(newValue) && newValue.find(item => item === value)) ) { if (!multiple) { this.fatSelect.selectItems = [ { key, label, value } ]; } else { this.fatSelect.selectItems.push({ key, label, value }); } } }, immediate: true } 复制代码
如果对应的 fatSelect.selectValue
变动时,要判断当前选项的 optionKey
是否在 selectValue
中,如果存在,就将
this.fatSelect.selectItems = [ { key, label, value } ]; 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 从零实现Vue的组件库(二)-Slider组件实现
- Vue自定义组件(简单实现一个自定义组件)
- 实现一个沙漏⏳组件
- angular 实现下拉列表组件
- 从零实现Vue的组件库(五)- Breadcrumb 实现
- 从零实现Vue的组件库(十二)- Table 实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
程序设计方法(中文版)
Matthias Fellisen / 黄林鹏、朱崇恺 / 人民邮电出版社 / 2003-12 / 49.00元
《程序设计方法》以Scheme语言为基础介绍计算和程序设计的一般理论和实践。《程序设计方法》由8个部分和7个独立的章节(第8、13、18、24、29、33、38章)组成。8个部分主要讨论程序设计,独立章节则介绍一些与程序设计和计算相关的话题。《程序设计方法》第1至第3部分介绍了基于数据驱动的程序设计基础。第4部分介绍了程序设计中的抽象问题。第5部分和第6部分是与递归及累积相关的内容。《程序设计方法......一起来看看 《程序设计方法(中文版)》 这本书的介绍吧!