mirror of
				https://gitee.com/vant-contrib/vant.git
				synced 2025-11-04 12:52:08 +08:00 
			
		
		
		
	[Improvement] Picker: optimize render performance (#1391)
This commit is contained in:
		
							parent
							
								
									6adf501441
								
							
						
					
					
						commit
						7f4ad6a28d
					
				@ -25,6 +25,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import create from '../utils/create';
 | 
					import create from '../utils/create';
 | 
				
			||||||
 | 
					import deepClone from '../utils/deep-clone';
 | 
				
			||||||
import { isObj } from '../utils';
 | 
					import { isObj } from '../utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DEFAULT_DURATION = 200;
 | 
					const DEFAULT_DURATION = 200;
 | 
				
			||||||
@ -38,7 +39,7 @@ export default create({
 | 
				
			|||||||
    className: String,
 | 
					    className: String,
 | 
				
			||||||
    itemHeight: Number,
 | 
					    itemHeight: Number,
 | 
				
			||||||
    visibleItemCount: Number,
 | 
					    visibleItemCount: Number,
 | 
				
			||||||
    options: {
 | 
					    initialOptions: {
 | 
				
			||||||
      type: Array,
 | 
					      type: Array,
 | 
				
			||||||
      default: () => []
 | 
					      default: () => []
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -54,15 +55,13 @@ export default create({
 | 
				
			|||||||
      offset: 0,
 | 
					      offset: 0,
 | 
				
			||||||
      duration: 0,
 | 
					      duration: 0,
 | 
				
			||||||
      startOffset: 0,
 | 
					      startOffset: 0,
 | 
				
			||||||
 | 
					      options: deepClone(this.initialOptions),
 | 
				
			||||||
      currentIndex: this.defaultIndex
 | 
					      currentIndex: this.defaultIndex
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  created() {
 | 
					  created() {
 | 
				
			||||||
    this.$parent.children && this.$parent.children.push(this);
 | 
					    this.$parent.children && this.$parent.children.push(this);
 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  mounted() {
 | 
					 | 
				
			||||||
    this.setIndex(this.currentIndex);
 | 
					    this.setIndex(this.currentIndex);
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,12 +72,6 @@ export default create({
 | 
				
			|||||||
  watch: {
 | 
					  watch: {
 | 
				
			||||||
    defaultIndex() {
 | 
					    defaultIndex() {
 | 
				
			||||||
      this.setIndex(this.defaultIndex);
 | 
					      this.setIndex(this.defaultIndex);
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    options(next, prev) {
 | 
					 | 
				
			||||||
      if (JSON.stringify(next) !== JSON.stringify(prev)) {
 | 
					 | 
				
			||||||
        this.setIndex(0);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -103,10 +96,6 @@ export default create({
 | 
				
			|||||||
        transform: `translate3d(0, ${this.offset + this.baseOffset}px, 0)`,
 | 
					        transform: `translate3d(0, ${this.offset + this.baseOffset}px, 0)`,
 | 
				
			||||||
        lineHeight: this.itemHeight + 'px'
 | 
					        lineHeight: this.itemHeight + 'px'
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    currentValue() {
 | 
					 | 
				
			||||||
      return this.options[this.currentIndex];
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -168,10 +157,13 @@ export default create({
 | 
				
			|||||||
      const { options } = this;
 | 
					      const { options } = this;
 | 
				
			||||||
      for (let i = 0; i < options.length; i++) {
 | 
					      for (let i = 0; i < options.length; i++) {
 | 
				
			||||||
        if (this.getOptionText(options[i]) === value) {
 | 
					        if (this.getOptionText(options[i]) === value) {
 | 
				
			||||||
          this.setIndex(i);
 | 
					          return this.setIndex(i);
 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getValue() {
 | 
				
			||||||
 | 
					      return this.options[this.currentIndex];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -12,10 +12,10 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div :class="b('columns')" :style="columnsStyle" @touchmove.prevent>
 | 
					    <div :class="b('columns')" :style="columnsStyle" @touchmove.prevent>
 | 
				
			||||||
      <picker-column
 | 
					      <picker-column
 | 
				
			||||||
        v-for="(item, index) in currentColumns"
 | 
					        v-for="(item, index) in (simple ? [columns] : columns)"
 | 
				
			||||||
        :key="index"
 | 
					        :key="index"
 | 
				
			||||||
        :value-key="valueKey"
 | 
					        :value-key="valueKey"
 | 
				
			||||||
        :options="item.values"
 | 
					        :initial-options="simple ? item : item.values"
 | 
				
			||||||
        :class-name="item.className"
 | 
					        :class-name="item.className"
 | 
				
			||||||
        :default-index="item.defaultIndex"
 | 
					        :default-index="item.defaultIndex"
 | 
				
			||||||
        :item-height="itemHeight"
 | 
					        :item-height="itemHeight"
 | 
				
			||||||
@ -65,22 +65,10 @@ export default create({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  data() {
 | 
					  data() {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      children: [],
 | 
					      children: []
 | 
				
			||||||
      currentColumns: []
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  watch: {
 | 
					 | 
				
			||||||
    columns: {
 | 
					 | 
				
			||||||
      handler() {
 | 
					 | 
				
			||||||
        const columns = this.columns.map(deepClone);
 | 
					 | 
				
			||||||
        this.isSimpleColumn = columns.length && !columns[0].values;
 | 
					 | 
				
			||||||
        this.currentColumns = this.isSimpleColumn ? [{ values: columns }] : columns;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      immediate: true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    frameStyle() {
 | 
					    frameStyle() {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
@ -92,12 +80,29 @@ export default create({
 | 
				
			|||||||
      return {
 | 
					      return {
 | 
				
			||||||
        height: this.itemHeight * this.visibleItemCount + 'px'
 | 
					        height: this.itemHeight * this.visibleItemCount + 'px'
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    simple() {
 | 
				
			||||||
 | 
					      return this.columns.length && !this.columns[0].values;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  watch: {
 | 
				
			||||||
 | 
					    columns() {
 | 
				
			||||||
 | 
					      this.setColumns();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
 | 
					    setColumns() {
 | 
				
			||||||
 | 
					      const columns = this.simple ? [{ values: this.columns }] : this.columns;
 | 
				
			||||||
 | 
					      columns.forEach((columns, index) => {
 | 
				
			||||||
 | 
					        this.setColumnValues(index, deepClone(columns.values));
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    emit(event) {
 | 
					    emit(event) {
 | 
				
			||||||
      if (this.isSimpleColumn) {
 | 
					      if (this.simple) {
 | 
				
			||||||
        this.$emit(event, this.getColumnValue(0), this.getColumnIndex(0));
 | 
					        this.$emit(event, this.getColumnValue(0), this.getColumnIndex(0));
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        this.$emit(event, this.getValues(), this.getIndexes());
 | 
					        this.$emit(event, this.getValues(), this.getIndexes());
 | 
				
			||||||
@ -105,7 +110,7 @@ export default create({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onChange(columnIndex) {
 | 
					    onChange(columnIndex) {
 | 
				
			||||||
      if (this.isSimpleColumn) {
 | 
					      if (this.simple) {
 | 
				
			||||||
        this.$emit('change', this, this.getColumnValue(0), this.getColumnIndex(0));
 | 
					        this.$emit('change', this, this.getColumnValue(0), this.getColumnIndex(0));
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        this.$emit('change', this, this.getValues(), columnIndex);
 | 
					        this.$emit('change', this, this.getValues(), columnIndex);
 | 
				
			||||||
@ -119,7 +124,8 @@ export default create({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // get column value by index
 | 
					    // get column value by index
 | 
				
			||||||
    getColumnValue(index) {
 | 
					    getColumnValue(index) {
 | 
				
			||||||
      return (this.getColumn(index) || {}).currentValue;
 | 
					      const column = this.getColumn(index);
 | 
				
			||||||
 | 
					      return column && column.getValue();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // set column value by index
 | 
					    // set column value by index
 | 
				
			||||||
@ -141,20 +147,21 @@ export default create({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // get options of column by index
 | 
					    // get options of column by index
 | 
				
			||||||
    getColumnValues(index) {
 | 
					    getColumnValues(index) {
 | 
				
			||||||
      return (this.currentColumns[index] || {}).values;
 | 
					      return (this.children[index] || {}).options;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // set options of column by index
 | 
					    // set options of column by index
 | 
				
			||||||
    setColumnValues(index, options) {
 | 
					    setColumnValues(index, options) {
 | 
				
			||||||
      const column = this.currentColumns[index];
 | 
					      const column = this.children[index];
 | 
				
			||||||
      if (column) {
 | 
					      if (column && JSON.stringify(column.options) !== JSON.stringify(options)) {
 | 
				
			||||||
        column.values = options;
 | 
					        column.options = options;
 | 
				
			||||||
 | 
					        column.setIndex(0);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // get values of all columns
 | 
					    // get values of all columns
 | 
				
			||||||
    getValues() {
 | 
					    getValues() {
 | 
				
			||||||
      return this.children.map(child => child.currentValue);
 | 
					      return this.children.map(child => child.getValue());
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // set values of all columns
 | 
					    // set values of all columns
 | 
				
			||||||
 | 
				
			|||||||
@ -26,9 +26,9 @@ exports[`renders demo correctly 1`] = `
 | 
				
			|||||||
      <!---->
 | 
					      <!---->
 | 
				
			||||||
      <div class="van-picker__columns" style="height:220px;">
 | 
					      <div class="van-picker__columns" style="height:220px;">
 | 
				
			||||||
        <div class="van-picker-column" style="height:220px;">
 | 
					        <div class="van-picker-column" style="height:220px;">
 | 
				
			||||||
          <ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;">
 | 
					          <ul style="transition:0ms;transform:translate3d(0, 44px, 0);line-height:44px;">
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item van-picker-column__item--disabled van-picker-column__item--selected">杭州</li>
 | 
					            <li class="van-ellipsis van-picker-column__item van-picker-column__item--disabled">杭州</li>
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item">宁波</li>
 | 
					            <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">宁波</li>
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item">温州</li>
 | 
					            <li class="van-ellipsis van-picker-column__item">温州</li>
 | 
				
			||||||
          </ul>
 | 
					          </ul>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
@ -70,7 +70,7 @@ exports[`renders demo correctly 1`] = `
 | 
				
			|||||||
          </ul>
 | 
					          </ul>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="van-picker-column column2" style="height:220px;">
 | 
					        <div class="van-picker-column column2" style="height:220px;">
 | 
				
			||||||
          <ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;">
 | 
					          <ul style="transition:0ms;transform:translate3d(0, 0px, 0);line-height:44px;">
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item">杭州</li>
 | 
					            <li class="van-ellipsis van-picker-column__item">杭州</li>
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item">宁波</li>
 | 
					            <li class="van-ellipsis van-picker-column__item">宁波</li>
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">温州</li>
 | 
					            <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">温州</li>
 | 
				
			||||||
@ -96,7 +96,7 @@ exports[`renders demo correctly 1`] = `
 | 
				
			|||||||
          </ul>
 | 
					          </ul>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="van-picker-column column2" style="height:220px;">
 | 
					        <div class="van-picker-column column2" style="height:220px;">
 | 
				
			||||||
          <ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;">
 | 
					          <ul style="transition:0ms;transform:translate3d(0, 0px, 0);line-height:44px;">
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item">杭州</li>
 | 
					            <li class="van-ellipsis van-picker-column__item">杭州</li>
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item">宁波</li>
 | 
					            <li class="van-ellipsis van-picker-column__item">宁波</li>
 | 
				
			||||||
            <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">温州</li>
 | 
					            <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">温州</li>
 | 
				
			||||||
 | 
				
			|||||||
@ -18,8 +18,8 @@ exports[`column watch default index 2`] = `
 | 
				
			|||||||
<div class="van-picker-column">
 | 
					<div class="van-picker-column">
 | 
				
			||||||
  <ul style="line-height: 50px;">
 | 
					  <ul style="line-height: 50px;">
 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item van-picker-column__item--disabled">1</li>
 | 
					    <li class="van-ellipsis van-picker-column__item van-picker-column__item--disabled">1</li>
 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">1990</li>
 | 
					    <li class="van-ellipsis van-picker-column__item">1990</li>
 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item">1991</li>
 | 
					    <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">1991</li>
 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item">1992</li>
 | 
					    <li class="van-ellipsis van-picker-column__item">1992</li>
 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item">1993</li>
 | 
					    <li class="van-ellipsis van-picker-column__item">1993</li>
 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item">1994</li>
 | 
					    <li class="van-ellipsis van-picker-column__item">1994</li>
 | 
				
			||||||
@ -27,14 +27,3 @@ exports[`column watch default index 2`] = `
 | 
				
			|||||||
  </ul>
 | 
					  </ul>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					 | 
				
			||||||
exports[`column watch default index 3`] = `
 | 
					 | 
				
			||||||
<div class="van-picker-column">
 | 
					 | 
				
			||||||
  <ul style="line-height: 50px;">
 | 
					 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">1</li>
 | 
					 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item van-picker-column__item--disabled">1</li>
 | 
					 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item van-picker-column__item--disabled">1</li>
 | 
					 | 
				
			||||||
    <li class="van-ellipsis van-picker-column__item van-picker-column__item--disabled">1</li>
 | 
					 | 
				
			||||||
  </ul>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import Picker from '../';
 | 
					import Picker from '../';
 | 
				
			||||||
import PickerColumn from '../PickerColumn';
 | 
					import PickerColumn from '../PickerColumn';
 | 
				
			||||||
import { mount, triggerDrag } from '../../../test/utils';
 | 
					import { mount, triggerDrag, later } from '../../../test/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const simpleColumn = ['1990', '1991', '1992', '1993', '1994', '1995'];
 | 
					const simpleColumn = ['1990', '1991', '1992', '1993', '1994', '1995'];
 | 
				
			||||||
const columns = [
 | 
					const columns = [
 | 
				
			||||||
@ -101,21 +101,19 @@ test('drag simple columns', () => {
 | 
				
			|||||||
  expect(wrapper.emitted('change')[0][1]).toEqual('1992');
 | 
					  expect(wrapper.emitted('change')[0][1]).toEqual('1992');
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('column watch default index', () => {
 | 
					test('column watch default index', async() => {
 | 
				
			||||||
  const disabled = { disabled: true, text: 1 };
 | 
					  const disabled = { disabled: true, text: 1 };
 | 
				
			||||||
  const wrapper = mount(PickerColumn, {
 | 
					  const wrapper = mount(PickerColumn, {
 | 
				
			||||||
    propsData: {
 | 
					    propsData: {
 | 
				
			||||||
 | 
					      initialOptions: [disabled, ...simpleColumn],
 | 
				
			||||||
      valueKey: 'text',
 | 
					      valueKey: 'text',
 | 
				
			||||||
      itemHeight: 50
 | 
					      itemHeight: 50
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  wrapper.vm.options = [disabled, ...simpleColumn];
 | 
					
 | 
				
			||||||
 | 
					  await later();
 | 
				
			||||||
  expect(wrapper).toMatchSnapshot();
 | 
					  expect(wrapper).toMatchSnapshot();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wrapper.vm.options = [disabled, ...simpleColumn];
 | 
					 | 
				
			||||||
  expect(wrapper).toMatchSnapshot();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  wrapper.vm.options = [1, disabled, disabled, disabled];
 | 
					 | 
				
			||||||
  wrapper.vm.defaultIndex = 2;
 | 
					  wrapper.vm.defaultIndex = 2;
 | 
				
			||||||
  expect(wrapper).toMatchSnapshot();
 | 
					  expect(wrapper).toMatchSnapshot();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user