简介
Element的下拉选择器示意图如下
确实做的很漂亮,交互体验非常好,html有原生的选择器<select>
,但是太丑了,而且各浏览器样式不统一,因此要做一个漂亮且实用的下拉选择器必须自己模拟全部方法和结构,Element的下拉选择器代码量非常大,仅
select.vue
一个文件就快1000行,而且里面是由Element的其他组件组合而成,算上其他组件的话,又得加上1000行,最后是这个选择器引用了非常多的util以及第三方js,再加上这些至少得再加2000行,所以只能分析部分核心原理,下面是下拉选择器的import
import Emitter from 'element-ui/src/mixins/emitter';
import Focus from 'element-ui/src/mixins/focus';
import Locale from 'element-ui/src/mixins/locale';
import ElInput from 'element-ui/packages/input';
import ElSelectMenu from './select-dropdown.vue';
import ElOption from './option.vue';
import ElTag from 'element-ui/packages/tag';
import ElScrollbar from 'element-ui/packages/scrollbar';
import debounce from 'throttle-debounce/debounce';
import Clickoutside from 'element-ui/src/utils/clickoutside';
import { addClass, removeClass, hasClass } from 'element-ui/src/utils/dom';
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
import { t } from 'element-ui/src/locale';
import scrollIntoView from 'element-ui/src/utils/scroll-into-view';
import { getValueByPath } from 'element-ui/src/utils/util';
import { valueEquals } from 'element-ui/src/utils/util';
import NavigationMixin from './navigation-mixin';
import { isKorean } from 'element-ui/src/utils/shared';
复制代码
不过这些import里面很多东西是值得学习的,官网代码点此
下拉选择器的html结构
还是先来分析这个下拉选择器的html结构,简化后的html代码如下
<template>
<div class="el-select" >
<div class="el-select__tags"
</div>
<el-input></el-input>
<transition>
<el-select-menu>
<el-select-menu>
</transtion>
</div>
</template>
复制代码
最外层一个div包裹所有子元素(相对定位),里面第一个div是展示下拉选择器的tag的包裹div,如下图,这个div绝对定位,然后通过top:50%;transform:translateY(-50%)
垂直居中于最外层的div内
然后第二个<el-input>
是Element封装的输入组件,前面文章介绍过,这个输入框宽度和最外层的div一样,如下图,右侧的箭头按钮是放在其padding位置上
<transtion>
不是组件,是Vue的过渡动画的标志,不会渲染出来,里面包裹着
<el-select-menu>
这也是Element封装的组件,表示弹出的下拉菜单,也是绝对定位,
所以整个下拉组件只有中间的input是相对定位,其他都是绝对定位,而且要善于复用自己已有的组件,而不是又重头写
部分功能源码分析
如果要写完所有功能,那至少得一周以上,所以只能写一部分
下拉框主体操作流程逻辑梳理
下面分析下下拉框主体操作流程以及其中的数据传递过程
首先看下下拉框的用法,官网代码如下
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
复制代码
数据部分如下
<script>
export default {
<