123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- <template>
- <view class="easy-select" @click.stop="trigger" :style="[easySelectSize]">
- <input type="text" v-model="value" :placeholder="placeholder" disabled clearable>
- <!-- <view class="easy-select-suffix" :style="{border: '1px solid rgba(0,0,0,0)'}" :class="[showSuffix]">
- <view class="easy-select-down-tag"></view>
- </view> -->
- <view class="easy-select-options" v-if="showOptions" :style="{'min-width': boundingClientRect.width + 'px', top: optionsGroupTop, margin: optionsGroupMargin}">
- <view class="easy-select-options-item" v-for="item in options" :key="item.code" @click.stop="select(item)" :class="{active: currentSelect.name === item.name}">
- <text>{{item.name}}</text>
- </view>
- </view>
- </view>
- </template>
- <script>
- /**
- * easy-select
- * @author Snoop zhang
- * @description Select Component
- * */
- const COMPONENT_NAME = 'easy-select'
- const MAX_OPTIONS_HEIGHT = 137 // 修改务必也修改easy-select-options的css部分
- const OPTIONS_ITEM_HEIGHT = 33 // 修改务必也修改easy-select-options-item的css部分
- const OPTIONS_MARGIN = 10
- const OPTIONS_PADDING = 6 * 2 + 2 // + 2是border
- const OPTIONS_OTHER_HEIGHT = OPTIONS_MARGIN + OPTIONS_PADDING
- const STORAGE_KEY = '_easyWindowHeight'
- const SIZE = {
- 'medium': {
- width: '150px',
- height: '40px'
- },
- 'small': {
- width: '200px',
- height: '30px'
- },
- 'mini': {
- width: '160px',
- height: '30px'
- }
- }
-
- export default {
- name: COMPONENT_NAME,
- props: {
- windowHeight: {
- type: [Number, String],
- default: 0
- },
- placeholder: {
- type: String,
- default: '选择币种'
- },
- value: {
- type: String,
- default: '双皮奶'
- },
- size: {
- type: String,
- default: 'medium'
- },
- options: {
- type: Array,
- default () {
- return []
- }
- }
- },
- data() {
- return {
- showOptions: false,
- boundingClientRect: {},
- currentSelect: {},
- optionsGroupTop: 'auto',
- optionsGroupMargin: ''
- }
- },
- computed: {
- showSuffix() {
- return this.showOptions ? 'showOptions' : 'no-showOptions'
- },
- easySelectSize() {
- let size = this.size.toLowerCase()
- if (size in SIZE) {
- return {
- width: SIZE[size].width,
- height: SIZE[size].height
- }
- } else {
- return {}
- }
- }
- },
- mounted() {
- const elQuery = uni.createSelectorQuery().in(this)
- elQuery.select('.easy-select').boundingClientRect(data => {
- this.boundingClientRect = data
- }).exec();
- try {
- if (!this.windowHeight) {
- const storageHeihgt = uni.getStorageSync(STORAGE_KEY)
- if (storageHeihgt) {
- this.easyWindowHeight = storageHeihgt
- return
- }
- const res = uni.getSystemInfoSync();
- this.easyWindowHeight = res.windowHeight
- uni.setStorageSync(STORAGE_KEY, this.easyWindowHeight)
- }
- } catch (e) {
- // error
- }
- },
- methods: {
- trigger(e) {
- const view = uni.createSelectorQuery().in(this)
- view.select('.easy-select').fields({rect: true}, data => {
- let { top, bottom } = data
- const thresholdHeight = Math.min(MAX_OPTIONS_HEIGHT + OPTIONS_MARGIN, (this.options.length * OPTIONS_ITEM_HEIGHT) +
- OPTIONS_OTHER_HEIGHT)
- bottom = Number(this.windowHeight || this.easyWindowHeight) - (top + this.boundingClientRect.height) // 距离底部的距离等于视口的高度减上top加select组件的高度
- // judge direction
- if (bottom < thresholdHeight) {
- this.optionsGroupDirection = 'up'
- this.optionsGroupTop = -thresholdHeight - 12 + 'px'
- this.optionsGroupMargin = '0'
- } else {
- this.optionsGroupDirection = 'down'
- this.optionsGroupTop = 'auto'
- this.optionsGroupMargin = '10px 0 0 0'
- }
- // if (this.scrollTop < )
- this.showOptions = !this.showOptions
- }).exec();
- },
- select(options) {
- this.showOptions = false
- this.currentSelect = options
- this.$emit('selectOne', options)
- },
- hideOptions() {
- this.showOptions = false
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .easy-select {
- position: relative;
- color: #606266;
- input{
- text-align: right;
- }
- }
- .easy-select input {
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- height: 100% !important;
- min-height: 100% !important;
- }
- .easy-select .easy-select-suffix {
- position: absolute;
- box-sizing: border-box;
- height: 100%;
- right: 5px;
- top: 0;
- display: flex;
- align-items: center;
- transform: rotate(180deg);
- transition: all .3s;
- transform-origin: center;
- }
- .easy-select .showOptions {
- transform: rotate(0) !important;
- }
- .easy-select .no-showOptions {
- transform: rotate(180deg) !important;
- }
- .easy-select .easy-select-options {
- position: absolute;
- padding: 6px 0;
- margin-top: 10px;
- border: 1px solid #e4e7ed;
- border-radius: 4px;
- background-color: #fff;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
- box-sizing: border-box;
- transform-origin: center top;
- z-index: 2238;
- overflow: scroll;
- max-height: 274rpx;
- }
- .easy-select .easy-select-options-item {
- padding: 0 20rpx;
- position: relative;
- white-space: nowrap;
- font-size: 14px;
- color: #606266;
- height: 33px;
- line-height: 33px;
- box-sizing: border-box;
- }
- .easy-select .active {
- background-color: #F5F7FA
- }
- </style>
|