index.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <uni-shadow-root class="vant-picker-column-index"><view class="van-picker-column custom-class" :style="computed.rootStyle({ itemHeight, visibleItemCount })" @touchstart="onTouchStart" @touchmove.stop.prevent="onTouchMove" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
  3. <view :style="computed.wrapperStyle({ offset, itemHeight, visibleItemCount, duration })">
  4. <view v-for="(option,index) in (options)" :key="option.index" :data-index="index" :style="'height: '+(itemHeight)+'px'" :class="'van-ellipsis '+(utils.bem('picker-column__item', { disabled: option && option.disabled, selected: index === currentIndex }))+' '+(index === currentIndex ? 'active-class' : '')" @click="onClickItem">{{ computed.optionText(option, valueKey) }}</view>
  5. </view>
  6. </view></uni-shadow-root>
  7. </template>
  8. <wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
  9. <script>
  10. global['__wxRoute'] = 'vant/picker-column/index'
  11. import { VantComponent } from '../common/component';
  12. import { range } from '../common/utils';
  13. import { isObj } from '../common/validator';
  14. const DEFAULT_DURATION = 200;
  15. VantComponent({
  16. classes: ['active-class'],
  17. props: {
  18. valueKey: String,
  19. className: String,
  20. itemHeight: Number,
  21. visibleItemCount: Number,
  22. initialOptions: {
  23. type: Array,
  24. value: [],
  25. },
  26. defaultIndex: {
  27. type: Number,
  28. value: 0,
  29. observer(value) {
  30. this.setIndex(value);
  31. },
  32. },
  33. },
  34. data: {
  35. startY: 0,
  36. offset: 0,
  37. duration: 0,
  38. startOffset: 0,
  39. options: [],
  40. currentIndex: 0,
  41. },
  42. created() {
  43. const { defaultIndex, initialOptions } = this.data;
  44. this.set({
  45. currentIndex: defaultIndex,
  46. options: initialOptions,
  47. }).then(() => {
  48. this.setIndex(defaultIndex);
  49. });
  50. },
  51. methods: {
  52. getCount() {
  53. return this.data.options.length;
  54. },
  55. onTouchStart(event) {
  56. this.setData({
  57. startY: event.touches[0].clientY,
  58. startOffset: this.data.offset,
  59. duration: 0,
  60. });
  61. },
  62. onTouchMove(event) {
  63. const { data } = this;
  64. const deltaY = event.touches[0].clientY - data.startY;
  65. this.setData({
  66. offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight),
  67. });
  68. },
  69. onTouchEnd() {
  70. const { data } = this;
  71. if (data.offset !== data.startOffset) {
  72. this.setData({ duration: DEFAULT_DURATION });
  73. const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
  74. this.setIndex(index, true);
  75. }
  76. },
  77. onClickItem(event) {
  78. const { index } = event.currentTarget.dataset;
  79. this.setIndex(index, true);
  80. },
  81. adjustIndex(index) {
  82. const { data } = this;
  83. const count = this.getCount();
  84. index = range(index, 0, count);
  85. for (let i = index; i < count; i++) {
  86. if (!this.isDisabled(data.options[i]))
  87. return i;
  88. }
  89. for (let i = index - 1; i >= 0; i--) {
  90. if (!this.isDisabled(data.options[i]))
  91. return i;
  92. }
  93. },
  94. isDisabled(option) {
  95. return isObj(option) && option.disabled;
  96. },
  97. getOptionText(option) {
  98. const { data } = this;
  99. return isObj(option) && data.valueKey in option
  100. ? option[data.valueKey]
  101. : option;
  102. },
  103. setIndex(index, userAction) {
  104. const { data } = this;
  105. index = this.adjustIndex(index) || 0;
  106. const offset = -index * data.itemHeight;
  107. if (index !== data.currentIndex) {
  108. return this.set({ offset, currentIndex: index }).then(() => {
  109. userAction && this.$emit('change', index);
  110. });
  111. }
  112. return this.set({ offset });
  113. },
  114. setValue(value) {
  115. const { options } = this.data;
  116. for (let i = 0; i < options.length; i++) {
  117. if (this.getOptionText(options[i]) === value) {
  118. return this.setIndex(i);
  119. }
  120. }
  121. return Promise.resolve();
  122. },
  123. getValue() {
  124. const { data } = this;
  125. return data.options[data.currentIndex];
  126. },
  127. },
  128. });
  129. export default global['__wxComponents']['vant/picker-column/index']
  130. </script>
  131. <style platform="mp-weixin">
  132. @import '../common/index.css';.van-picker-column{color:var(--picker-option-text-color,#000);font-size:var(--picker-option-font-size,16px);overflow:hidden;text-align:center}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{color:var(--picker-option-selected-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}
  133. </style>