mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[Improvement] Collapse: add transition animation (#1500)
This commit is contained in:
parent
a99e73e07e
commit
9da3e0ce5a
@ -8,15 +8,18 @@
|
|||||||
<cell :class="b('title')" is-link @click="onClick">
|
<cell :class="b('title')" is-link @click="onClick">
|
||||||
<slot name="title">{{ title }}</slot>
|
<slot name="title">{{ title }}</slot>
|
||||||
</cell>
|
</cell>
|
||||||
<div v-show="expanded" :class="b('content')">
|
<div v-show="show" ref="wrapper" :class="b('wrapper')" @transitionend="onTransitionEnd">
|
||||||
|
<div ref="content" :class="b('content')">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import findParent from '../mixins/find-parent';
|
import { raf } from '../utils/raf';
|
||||||
import create from '../utils/create';
|
import create from '../utils/create';
|
||||||
|
import findParent from '../mixins/find-parent';
|
||||||
|
|
||||||
export default create({
|
export default create({
|
||||||
name: 'collapse-item',
|
name: 'collapse-item',
|
||||||
@ -28,6 +31,12 @@ export default create({
|
|||||||
title: String
|
title: String
|
||||||
},
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
items() {
|
items() {
|
||||||
return this.parent.items;
|
return this.parent.items;
|
||||||
@ -42,6 +51,10 @@ export default create({
|
|||||||
},
|
},
|
||||||
|
|
||||||
expanded() {
|
expanded() {
|
||||||
|
if (!this.parent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const { value } = this.parent;
|
const { value } = this.parent;
|
||||||
return this.parent.accordion
|
return this.parent.accordion
|
||||||
? value === this.currentName
|
? value === this.currentName
|
||||||
@ -52,17 +65,52 @@ export default create({
|
|||||||
created() {
|
created() {
|
||||||
this.findParent('van-collapse');
|
this.findParent('van-collapse');
|
||||||
this.items.push(this);
|
this.items.push(this);
|
||||||
|
this.show = this.expanded;
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.items.splice(this.index, 1);
|
this.items.splice(this.index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
expanded(expanded, prev) {
|
||||||
|
if (prev === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expanded) {
|
||||||
|
this.show = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const { content, wrapper } = this.$refs;
|
||||||
|
if (!content || !wrapper) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentHeight = content.clientHeight + 'px';
|
||||||
|
wrapper.style.height = expanded ? 0 : contentHeight;
|
||||||
|
raf(() => {
|
||||||
|
wrapper.style.height = expanded ? contentHeight : 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onClick() {
|
onClick() {
|
||||||
const { parent } = this;
|
const { parent } = this;
|
||||||
const name = parent.accordion && this.currentName === parent.value ? '' : this.currentName;
|
const name = parent.accordion && this.currentName === parent.value ? '' : this.currentName;
|
||||||
this.parent.switch(name, !this.expanded);
|
const expanded = !this.expanded;
|
||||||
|
this.parent.switch(name, expanded);
|
||||||
|
},
|
||||||
|
|
||||||
|
onTransitionEnd() {
|
||||||
|
if (!this.expanded) {
|
||||||
|
this.show = false;
|
||||||
|
} else {
|
||||||
|
this.$refs.wrapper.style.height = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -13,8 +13,10 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="van-collapse-item__wrapper">
|
||||||
<div class="van-collapse-item__content">提供多样店铺模板,快速搭建网上商城</div>
|
<div class="van-collapse-item__content">提供多样店铺模板,快速搭建网上商城</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="van-collapse-item van-hairline--top">
|
<div class="van-collapse-item van-hairline--top">
|
||||||
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
||||||
<!---->
|
<!---->
|
||||||
@ -24,7 +26,9 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item__content" style="display:none;">网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失</div>
|
<div class="van-collapse-item__wrapper" style="display:none;">
|
||||||
|
<div class="van-collapse-item__content">网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item van-hairline--top">
|
<div class="van-collapse-item van-hairline--top">
|
||||||
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
||||||
@ -35,7 +39,9 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item__content" style="display:none;">线上拓客,随时预约,贴心顺手的开单收银</div>
|
<div class="van-collapse-item__wrapper" style="display:none;">
|
||||||
|
<div class="van-collapse-item__content">线上拓客,随时预约,贴心顺手的开单收银</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -50,8 +56,10 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="van-collapse-item__wrapper">
|
||||||
<div class="van-collapse-item__content">提供多样店铺模板,快速搭建网上商城</div>
|
<div class="van-collapse-item__content">提供多样店铺模板,快速搭建网上商城</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="van-collapse-item van-hairline--top">
|
<div class="van-collapse-item van-hairline--top">
|
||||||
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
||||||
<!---->
|
<!---->
|
||||||
@ -61,7 +69,9 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item__content" style="display:none;">网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失</div>
|
<div class="van-collapse-item__wrapper" style="display:none;">
|
||||||
|
<div class="van-collapse-item__content">网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item van-hairline--top">
|
<div class="van-collapse-item van-hairline--top">
|
||||||
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
||||||
@ -72,7 +82,9 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item__content" style="display:none;">线上拓客,随时预约,贴心顺手的开单收银</div>
|
<div class="van-collapse-item__wrapper" style="display:none;">
|
||||||
|
<div class="van-collapse-item__content">线上拓客,随时预约,贴心顺手的开单收银</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -93,10 +105,12 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item__content" style="display:none;">
|
<div class="van-collapse-item__wrapper" style="display:none;">
|
||||||
|
<div class="van-collapse-item__content">
|
||||||
提供多样店铺模板,快速搭建网上商城
|
提供多样店铺模板,快速搭建网上商城
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="van-collapse-item van-hairline--top">
|
<div class="van-collapse-item van-hairline--top">
|
||||||
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
<div class="van-cell van-cell--clickable van-hairline van-collapse-item__title">
|
||||||
<!---->
|
<!---->
|
||||||
@ -106,7 +120,9 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-collapse-item__content" style="display:none;">网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失</div>
|
<div class="van-collapse-item__wrapper" style="display:none;">
|
||||||
|
<div class="van-collapse-item__content">网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Collapse from '..';
|
import Collapse from '..';
|
||||||
import CollapseItem from '../../collapse-item';
|
import CollapseItem from '../../collapse-item';
|
||||||
import { mount } from '../../../test/utils';
|
import { later, mount } from '../../../test/utils';
|
||||||
|
|
||||||
const component = {
|
const component = {
|
||||||
template: `
|
template: `
|
||||||
@ -24,7 +24,7 @@ const component = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test('basic mode', () => {
|
test('basic mode', async() => {
|
||||||
const wrapper = mount(component);
|
const wrapper = mount(component);
|
||||||
|
|
||||||
const titles = wrapper.findAll('.van-collapse-item__title');
|
const titles = wrapper.findAll('.van-collapse-item__title');
|
||||||
@ -34,13 +34,14 @@ test('basic mode', () => {
|
|||||||
titles.at(1).trigger('click');
|
titles.at(1).trigger('click');
|
||||||
expect(wrapper.vm.active).toEqual(['first', 1]);
|
expect(wrapper.vm.active).toEqual(['first', 1]);
|
||||||
|
|
||||||
|
await later();
|
||||||
titles.at(0).trigger('click');
|
titles.at(0).trigger('click');
|
||||||
expect(wrapper.vm.active).toEqual([1]);
|
expect(wrapper.vm.active).toEqual([1]);
|
||||||
|
|
||||||
wrapper.destroy();
|
wrapper.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accordion', () => {
|
it('accordion', async() => {
|
||||||
const wrapper = mount(component, {
|
const wrapper = mount(component, {
|
||||||
propsData: {
|
propsData: {
|
||||||
accordion: true
|
accordion: true
|
||||||
@ -54,6 +55,7 @@ it('accordion', () => {
|
|||||||
titles.at(1).trigger('click');
|
titles.at(1).trigger('click');
|
||||||
expect(wrapper.vm.active).toEqual(1);
|
expect(wrapper.vm.active).toEqual(1);
|
||||||
|
|
||||||
|
await later();
|
||||||
titles.at(0).trigger('click');
|
titles.at(0).trigger('click');
|
||||||
expect(wrapper.vm.active).toEqual('first');
|
expect(wrapper.vm.active).toEqual('first');
|
||||||
|
|
||||||
|
@ -12,6 +12,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
overflow: hidden;
|
||||||
|
will-change: height;
|
||||||
|
transition: height .3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user