index.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { use } from '../utils';
  2. import { preventDefault } from '../utils/event';
  3. import { deepClone } from '../utils/deep-clone';
  4. import { pickerProps } from './shared';
  5. import Loading from '../loading';
  6. import PickerColumn from './PickerColumn';
  7. const [sfc, bem, t] = use('picker');
  8. export default sfc({
  9. props: {
  10. ...pickerProps,
  11. columns: Array,
  12. defaultIndex: {
  13. type: Number,
  14. default: 0
  15. },
  16. valueKey: {
  17. type: String,
  18. default: 'text'
  19. }
  20. },
  21. data() {
  22. return {
  23. children: []
  24. };
  25. },
  26. computed: {
  27. simple() {
  28. return this.columns.length && !this.columns[0].values;
  29. }
  30. },
  31. watch: {
  32. columns() {
  33. this.setColumns();
  34. }
  35. },
  36. methods: {
  37. setColumns() {
  38. const columns = this.simple ? [{ values: this.columns }] : this.columns;
  39. columns.forEach((column, index) => {
  40. this.setColumnValues(index, deepClone(column.values));
  41. });
  42. },
  43. emit(event) {
  44. if (this.simple) {
  45. this.$emit(event, this.getColumnValue(0), this.getColumnIndex(0));
  46. } else {
  47. this.$emit(event, this.getValues(), this.getIndexes());
  48. }
  49. },
  50. onChange(columnIndex) {
  51. if (this.simple) {
  52. this.$emit('change', this, this.getColumnValue(0), this.getColumnIndex(0));
  53. } else {
  54. this.$emit('change', this, this.getValues(), columnIndex);
  55. }
  56. },
  57. // get column instance by index
  58. getColumn(index) {
  59. return this.children[index];
  60. },
  61. // get column value by index
  62. getColumnValue(index) {
  63. const column = this.getColumn(index);
  64. return column && column.getValue();
  65. },
  66. // set column value by index
  67. setColumnValue(index, value) {
  68. const column = this.getColumn(index);
  69. column && column.setValue(value);
  70. },
  71. // get column option index by column index
  72. getColumnIndex(columnIndex) {
  73. return (this.getColumn(columnIndex) || {}).currentIndex;
  74. },
  75. // set column option index by column index
  76. setColumnIndex(columnIndex, optionIndex) {
  77. const column = this.getColumn(columnIndex);
  78. column && column.setIndex(optionIndex);
  79. },
  80. // get options of column by index
  81. getColumnValues(index) {
  82. return (this.children[index] || {}).options;
  83. },
  84. // set options of column by index
  85. setColumnValues(index, options) {
  86. const column = this.children[index];
  87. if (column && JSON.stringify(column.options) !== JSON.stringify(options)) {
  88. column.options = options;
  89. column.setIndex(0);
  90. }
  91. },
  92. // get values of all columns
  93. getValues() {
  94. return this.children.map(child => child.getValue());
  95. },
  96. // set values of all columns
  97. setValues(values) {
  98. values.forEach((value, index) => {
  99. this.setColumnValue(index, value);
  100. });
  101. },
  102. // get indexes of all columns
  103. getIndexes() {
  104. return this.children.map(child => child.currentIndex);
  105. },
  106. // set indexes of all columns
  107. setIndexes(indexes) {
  108. indexes.forEach((optionIndex, columnIndex) => {
  109. this.setColumnIndex(columnIndex, optionIndex);
  110. });
  111. },
  112. onConfirm() {
  113. this.emit('confirm');
  114. },
  115. onCancel() {
  116. this.emit('cancel');
  117. }
  118. },
  119. render(h) {
  120. const { itemHeight } = this;
  121. const columns = this.simple ? [this.columns] : this.columns;
  122. const frameStyle = {
  123. height: `${itemHeight}px`
  124. };
  125. const columnsStyle = {
  126. height: `${itemHeight * this.visibleItemCount}px`
  127. };
  128. const Toolbar = this.showToolbar && (
  129. <div class={['van-hairline--top-bottom', bem('toolbar')]}>
  130. {this.slots() || [
  131. <div class={bem('cancel')} onClick={this.onCancel}>
  132. {this.cancelButtonText || t('cancel')}
  133. </div>,
  134. this.slots('title') ||
  135. (this.title && (
  136. <div class={['van-ellipsis', bem('title')]}>{this.title}</div>
  137. )),
  138. <div class={bem('confirm')} onClick={this.onConfirm}>
  139. {this.confirmButtonText || t('confirm')}
  140. </div>
  141. ]}
  142. </div>
  143. );
  144. return (
  145. <div class={bem()}>
  146. {Toolbar}
  147. {this.loading ? (
  148. <div class={bem('loading')}>
  149. <Loading />
  150. </div>
  151. ) : (
  152. h()
  153. )}
  154. <div class={bem('columns')} style={columnsStyle} onTouchmove={preventDefault}>
  155. {columns.map((item, index) => (
  156. <PickerColumn
  157. valueKey={this.valueKey}
  158. className={item.className}
  159. itemHeight={this.itemHeight}
  160. defaultIndex={item.defaultIndex || this.defaultIndex}
  161. visibleItemCount={this.visibleItemCount}
  162. initialOptions={this.simple ? item : item.values}
  163. onChange={() => {
  164. this.onChange(index);
  165. }}
  166. />
  167. ))}
  168. <div class={['van-hairline--top-bottom', bem('frame')]} style={frameStyle} />
  169. </div>
  170. </div>
  171. );
  172. }
  173. });