Skip to content
This repository was archived by the owner on Oct 27, 2021. It is now read-only.

Commit

Permalink
feat: add Accordion
Browse files Browse the repository at this point in the history
  • Loading branch information
pengshanglong committed May 13, 2020
1 parent c80a70d commit 53a55c0
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 31 deletions.
154 changes: 154 additions & 0 deletions src/components/accordion/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import classNames from 'classnames'
import mixins from '../mixins'
import { delayQuerySelector } from '../../utils/common'

export default {
name: 'Accordion',
mixins: [mixins],
props: {
open: {
type: Boolean,
default: false,
},
customStyle: {
type: String,
default: '',
},
className: {
type: String,
default: '',
},
title: {
type: String,
default: '',
},
note: {
type: String,
default: '',
},
icon: {
type: Object,
default: () => ({ value: '' }),
},
hasBorder: {
type: Boolean,
default: true,
},
isAnimation: {
type: Boolean,
default: true,
},
onClick: {
type: Function,
default: () => () => {},
},
},
data() {
return {
isCompleted: true,
startOpen: false,
state: {
wrapperHeight: 0,
},
}
},
watch: {
open(val, oldVal) {
if (val !== oldVal) {
this.startOpen = !!val && !!this.isAnimation
this.toggleWithAnimation()
}
},
},
methods: {
/**
*
* @param {event} event
*/
handleClick(event) {
const { open } = this
if (!this.isCompleted) return

this.onClick && this.onClick(!open, event)
},
toggleWithAnimation() {
const { open, isAnimation } = this
if (!this.isCompleted || !isAnimation) return
this.isCompleted = false
delayQuerySelector(this, '.at-accordion__body', 0).then((rect) => {
const height = parseInt(rect[0].height.toString())
const startHeight = open ? height : 0
const endHeight = open ? 0 : height
this.startOpen = false
this.setState(
{
wrapperHeight: startHeight,
},
() => {
setTimeout(() => {
this.setState(
{
wrapperHeight: endHeight,
},
() => {
setTimeout(() => {
this.isCompleted = true
this.setState({})
}, 700)
}
)
}, 100)
}
)
})
},
},
render() {
const { customStyle, className, title, icon, hasBorder, open, note } = this
const { wrapperHeight } = this.state

const rootCls = classNames('at-accordion', className)
const prefixClass = (icon && icon.prefixClass) || 'at-icon'
const iconCls = classNames({
[prefixClass]: true,
[`${prefixClass}-${icon && icon.value}`]: icon && icon.value,
'at-accordion__icon': true,
})
const headerCls = classNames('at-accordion__header', {
'at-accordion__header--noborder': !hasBorder,
})
const arrowCls = classNames('at-accordion__arrow', {
'at-accordion__arrow--folded': !!open,
})
const contentCls = classNames('at-accordion__content', {
'at-accordion__content--inactive': (!open && this.isCompleted) || this.startOpen,
})
const iconStyle = {
color: (icon && icon.color) || '',
fontSize: (icon && `${icon.size}px`) || '',
}
const contentStyle = { height: `${wrapperHeight}px` }

if (this.isCompleted) {
contentStyle.height = ''
}

return (
<view class={rootCls} style={customStyle}>
<view class={headerCls} onTap={this.handleClick}>
{icon && icon.value && <view class={iconCls} style={iconStyle}></view>}
<view class="at-accordion__info">
<view class="at-accordion__info__title">{title}</view>
<view class="at-accordion__info__note">{note}</view>
</view>
<view class={arrowCls}>
<view class="at-icon at-icon-chevron-down"></view>
</view>
</view>
<view style={contentStyle} class={contentCls}>
<view class="at-accordion__body">{this.$slots.default}</view>
</view>
</view>
)
},
}
3 changes: 2 additions & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import List from './list/index'
import ListItem from './list/item/index'
import Card from './card/index'
import FloatLayout from './float-layout/index'
import Accordion from './accordion/index'

export { Grid, List, ListItem, Card, FloatLayout }
export { Grid, List, ListItem, Card, FloatLayout, Accordion }
3 changes: 2 additions & 1 deletion src/components/notes.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Noticebar marquee 属性 还不可用
- Button 未完成,Invalid handler for event "getPhoneNumber": got undefined 等错误
- Button 未完成,Invalid handler for event "getPhoneNumber": got undefined 等错误
- Accordion 动画不顺滑
85 changes: 59 additions & 26 deletions src/pages/index/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,33 @@
<view
class="index"
>
<Accordion
title="标题三"
:icon="accordionIcon"
:open="openAccordion"
:on-click="handleAccordionOpen"
>
<List :has-border="false">
<ListItem
title="标题文字"
arrow="right"
thumb="https://img12.360buyimg.com/jdphoto/s72x72_jfs/t6160/14/2008729947/2754/7d512a86/595c3aeeNa89ddf71.png"
/>
<ListItem
title="标题文字"
note="描述信息"
arrow="right"
thumb="http://img10.360buyimg.com/jdphoto/s72x72_jfs/t5872/209/5240187906/2872/8fa98cd/595c3b2aN4155b931.png"
/>
<ListItem
title="标题文字"
note="描述信息"
extra-text="详细信息"
arrow="right"
thumb="http://img12.360buyimg.com/jdphoto/s72x72_jfs/t10660/330/203667368/1672/801735d7/59c85643N31e68303.png"
/>
</List>
</Accordion>
<FloatLayout
title="这是个标题"
>
Expand Down Expand Up @@ -217,7 +244,7 @@ import ModalAction from '../../components/modal/action/index.jsx'
import Toast from '../../components/toast/index.jsx'
import SwipeAction from '../../components/swipe-action/index.jsx'
import Message from '../../components/message/index.jsx'
import { Grid, List, ListItem, Card, FloatLayout } from '../../components/index'
import { Grid, List, ListItem, Card, FloatLayout, Accordion } from '../../components/index'
export default {
name: 'Index',
Expand Down Expand Up @@ -249,6 +276,7 @@ export default {
ListItem,
Card,
FloatLayout,
Accordion,
},
data() {
return {
Expand All @@ -269,31 +297,33 @@ export default {
}
],
gridData: [
{
image: 'https://img12.360buyimg.com/jdphoto/s72x72_jfs/t6160/14/2008729947/2754/7d512a86/595c3aeeNa89ddf71.png',
value: '领取中心'
},
{
image: 'https://img20.360buyimg.com/jdphoto/s72x72_jfs/t15151/308/1012305375/2300/536ee6ef/5a411466N040a074b.png',
value: '找折扣'
},
{
image: 'https://img10.360buyimg.com/jdphoto/s72x72_jfs/t5872/209/5240187906/2872/8fa98cd/595c3b2aN4155b931.png',
value: '领会员'
},
{
image: 'https://img12.360buyimg.com/jdphoto/s72x72_jfs/t10660/330/203667368/1672/801735d7/59c85643N31e68303.png',
value: '新品首发'
},
{
image: 'https://img14.360buyimg.com/jdphoto/s72x72_jfs/t17251/336/1311038817/3177/72595a07/5ac44618Na1db7b09.png',
value: '领京豆'
},
{
image: 'https://img30.360buyimg.com/jdphoto/s72x72_jfs/t5770/97/5184449507/2423/294d5f95/595c3b4dNbc6bc95d.png',
value: '手机馆'
}
]
{
image: 'https://img12.360buyimg.com/jdphoto/s72x72_jfs/t6160/14/2008729947/2754/7d512a86/595c3aeeNa89ddf71.png',
value: '领取中心'
},
{
image: 'https://img20.360buyimg.com/jdphoto/s72x72_jfs/t15151/308/1012305375/2300/536ee6ef/5a411466N040a074b.png',
value: '找折扣'
},
{
image: 'https://img10.360buyimg.com/jdphoto/s72x72_jfs/t5872/209/5240187906/2872/8fa98cd/595c3b2aN4155b931.png',
value: '领会员'
},
{
image: 'https://img12.360buyimg.com/jdphoto/s72x72_jfs/t10660/330/203667368/1672/801735d7/59c85643N31e68303.png',
value: '新品首发'
},
{
image: 'https://img14.360buyimg.com/jdphoto/s72x72_jfs/t17251/336/1311038817/3177/72595a07/5ac44618Na1db7b09.png',
value: '领京豆'
},
{
image: 'https://img30.360buyimg.com/jdphoto/s72x72_jfs/t5770/97/5184449507/2423/294d5f95/595c3b4dNbc6bc95d.png',
value: '手机馆'
}
],
accordionIcon: { value: 'chevron-down', color: 'red', size: '15' },
openAccordion: false
}
},
methods: {
Expand All @@ -311,6 +341,9 @@ export default {
'message': '消息通知',
'type': type,
})
},
handleAccordionOpen(isOpen, e) {
this.openAccordion = isOpen
}
},
}
Expand Down
6 changes: 3 additions & 3 deletions src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ function delayGetClientRect({ _, selectorStr, delayTime = 500 }): Promise<[]> {
})
}

function delayQuerySelector(self, selectorStr: string, delayTime = 500): Promise<[]> {
const $scope = ENV === Taro.ENV_TYPE.WEB ? self : self.$scope
const selector: SelectorQuery = Taro.createSelectorQuery().in($scope)
function delayQuerySelector(_, selectorStr: string, delayTime = 500): Promise<[]> {
false && console.log(_)
const selector: SelectorQuery = Taro.createSelectorQuery()

return new Promise((resolve) => {
delay(delayTime).then(() => {
Expand Down

0 comments on commit 53a55c0

Please # to comment.