[Improvement] Picker: optimize render performance (#1391)

This commit is contained in:
neverland 2018-07-03 23:36:36 +08:00 committed by GitHub
parent 6adf501441
commit 7f4ad6a28d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 64 deletions

View File

@ -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];
} }
} }
}); });

View File

@ -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

View File

@ -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>

View File

@ -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>
`;

View File

@ -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();
}); });