input式的下拉列表的东西
- 由于极其不爽这个input的下拉列表的样式所以自己写了一个
- 这个三角的东西是用的图片所以 自己弄一个上去吧
之前的那个有个bug, 就是它没有出来的时候都会档住下面的东西
其实还有一个思路就是改变外面边框的高度这样就不会在拉上去的时候挡住, 下面的东西
展示
不会档住的形式
- 核心思路就是将内部的bottom变换改成外面over-flow: hidden 的盒子的高度变化
DropDownList.vue
<template>
<div
class="drop-down-list"
:style = "getStyle"
ref = "drop"
@click = "dropDown"
>
{{value}}
<img
src="~assets/img/common/triangle.svg"
:class = "getClass"
class = "icon" alt="">
<div
class = "down-list"
:style = "getDropStyle"
ref = "downListOuter">
<div ref = 'downlist'
class = "list-in"
>
<list-item
v-for = "item in list"
:item = "item"
@itemClick = "itemClick"
:importance = "getImportance(item)">
<!-- 阻止事件冒泡 -->
</list-item>
</div>
</div>
</div>
</template>
<script>
import ListItem from './ListItem'
export default {
name: 'DropDownList',
data() {
return {
value: this.list[0],
isDown: false,
time: -1,
only: true,
dropDownHeight: "100px",
initHeight: ""
}
},
props: {
list: {
type: Array,
default () {
return [
"成都",
"北京",
"上海"
]
}
},
width: {
type: String,
default: "72%"
},
},
components: {
ListItem
},
mounted() {
console.log( "mounted: " + window.getComputedStyle(this.$refs.downlist).height )
this.dropDownHeight = window.getComputedStyle(this.$refs.downlist).height
},
methods: {
getImportance(item) {
console.log(this.value == item)
return this.value == item
},
itemClick(value) {
this.value = value
},
dropDown() {
// // 缓动动画
let n = 0.08
if( this.time != -1 ) {
clearInterval(this.time)
}
// if( this.only ) {
// this.only = false;
this.isDown = !this.isDown;
if( this.isDown ) {
this.$refs.downListOuter.style.zIndex = 0;
this.dropDownList(n)
} else {
this.dropUpList(n)
}
// }
},
dropDownList(n) {
// 正往下拉的情况
const downlist = this.$refs.downlist
const downListOuter = this.$refs.downListOuter
// 关闭上一个计时器
if( this.time != -1 ) {
clearInterval(this.time)
}
downlist.style.bottom = 0 + "px"
let index2;
if( this.initHeight == "" ) {
this.initHeight = this.getNumber(downListOuter.style.height);
console.log(this.initHeight)
}
let result2 = this.initHeight;
// 让下拉列表窗口的高度等于0
downListOuter.style.height = 0 + "px";
let index;
let result = 0;
this.time = setInterval( ()=>{
index = this.getNumber(downlist.style.bottom)
result = 0;
// downlist.style.bottom = index - (index - result) * n + "px";
index2 = this.getNumber(downListOuter.style.height);
downListOuter.style.height = index2 - (index2 - result2) * n + "px";
if( Math.abs(this.getNumber(downListOuter.style.height) - result2) < 0.1 ) {
clearInterval(this.time)
// downlist.style.bottom = result + "px";
downListOuter.style.height = result2 + "px";
}
} , 10 )
},
dropUpList(n) {
const downlist = this.$refs.downlist
const downListOuter = this.$refs.downListOuter
// 关闭上一个计时器
if( this.time != -1 ) {
clearInterval(this.time)
}
let index2;
let result2 = 0;
// 初始化高度 100%
let index;
let result = this.getNumber(downlist.parentElement.style.height);
this.time = setInterval( ()=>{
index = this.getNumber(downlist.style.bottom)
// downlist.style.bottom = index + (result - index) * n + "px";
index2 = this.getNumber(downListOuter.style.height);
downListOuter.style.height = index2 + (result2 - index2) * n + "px";
console.log("downListOuter.style.height", downListOuter.style.height)
if( Math.abs(downListOuter.style.height - result2) < 0.1 ) {
clearInterval(this.time)
downlist.style.bottom = result + "px";
downListOuter.style.height = result2 + "px";
this.$refs.downListOuter.style.zIndex = -10;
}
} , 10 )
},
getNumber( inputStr ) {
// 字符串转化成数字
return Number(inputStr.replace("px", ""))
}
},
computed: {
getStyle() {
return {
width: this.width,
}
},
getClass() {
return {
'rotate': this.isDown
}
},
getDropStyle() {
return {
height: this.dropDownHeight
}
}
}
}
</script>
<style scoped>
.drop-down-list {
position: relative;
display: flex;
justify-content: space-between;
border-radius: 5px;
padding: 5px 10px 5px 10px;
font-size: 16px;
border: 1px solid #ccc;
transition: all .5s;
}
.drop-down-list:hover {
outline: none;
box-shadow: 0 0px 15px skyblue;
}
.bg-red {
background-color: red;
}
.icon {
width: 20px;
margin-top: 3px;
transform: rotate(180deg);
transition: all 0.3s;
}
.rotate {
transform: rotate(0deg);
transform-origin: 50% 50%;
}
.down-list {
position: absolute;
top: calc(100% + 5px);
left: 0px;
width: 100%;
background-color: transparent;
z-index: -10;
overflow: hidden;
}
.list-in {
position: absolute;
bottom: 100%;
/* height: 100%; */
width: 100%;
padding: 10px 0px;
background-color: white;
border-radius: 0 0 5px 5px;
}
</style>
文件结构
DropDownList.vue
<template>
<div
class="drop-down-list"
:style = "getStyle"
ref = "drop"
@click = "dropDown"
>
{{value}}
<img
src="~assets/img/common/triangle.svg"
:class = "getClass"
class = "icon" alt="">
<div
class = "down-list"
:style = "getDropStyle"
ref = "downListOuter">
<div ref = 'downlist'
class = "list-in"
>
<list-item
v-for = "item in list"
:item = "item"
@itemClick = "itemClick"
:importance = "getImportance(item)">
<!-- 阻止事件冒泡 -->
</list-item>
</div>
</div>
</div>
</template>
<script>
import ListItem from './ListItem'
export default {
name: 'DropDownList',
data() {
return {
value: this.list[0],
isDown: false,
time: -1,
only: true,
dropDownHeight: "100px"
}
},
props: {
list: {
type: Array,
default () {
return [
"成都",
"北京",
"上海"
]
}
},
width: {
type: String,
default: "72%"
},
},
components: {
ListItem
},
mounted() {
console.log( "mounted: " + window.getComputedStyle(this.$refs.downlist).height )
this.dropDownHeight = window.getComputedStyle(this.$refs.downlist).height
},
methods: {
getImportance(item) {
console.log(this.value == item)
return this.value == item
},
itemClick(value) {
this.value = value
},
dropDown() {
// // 缓动动画
let n = 0.08
if( this.time != -1 ) {
clearInterval(this.time)
}
// if( this.only ) {
// this.only = false;
this.isDown = !this.isDown;
if( this.isDown ) {
this.$refs.downListOuter.style.zIndex = 0;
this.dropDownList(n)
} else {
this.dropUpList(n)
}
// }
},
dropDownList(n) {
// 正往下拉的情况
const downlist = this.$refs.downlist
// 关闭上一个计时器
if( this.time != -1 ) {
clearInterval(this.time)
}
// 初始化高度 100%不行
if( downlist.style.bottom == "" ) {
downlist.style.bottom = downlist.parentElement.style.height
}
let index;
let result = 0;
this.time = setInterval( ()=>{
index = this.getNumber(downlist.style.bottom)
result = 0;
downlist.style.bottom = index - (index - result) * n + "px";
if( Math.abs(this.getNumber(downlist.style.bottom) - result) < 0.1 ) {
clearInterval(this.time)
downlist.style.bottom = result + "px";
}
} , 10 )
},
dropUpList(n) {
const downlist = this.$refs.downlist
// 关闭上一个计时器
if( this.time != -1 ) {
clearInterval(this.time)
}
// 初始化高度 100%
let index;
let result = this.getNumber(downlist.parentElement.style.height);
this.time = setInterval( ()=>{
index = this.getNumber(downlist.style.bottom)
downlist.style.bottom = index + (result - index) * n + "px";
if( Math.abs(this.getNumber(downlist.style.bottom) - result) < 0.2 ) {
clearInterval(this.time)
downlist.style.bottom = result + "px";
this.$refs.downListOuter.style.zIndex = -10;
}
} , 10 )
},
getNumber( inputStr ) {
// 字符串转化成数字
return Number(inputStr.replace("px", ""))
}
},
computed: {
getStyle() {
return {
width: this.width,
}
},
getClass() {
return {
'rotate': this.isDown
}
},
getDropStyle() {
return {
height: this.dropDownHeight
}
}
}
}
</script>
<style scoped>
.drop-down-list {
position: relative;
display: flex;
justify-content: space-between;
border-radius: 5px;
padding: 5px 10px 5px 10px;
font-size: 16px;
border: 1px solid #ccc;
transition: all .5s;
}
.drop-down-list:hover {
outline: none;
box-shadow: 0 0px 15px skyblue;
}
.bg-red {
background-color: red;
}
.icon {
width: 20px;
margin-top: 3px;
transform: rotate(180deg);
transition: all 0.3s;
}
.rotate {
transform: rotate(0deg);
transform-origin: 50% 50%;
}
.down-list {
position: absolute;
top: calc(100% + 5px);
left: 0px;
width: 100%;
background-color: transparent;
z-index: -10;
overflow: hidden;
}
.list-in {
position: absolute;
bottom: 100%;
/* height: 100%; */
width: 100%;
padding: 10px 0px;
background-color: white;
border-radius: 0 0 5px 5px;
}
</style>
ListItem.vue
<template>
<div
class = "list-item"
@click = "itemClick(item)">
{{item}}
</div>
</template>
<script>
export default {
name: 'ListItem',
methods: {
itemClick(value) {
this.$emit("itemClick", value)
}
},
props: {
item: {
type: String,
default: "item"
}
}
}
</script>
<style scoped>
.list-item {
padding: 5px 10px;
}
.list-item:hover {
background-color: #F0F1F2;
}
</style>