drop-down.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <template>
  2. <div class="dropdown-item">
  3. <!-- selected -->
  4. <view :class="['dropdown-item__selected',listWidth!='150rpx'?'dropdown-item__right':'dropdown-item__left']"
  5. @click="changePopup" :style="{maxWidth:selectWidth}">
  6. <view class="selected__name">{{selectItem.text}}</view>
  7. <view class="selected__icon"
  8. :class="showClass === 'show'? 'up' : 'down'"
  9. >
  10. <li class="iconfont icon-caretdown"></li>
  11. </view>
  12. </view>
  13. <view class="dropdown-item__content" :style="{top: contentTop + 'rpx'}" v-if="showList">
  14. <!-- dropdown -->
  15. <view :class="['list', showClass]" :style="{left: contentLeft>0?contentLeft + 'rpx':'auto',right: contentRight>0?contentRight + 'rpx':'auto',}">
  16. <view class="list__option"
  17. v-for="(item, index) in list" :key="index"
  18. @click="choose(item)">
  19. <view>{{item.text}}</view>
  20. <icon v-if="item.value === value" type="success_no_circle" size="20"/>
  21. </view>
  22. </view>
  23. <!-- dropdown-mask -->
  24. <view :class="['dropdown-mask', showClass]" v-if="showList" @click="closePopup"></view>
  25. </view>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. components: {
  31. },
  32. props: {
  33. value: [Number, String, Object],
  34. list: {
  35. type: Array,
  36. default: ()=> {
  37. return []
  38. }
  39. },
  40. contentTop:{
  41. type:String,
  42. default:"185"
  43. },
  44. contentLeft:{
  45. type:String,
  46. default:"0"
  47. },
  48. contentRight:{
  49. type:String,
  50. default:"0"
  51. },
  52. listWidth:{
  53. type:String,
  54. default:'150rpx'
  55. },
  56. selectWidth:{
  57. type:String,
  58. default:'150rpx'
  59. }
  60. },
  61. data() {
  62. return {
  63. showList: "",
  64. showClass: '',
  65. selectItem: {},
  66. }
  67. },
  68. watch: {
  69. list(newVal,oldVal){
  70. this.selectItem = newVal[0];
  71. }
  72. },
  73. mounted() {
  74. this.showList = this.active;
  75. this.selectItem = this.list[0];
  76. },
  77. methods: {
  78. choose(item) {
  79. if(item.value != "auto"){
  80. this.selectItem = item
  81. }
  82. this.$emit('changeItem', item);
  83. this.closePopup();
  84. },
  85. selectAuto(){
  86. this.selectItem = {text: '指定日期',value: 'auto'};
  87. },
  88. changePopup() {
  89. if(this.showList) {
  90. this.closePopup()
  91. } else {
  92. this.openPopup()
  93. }
  94. },
  95. openPopup() {
  96. setTimeout(() => {
  97. this.showClass = 'show';
  98. this.showList = true;
  99. }, 100);
  100. },
  101. closePopup() {
  102. this.showClass = ''
  103. setTimeout(() => {
  104. this.showList = false
  105. }, 200);
  106. },
  107. close() {
  108. this.showClass = ''
  109. this.showList = false
  110. },
  111. }
  112. }
  113. </script>
  114. <style lang="scss">
  115. li{
  116. list-style-type:none;
  117. }
  118. .dropdown-item__content{
  119. z-index: 10!important;
  120. }
  121. .dropdown-item {
  122. width: 100%;
  123. flex:1;
  124. position: relative;
  125. &__selected {
  126. position: relative;
  127. padding: 10rpx 0;
  128. box-sizing: border-box;
  129. color: #fff;
  130. .selected__name {
  131. font-size: 28rpx;
  132. text-overflow: ellipsis;
  133. white-space: nowrap;
  134. overflow: hidden;
  135. }
  136. .selected__icon {
  137. margin-left: 20rpx;
  138. &.down {
  139. transition: transform .3s;
  140. transform: rotateZ(0);
  141. }
  142. &.up {
  143. transition: transform .3s;
  144. transform: rotateZ(-180deg);
  145. }
  146. }
  147. }
  148. &__left{
  149. display: flex;
  150. flex-direction: row;
  151. justify-content: flex-start;
  152. align-items: center;
  153. }
  154. &__right{
  155. display: flex;
  156. flex-direction: row;
  157. justify-content: flex-end;
  158. align-items: center;
  159. }
  160. &__content {
  161. position: fixed;
  162. left: 0;
  163. right: 0;
  164. overflow: hidden;
  165. top: 0;
  166. bottom: 0;
  167. z-index: 1;
  168. .list {
  169. max-height: 400px;
  170. text-align: center;
  171. overflow-y: auto;
  172. position: absolute;
  173. z-index: 1200;
  174. background: #fff;
  175. transform: translateY(-100%);
  176. transition: all .3s;
  177. &.show {
  178. transform: translateY(0);
  179. }
  180. &__option {
  181. font-size:30rpx;
  182. padding: 18rpx;
  183. display: flex;
  184. justify-content: space-between;
  185. color: #303133;
  186. &:not(:last-child) {
  187. border-bottom: 1rpx solid #DDDDDD;
  188. }
  189. }
  190. }
  191. .dropdown-mask {
  192. position: absolute;
  193. left: 0;
  194. right: 0;
  195. top: 0;
  196. bottom: 0;
  197. transition: all .3s;
  198. z-index: 1100;
  199. &.show {
  200. background:rgba(0,0,0,0.5);
  201. }
  202. }
  203. }
  204. &:not(:last-child):after {
  205. content: ' ';
  206. position: absolute;
  207. width: 2rpx;
  208. top: 36rpx;
  209. bottom: 36rpx;
  210. right: 0;
  211. background: $uni-border-color;
  212. }
  213. }
  214. </style>