[bugfix] Collapse: improve performance & optimize initial style set

fix #1494
This commit is contained in:
rex 2019-04-11 10:34:48 +08:00 committed by GitHub
parent 60c2bf212f
commit bbb070f084
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 61 deletions

View File

@ -27,6 +27,10 @@
&__wrapper { &__wrapper {
overflow: hidden; overflow: hidden;
&--transition {
transition: height 300ms ease-in-out;
}
} }
&__content { &__content {

View File

@ -1,5 +1,7 @@
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
const nextTick = () => new Promise(resolve => setTimeout(resolve, 20));
VantComponent({ VantComponent({
classes: ['title-class', 'content-class'], classes: ['title-class', 'content-class'],
@ -30,58 +32,58 @@ VantComponent({
data: { data: {
contentHeight: 0, contentHeight: 0,
expanded: false expanded: false,
transition: false
}, },
beforeCreate() { mounted() {
this.animation = wx.createAnimation({ this.updateExpanded()
duration: 300, .then(nextTick)
timingFunction: 'ease-in-out' .then(() => {
this.set({ transition: true });
}); });
}, },
methods: { methods: {
updateExpanded() { updateExpanded() {
if (!this.parent) { if (!this.parent) {
return null; return Promise.resolve();
} }
const { value, accordion, items } = this.parent.data; const { value, accordion } = this.parent.data;
const { children = [] } = this.parent;
const { name } = this.data; const { name } = this.data;
const index = items.indexOf(this); const index = children.indexOf(this);
const currentName = name == null ? index : name; const currentName = name == null ? index : name;
const expanded = accordion const expanded = accordion
? value === currentName ? value === currentName
: value.some(name => name === currentName); : (value || []).some((name: string | number) => name === currentName);
const stack = [];
if (expanded !== this.data.expanded) { if (expanded !== this.data.expanded) {
this.updateStyle(expanded); stack.push(this.updateStyle(expanded));
} }
this.set({ index, expanded }); stack.push(this.set({ index, expanded }));
return Promise.all(stack);
}, },
updateStyle(expanded: boolean) { updateStyle(expanded: boolean) {
this.getRect('.van-collapse-item__content').then(res => { return this.getRect('.van-collapse-item__content')
const animationData = this.animation .then((rect: wx.BoundingClientRectCallbackResult) => rect.height)
.height(expanded ? res.height : 0) .then((height: number) => {
.step()
.export();
if (expanded) { if (expanded) {
this.set({ animationData }); return this.set({
contentHeight: height ? `${height}px` : 'auto'
});
} else { } else {
this.set( return this.set({ contentHeight: `${height}px` })
{ .then(nextTick)
contentHeight: res.height + 'px' .then(() => this.set({ contentHeight: 0 }));
},
() => {
setTimeout(() => {
this.set({ animationData });
}, 20);
}
);
} }
}); });
}, },
@ -92,8 +94,7 @@ VantComponent({
} }
const { name, expanded } = this.data; const { name, expanded } = this.data;
const index = this.parent.children.indexOf(this);
const index = this.parent.data.items.indexOf(this);
const currentName = name == null ? index : name; const currentName = name == null ? index : name;
this.parent.switch(currentName, !expanded); this.parent.switch(currentName, !expanded);

View File

@ -30,9 +30,8 @@
/> />
</van-cell> </van-cell>
<view <view
class="van-collapse-item__wrapper" class="{{ utils.bem('collapse-item__wrapper', { transition }) }}"
style="height: {{ contentHeight }};" style="height: {{ contentHeight }};"
animation="{{ animationData }}"
bind:transitionend="onTransitionEnd" bind:transitionend="onTransitionEnd"
> >
<view <view

View File

@ -5,47 +5,42 @@ VantComponent({
name: 'collapse-item', name: 'collapse-item',
type: 'descendant', type: 'descendant',
linked(child: Weapp.Component) { linked(child: Weapp.Component) {
this.set({ this.children.push(child);
items: [...this.data.items, child]
}, () => {
child.updateExpanded();
});
} }
}, },
props: { props: {
value: null, value: {
accordion: Boolean, type: null,
observer: 'updateExpanded'
},
accordion: {
type: Boolean,
observer: 'updateExpanded'
},
border: { border: {
type: Boolean, type: Boolean,
value: true value: true
} }
}, },
data: { beforeCreate() {
items: [] this.children = [];
},
watch: {
value() {
this.data.items.forEach(child => {
child.updateExpanded();
});
},
accordion() {
this.data.items.forEach(child => {
child.updateExpanded();
});
}
}, },
methods: { methods: {
switch(name, expanded) { updateExpanded() {
this.children.forEach((child: Weapp.Component) => {
child.updateExpanded();
});
},
switch(name: string | number, expanded: boolean) {
const { accordion, value } = this.data; const { accordion, value } = this.data;
if (!accordion) { if (!accordion) {
name = expanded name = expanded
? value.concat(name) ? (value || []).concat(name)
: value.filter(activeName => activeName !== name); : (value || []).filter((activeName: string | number) => activeName !== name);
} else { } else {
name = expanded ? name : ''; name = expanded ? name : '';
} }