Dropdown.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <div class="dropdown pre">
  3. <!-- 触发区 -->
  4. <div @click.stop="visible = true" class="dropdown-trigger">
  5. <slot></slot>
  6. </div>
  7. <!-- 遮罩 -->
  8. <div class="pfi" @click="visible = false" v-if="visible" :style="[maskStyle]"></div>
  9. <!-- 下拉菜单 -->
  10. <template v-if="visible">
  11. <div :class="['dropdown-menu pab', visible ? 'animation-fade' : '']" :style="[dropdownMenuStyle]">
  12. <slot name="dropdown-menu">
  13. <template v-if="list.length">
  14. <div :class="['dropdown-menu-item tc', {line: index !== 0, active: isActvie && item[defaultprop.value] === value}]" :style="isActvie && item[defaultprop.value] === value ? activeStyle : {}" v-for="(item, index) in list" :key="item[defaultprop.value]" @click="change(item)">
  15. <span class="menu-name">{{ item[defaultprop.label] }}</span>
  16. </div>
  17. </template>
  18. </slot>
  19. </div>
  20. </template>
  21. </div>
  22. </template>
  23. <script>
  24. export default {
  25. name: 'dropdown',
  26. props: {
  27. // 下拉框数据
  28. list: {
  29. type: Array,
  30. default: () => {
  31. return []
  32. }
  33. },
  34. // 替换回显以及key字段
  35. prop: {
  36. type: Object,
  37. default: () => {
  38. return {}
  39. }
  40. },
  41. dropdownMenuStyle: {
  42. type: Object,
  43. default: () => {
  44. return {}
  45. }
  46. },
  47. value: {
  48. type: [String, Number],
  49. default: ''
  50. },
  51. // 下拉菜单是否激活选中项
  52. isActvie: {
  53. type: Boolean,
  54. default: false
  55. },
  56. // 下拉菜单选中时的样式
  57. activeStyle: {
  58. type: [Object, Array],
  59. default: () => ({})
  60. }
  61. },
  62. data() {
  63. return {
  64. // 下拉框及遮罩是否显示
  65. visible: false,
  66. // 默认的prop
  67. defaultprop: {
  68. label: 'label',
  69. icon: 'icon',
  70. value: 'value'
  71. },
  72. // 屏幕高度
  73. windowHeight: 0,
  74. }
  75. },
  76. mounted() {
  77. // 获取屏幕高度
  78. this.windowHeight = window.innerHeight;
  79. // 如果有自定义的prop,那么就直接替换
  80. if (Object.keys(this.prop).length) Object.assign(this.defaultprop, this.prop)
  81. },
  82. watch: {
  83. visible(val) {
  84. // 监听visible的变化
  85. this.$emit('visible', val)
  86. }
  87. },
  88. computed: {
  89. maskStyle() {
  90. return {
  91. height: this.windowHeight + 'px',
  92. width: '100vw'
  93. }
  94. }
  95. },
  96. methods: {
  97. change(data) {
  98. this.visible = false
  99. this.$emit('input', data[this.defaultprop.value])
  100. this.$emit('change', data[this.defaultprop.value])
  101. }
  102. }
  103. }
  104. </script>
  105. <style lang="scss" scoped>
  106. .pre {
  107. position: relative;
  108. }
  109. .pab {
  110. position: absolute;
  111. }
  112. .dropdown-menu {
  113. min-width: 120px;
  114. background-color: #2C2C2D;
  115. box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
  116. animation-duration: .2s !important;
  117. z-index: 2501;
  118. padding: 0 12px;
  119. font-family: PingFangSC, PingFang SC;
  120. font-weight: 400;
  121. font-size: 14px;
  122. color: #FFF;
  123. line-height: 18px;
  124. text-align: left;
  125. font-style: normal;
  126. border-radius: 8px;
  127. .dropdown-menu-item {
  128. display: flex;
  129. align-items: center;
  130. padding: 12px 0;
  131. .menu-name {
  132. flex: 1;
  133. }
  134. }
  135. }
  136. .pfi {
  137. left: 0px;
  138. top: 0px;
  139. z-index: 2500;
  140. background-color: rgba(0, 0, 0, .5);
  141. position: fixed;
  142. }
  143. .active {
  144. color: #3666F2;
  145. }
  146. </style>