更新: 使用 contains 方法来判断更简单,当前点击了B,如果 B元素是A元素的子节点,A.contains(B) 为true,B是A元素的子节点,否则反之。
利用事件委托的方法来实现,点击 input 输入框会冒泡到外面的盒子触发事件,先隐藏,再判断点击的元素是不是 input输入框,true 就让下拉框显示。
// select 组件
<template>
<div class="input">
<span> <slot></slot> </span>
<div class="input_inner_select">
<i class="triangle"></i>
<input type="text" class="inputSelect" readonly />
<ul ref="options">
<slot name="li"></slot>
</ul>
</div>
</div>
</template>
// 样式
<style lang="less">
.input_inner_select {
display: inline-block;
position: relative;
.inputSelect {
width: 200px;
height: 38px;
padding-left: 10px;
border: 1px solid #dcdfe6;
border-radius: 5px;
cursor: pointer;
}
ul {
display: none;
position: absolute;
left: 0px;
width: 100%;
max-height: 180px;
margin-top: 2px;
overflow-y: auto;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
z-index: 5;
li .iconfont {
color: #97c3ed;
vertical-align: middle;
margin-right: 4px;
}
li:hover {
background: #eff5fe;
}
}
}
.triangle {
position: absolute;
top: 45%;
right: 12px;
width: 5px;
height: 5px;
border-bottom: 1px solid #5a5a5a;
border-left: 1px solid #5a5a5a;
transform: translateY(-50%) rotate(-45deg);
}
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
height: 30px;
line-height: 30px;
}
input {
outline: none;
}
</style>
如果有时点击空白处没有隐藏下拉框,看看是不是没有点击在父组件的区域内
// 父组件
<template>
<div style="padding:50px" @click="clickShow">
<test>
选择框
<template slot="li">
<!-- 渲染 li -->
<li v-for="(li, i) in option" :key="i" :value="li.val">
{{ li.label }}
</li>
</template>
</test>
</div>
</template>
<script>
import test from "./components/test.vue";
export default {
data() {
return {
// 渲染数据
option: [
{ label: "1", val: "1" },
{ label: "2", val: "2" },
{ label: "3", val: "3" },
],
// 保存 ul 下拉框
sibling: null,
};
},
methods: {
// 给 父组件 添加事件
clickShow(e) {
this.showinputSelect(e.target);
},
// 这里我是想封装成一个全局方法,现在暂时放这
// 显示隐藏选择框
showinputSelect(node) {
if (this.sibling) this.sibling.style.display = "none";
if (node.className === "inputSelect") {
// 保存 ul 隐藏时就不需要获取了
this.sibling = node.nextSibling;
this.sibling.style.display = "block";
return;
} else {
this.sibling = null;
}
},
},
components: {
test,
},
};
</script>