简介
级联选择器,如下图,也是一种常用的组件,这个组件会比较复杂一点
main.vue
和
menu.vue
2个文件,前者代表输入框部分,后者代表下方的级联选择部分,以及附加的js文件popper.js以及vue.popper.js,用来处理弹出框逻辑,前面文章介绍过,这4个文件总代码量2000行左右,首先要明确,Element中把弹出框的逻辑分离出去了,放在专门的popper.js中,因为许多组件都要用到该弹出框。该组件官网代码
点此
级联选择器输入框的html结构
先来看main.vue
中的html结构,main.vue
代表输入框部分,简化后的html结构如下
<span class="el-cascader">
<el-input>
<template slot="suffix">
<i v-if></i>
<i v-else></i>
</template>
</el-input>
<span class="el-cascader__label">
...
</span>
</span>
复制代码
结构很简单,最外层一个span包裹所有元素,该span相对定位且inline-block,里面是一个<el-input>
输入框组件,该输入框用来搜索目标内容(内容就是级联选择器的data),然后<el-input>
里面一个template作为插槽存放了2个i标签,注意这里的slot="suffix"
这是将这2个i标签作为具名插槽的内容插入<el-input>
中的对应位置,带表了下箭头和清空输入框的按钮。然后是一个span,这个span就是下图中输入框内的文字
是不是没有发现下拉菜单的html结构?因为下拉菜单是挂载在document.body上的,通过popper.js来控制,所以结构被分离出去了
级联选择器输入框的代码分析
先来看最外层span的代码
<span
class="el-cascader"
:class="[
{
'is-opened': menuVisible,
'is-disabled': cascaderDisabled
},
cascaderSize ? 'el-cascader--' + cascaderSize : ''
]"
@click="handleClick"
@mouseenter="inputHover = true"
@focus="inputHover = true"
@mouseleave="inputHover = false"
@blur="inputHover = false"
ref="reference"
v-clickoutside="handleClickoutside"
@keydown="handleKeydown"
>
复制代码
作为组件最外层的span,其功能主要就是点击之后会弹出/隐藏下拉框,前面class部分就是控制该输入框是否禁用的样式,is-opened
这个类很奇怪,源码里没有,而且审查元素也发现该类是空,menuVisible
是组件内data中的变量,控制是否显示下拉菜单,自然可以想到,下面的@click="handleClick"
中有控制该变量的代码,该方法如下
handleClick() {
if (this.cascaderDisabled) return;
this.$refs.input.focus();
if (this.filterable) {
this.menuVisible = true;
return;
}
this.menuVisible = !this.menuVisible;
},
复制代码
首先判断组件是否禁用,如果禁用则直接返回,第二句this.$refs.input.focus()
是获取到该组件内的<el-input>
并让其获得焦点,focus是原生用法,注意这里默认状态下组件内的输入框是readonly只读的,只有在开启了搜索状态下才能获得焦点,而开启搜索由filterable
这个prop控制,用户传入,<el-input>
上:readonly="readonly"
这句话就是控制只读的,readonly是个计算属性,如下
readonly() {
const isIE = !this.$isServer && !isNaN(Number(document.documentMode));
return !this.filterable || (!isIE && !this.menuVisible);
}
复制代码
这里首先判断是不是ie浏览器,首先判断是不是服务端渲染,如果是则直接返回false,然后这句话!isNaN(Number(document.documentMode)
就可以很轻松的判断是否是ie,之前我记得一般是用navigator.userAgent.indexOf("MSIE")>0
来判断的,documentMode是一个ie特有属性
document.documentMode!==undefined
来判断呢这里不明白,难道是怕undefined不是真正的undefined?因为undefined可以被修改。继续看return逻辑,如果是开启搜索状态(filterable为true,那么一般情况下输入框readonly