my-select.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <view
  3. class="input"
  4. :style="isActive? {...activeStyle}: ''"
  5. @click.stop="openList"
  6. >
  7. <!-- 文字显示区 -->
  8. <view
  9. class="select-text"
  10. :style="{
  11. color: (placeholder? '#606266': '#bbb')
  12. }">
  13. {{ selectText || initValue || placeholder }}
  14. </view>
  15. <!-- 图标 -->
  16. <view
  17. class="icon"
  18. :class="isActive? 'animate-open-rotate': 'animate-close-rotate'"
  19. >
  20. <uni-icons
  21. :type="rightIcon"
  22. :size="rightIconSize"
  23. :color="rightIconColor">
  24. </uni-icons>
  25. </view>
  26. <!-- 展示列表 -->
  27. <view
  28. v-if="isActive"
  29. class="list-wrap"
  30. :class="isActive? 'fadeShow': 'fadeHidden'"
  31. >
  32. <!-- 特殊格式长*宽*高 -->
  33. <view class="list" v-if="itemFormat == '*'" :style="{height: `${list.length * itemHeight}rpx`}">
  34. <view
  35. class="item"
  36. :style="{...(item.selected? itemActive: {}),height: `${itemHeight}rpx`,lineHeight: `${itemHeight}rpx`}"
  37. v-for="(item, index) in list"
  38. @click.stop="select(item)"
  39. >
  40. {{ `${item.width}*${item.height}*${item.length}` }}
  41. </view>
  42. </view>
  43. <!-- 按照绑定得字段来显示选中字段 :style="{height: `${list.length * itemHeight}rpx`}"-->
  44. <view v-else class="list" >
  45. <view
  46. class="item"
  47. :style="{...(item.selected? itemActive: {}),height: `${itemHeight}rpx`,lineHeight: `${itemHeight}rpx`}"
  48. v-for="(item, index) in list"
  49. @click.stop="select(item)"
  50. >
  51. {{ `${item[itemFormat]}` }}
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </template>
  57. <script>
  58. export default {
  59. data() {
  60. return {
  61. selectText: '',
  62. isActive: false
  63. };
  64. },
  65. methods: {
  66. // 下拉框选择
  67. select(item) {
  68. this.clearListStatus()
  69. item.selected = true
  70. this.itemFormat == '*'?this.selectText = `${item.width}*${item.height}*${item.length}`: this.selectText = item.text
  71. setTimeout(() => {
  72. this.toggleSelectStyle()
  73. }, 100)
  74. this.$emit('change', {
  75. newVal: item.value,
  76. orignItem: item
  77. })
  78. },
  79. openList() {
  80. this.toggleSelectStyle()
  81. },
  82. // 切换下拉框状态
  83. toggleSelectStyle() {
  84. this.isActive = !this.isActive
  85. },
  86. // 清空输入框
  87. clearInput() {
  88. this.selectText = ''
  89. this.isActive = false
  90. this.clearListStatus()
  91. },
  92. // 清空列表的选中样式
  93. clearListStatus() {
  94. for(let item of this.list) {
  95. item.selected = false
  96. }
  97. }
  98. },
  99. props: {
  100. // 下拉框点击显示的绑定字段
  101. itemFormat: {
  102. type: String,
  103. default: 'text'
  104. },
  105. // 数据列表
  106. list: {
  107. type: Array,
  108. default: () => {
  109. return [
  110. {text: '1楼', value: 1},
  111. {text: '4楼', value: 2}
  112. ]
  113. }
  114. },
  115. // 输入框选中样式
  116. activeStyle: {
  117. type: Object,
  118. default: () => {
  119. return {
  120. borderColor: '#007aff'
  121. }
  122. }
  123. },
  124. itemActive: {
  125. type: Object,
  126. default: () => {
  127. return {
  128. backgroundColor: '#f5f7fa',
  129. color: '#007aff',
  130. }
  131. }
  132. },
  133. itemHeight: {
  134. type: Number,
  135. default: 72
  136. },
  137. // 右侧图标颜色
  138. rightIconColor: {
  139. type: String,
  140. default: '#bbb'
  141. },
  142. // 右侧图标
  143. rightIcon: {
  144. type: String,
  145. default: 'arrowdown'
  146. },
  147. // 右侧图标大小
  148. rightIconSize: {
  149. type: Number,
  150. default: 12
  151. },
  152. // 占位符
  153. placeholder: {
  154. type: String,
  155. default: '1楼'
  156. },
  157. initValue: {
  158. type: String,
  159. default: ''
  160. }
  161. },
  162. onLoad() {
  163. }
  164. }
  165. </script>
  166. <style lang="scss">
  167. .input {
  168. position: relative;
  169. padding: 0 5%;
  170. height: 72rpx;
  171. line-height: 72rpx;
  172. width: 100%;
  173. border-radius: 5rpx;
  174. border: 1px solid #6A6B6C;
  175. .select-text {
  176. padding-right: 50rpx;
  177. display: flex;
  178. align-items: center;
  179. width: 100%;
  180. height: 100%;
  181. overflow: hidden;
  182. text-overflow: ellipsis;
  183. }
  184. .icon {
  185. position: absolute;
  186. right: 20rpx;
  187. top: 0;
  188. height: 100%;
  189. }
  190. .list-wrap {
  191. position: absolute;
  192. top: calc(100% + 10px);
  193. left: 0;
  194. z-index: 999;
  195. width: 100%;
  196. border: 1px solid #eee;
  197. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  198. background-color: #FFFFFF;
  199. &::before {
  200. content: '';
  201. position: absolute;
  202. top: -14rpx;
  203. left: 50rpx;
  204. z-index: 999;
  205. width: 0;
  206. height: 0;
  207. border-left: 12rpx solid transparent;
  208. border-right: 12rpx solid transparent;
  209. border-bottom: 14rpx solid #eee;
  210. }
  211. &::after {
  212. content: '';
  213. position: absolute;
  214. top: -13rpx;
  215. left: 52rpx;
  216. z-index: 999;
  217. width: 0;
  218. height: 0;
  219. border-left: 11rpx solid transparent;
  220. border-right: 11rpx solid transparent;
  221. border-bottom: 13rpx solid #fff;
  222. }
  223. .list {
  224. padding: 10rpx 0;
  225. max-height: 300rpx;
  226. height: 300rpx;
  227. overflow: auto;
  228. border-radius: 5rpx;
  229. .item {
  230. padding: 0 5%;
  231. }
  232. }
  233. }
  234. .animate-open-rotate {
  235. transform: rotate(180deg);
  236. transition: all .5s ease;
  237. }
  238. .animate-close-rotate {
  239. transform: rotate(0);
  240. transition: all .5s ease;
  241. }
  242. .fadeShow {
  243. animation: fadeShow .2s linear;
  244. }
  245. .fadeHidden {
  246. animation: fadeHidden .2s linear;
  247. }
  248. }
  249. @keyframes fadeShow {
  250. 0%{opacity: 0;}
  251. 100%{opacity: 1}
  252. }
  253. @keyframes fadeHidden {
  254. 0%{opacity: 1;}
  255. 100%{opacity: 0}
  256. }
  257. </style>