Skip to content

Commit

Permalink
fix(accordion): 适配百度并重构
Browse files Browse the repository at this point in the history
  • Loading branch information
jimczj committed Jan 31, 2019
1 parent 0743caf commit 13f927d
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 117 deletions.
4 changes: 4 additions & 0 deletions @types/accordion.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export interface AtAccordionProps extends AtComponent {

icon?: AtIconBaseProps

isAnimation?: boolean

hasBorder?: boolean

onClick?: CommonEventFunction
}

Expand Down
85 changes: 57 additions & 28 deletions docs/markdown/accordion.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,63 @@ import { AtAccordion } from 'taro-ui'

## 一般用法

说明
说明:

* 该组件为受控组件,开发者通过 open 来控制组件开关状态,可通过触发 onClick 函数时修改 open 实现状态切换

:::demo

```html
<AtAccordion
onClick={this.onClick.bind(this)}
title='标题一'
>
<AtList hasBorder={false}>
<AtListItem
title='标题文字'
arrow='right'
thumb='https://img12.360buyimg.com/jdphoto/s72x72_jfs/t6160/14/2008729947/2754/7d512a86/595c3aeeNa89ddf71.png'
/>
<AtListItem
title='标题文字'
note='描述信息'
arrow='right'
thumb='http://img10.360buyimg.com/jdphoto/s72x72_jfs/t5872/209/5240187906/2872/8fa98cd/595c3b2aN4155b931.png'
/>
<AtListItem
title='标题文字'
note='描述信息'
extraText='详细信息'
arrow='right'
thumb='http://img12.360buyimg.com/jdphoto/s72x72_jfs/t10660/330/203667368/1672/801735d7/59c85643N31e68303.png'
/>
</AtList>
</AtAccordion>
```js
import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'
import { AtAccordion, AtList, AtListItem } from 'taro-ui'

export default class Index extends Taro.Component {
constructor () {
super(...arguments)
this.state = {
open: false,
}
}
handleClick (value) {
this.setState({
open: value
})
}
render () {

return (
<AtAccordion
open={this.state.open}
onClick={this.onClick.bind(this)}
title='标题一'
>
<AtList hasBorder={false}>
<AtListItem
title='标题文字'
arrow='right'
thumb='https://img12.360buyimg.com/jdphoto/s72x72_jfs/t6160/14/2008729947/2754/7d512a86/595c3aeeNa89ddf71.png'
/>
<AtListItem
title='标题文字'
note='描述信息'
arrow='right'
thumb='http://img10.360buyimg.com/jdphoto/s72x72_jfs/t5872/209/5240187906/2872/8fa98cd/595c3b2aN4155b931.png'
/>
<AtListItem
title='标题文字'
note='描述信息'
extraText='详细信息'
arrow='right'
thumb='http://img12.360buyimg.com/jdphoto/s72x72_jfs/t10660/330/203667368/1672/801735d7/59c85643N31e68303.png'
/>
</AtList>
</AtAccordion>
)
}
}


```

:::
Expand Down Expand Up @@ -94,10 +121,12 @@ import { AtAccordion } from 'taro-ui'
| ---------- | -------------------------------------- | ------- | ------------------------------------------------------------------- | -------- |
| open | 是否默认开启 | Boolean | - | false |
| title | 标题 | String | - | - |
| hasBorder | 是否有头部下划线 | Boolean | - | true |
| isAnimation | 是否开启动画 (v2.0.0-beta.3 支持)| Boolean | - | true |
| icon | 图标,仅支持 AtIcon 支持的类型,object 属性有 value color size | object | - | - |

## 事件

| 事件名称 | 说明 | 返回参数 |
|---------- |-------------- |---------- |
| onClick | 点击头部触发事件 | event |
| onClick | 点击头部触发事件 | (open,event) => void |
30 changes: 29 additions & 1 deletion src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,33 @@ function pxTransform(size) {
return Taro.pxTransform(size)
}


function linear(t, b, c, d) {
return (c * t / d) + b
}

function easeOut(from, to, callback) {
if (from === to || typeof from !== 'number') {
return
}

const change = to - from
const dur = 1000
const sTime = +new Date()
const isLarger = to >= from

function step() {
from = linear(+new Date() - sTime, from, change, dur)
if ((isLarger && from >= to) || (!isLarger && to >= from)) {
callback(to)
return
}
callback(from)
requestAnimationFrame(step)
}
step()
}

export {
delay,
delayQuerySelector,
Expand All @@ -229,5 +256,6 @@ export {
pxTransform,
handleTouchScroll,
delayGetClientRect,
delayGetScrollOffset
delayGetScrollOffset,
easeOut
}
126 changes: 57 additions & 69 deletions src/components/accordion/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,50 @@ import PropTypes from 'prop-types'
import classNames from 'classnames'
import { View, Text } from '@tarojs/components'
import AtComponent from '../../common/component'
import { delayQuerySelector, uuid } from '../../common/utils'
import { delayQuerySelector, initTestEnv, easeOut } from '../../common/utils'

initTestEnv()

// 文档
export default class AtAccordion extends AtComponent {
constructor () {
super(...arguments)
this.bodyHeight = 0 // body 高度
this.accordionId = this.props.isTest ? 'accordion-AOTU2018' : `accordion-${uuid()}`
this.isCompleted = true
this.state = {
isOpen: !!this.props.open, // 组件是否展开
wrapperHeight: '',
wrapperHeight: ''
}
}

handleClick (e) {
this.switch()
this.props.onClick(e)
}

componentDidMount () {
this.initData()
}

componentWillReceiveProps () {
this.initData()
handleClick = event => {
const { open } = this.props
this.props.onClick(!open, event)
}

initData () {
const { isOpen } = this.state
const env = Taro.getEnv()
toggleWithAnimation () {
const { open, isAnimation } = this.props
if (!this.isCompleted || !isAnimation) return

if (env === Taro.ENV_TYPE.WEB) {
setTimeout(() => {
this.accordionRef = document.getElementById(this.accordionId)
this.bodyHeight = this.accordionRef.getBoundingClientRect().height

this.setState({
wrapperHeight: isOpen ? this.bodyHeight : 0
})
}, 500)
} else if (env === Taro.ENV_TYPE.WEAPP || env === Taro.ENV_TYPE.ALIPAY) {
delayQuerySelector(this, `#${this.accordionId}`)
.then(rect => {
this.bodyHeight = rect[0].height || 0
this.isCompleted = false
delayQuerySelector(this, '.at-accordion__content', 0)
.then(rect => {
const height = parseInt(rect[0].height)
const startHeight = open ? height : 0
const endHeight = open ? 0 : height
easeOut(startHeight, endHeight, value => {
if (value === endHeight) {
this.isCompleted = true
}
this.setState({
wrapperHeight: isOpen ? this.bodyHeight : 0
wrapperHeight: value
})
})
}
})
}

switch () {
const { isOpen } = this.state
this.setState({
isOpen: !isOpen,
wrapperHeight: isOpen ? 0 : this.bodyHeight
})
componentWillReceiveProps (nextProps) {
if (nextProps.open !== this.props.open) {
this.toggleWithAnimation()
}
}

render () {
Expand All @@ -68,61 +56,61 @@ export default class AtAccordion extends AtComponent {
title,
icon,
hasBorder,
open
} = this.props
const { wrapperHeight, isOpen } = this.state
const { wrapperHeight } = this.state

const isAnimationStart = open && !this.isCompleted && wrapperHeight < 2

const iconClass = classNames({
const rootCls = classNames('at-accordion', className)
const iconCls = classNames({
'at-icon': true,
[`at-icon-${icon && icon.value}`]: icon && icon.value,
'at-accordion__icon': true,
})
const headerClass = classNames('at-accordion__header', {
const headerCls = classNames('at-accordion__header', {
'at-accordion__header--noborder': !hasBorder
})
const arrowClass = classNames('at-accordion__arrow', {
'at-accordion__arrow--folded': !!isOpen
const arrowCls = classNames('at-accordion__arrow', {
'at-accordion__arrow--folded': !!open
})
const contentCls = classNames('at-accordion__content', {
'at-accordion__content--inactive': (!open && this.isCompleted) || isAnimationStart
})

const contentStyle = {
height: `${wrapperHeight}px`
}
const iconStyle = {
color: (icon && icon.color) || '',
fontSize: (icon && `${icon.size}px`) || '',
}
const contentStyle = { height: `${wrapperHeight}px` }

return (
<View
className={classNames('at-accordion', className)}
style={customStyle}
>
<View className={headerClass} onClick={this.handleClick.bind(this)}>
{icon && icon.value && <Text className={iconClass} style={iconStyle}></Text>}
<View className='at-accordion__title'>{title}</View>
<View className={arrowClass}>
<Text className='at-icon at-icon-chevron-down'></Text>
</View>
</View>
<View
className='at-accordion__content'
style={contentStyle}
id={this.accordionId}
>
{this.props.children}
if (this.isCompleted || isAnimationStart) {
contentStyle.height = ''
}

return <View className={rootCls} style={customStyle}>
<View className={headerCls} onClick={this.handleClick}>
{icon && icon.value && <Text className={iconCls} style={iconStyle}></Text>}
<View className='at-accordion__title'>{title}</View>
<View className={arrowCls}>
<Text className='at-icon at-icon-chevron-down'></Text>
</View>
</View>
)
<View className={contentCls} style={contentStyle}>
{this.props.children}
</View>
</View>
}
}

AtAccordion.defaultProps = {
isTest: false,
open: false,
customStyle: '',
className: '',
title: '',
icon: {},
hasBorder: true,
isAnimation: true,
onClick: () => {},
}

Expand All @@ -135,8 +123,8 @@ AtAccordion.propTypes = {
PropTypes.array,
PropTypes.string
]),
isTest: PropTypes.bool,
open: PropTypes.bool,
isAnimation: PropTypes.bool,
title: PropTypes.string,
icon: PropTypes.object,
hasBorder: PropTypes.bool,
Expand Down
17 changes: 4 additions & 13 deletions src/components/accordion/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,23 @@ import AtAccordion from '../../../.temp/components/accordion'

describe('AtAccordion Snap', () => {
it('render initial AtAccordion', () => {
const component = renderToString(
<AtAccordion isTest>
</AtAccordion>
)
const component = renderToString(<AtAccordion />)
expect(component).toMatchSnapshot()
})

it('render AtAccordion -- props title', () => {
const component = renderToString(
<AtAccordion isTest title='title'>
</AtAccordion>
)
const component = renderToString(<AtAccordion title='title' />)
expect(component).toMatchSnapshot()
})

it('render AtAccordion -- props open', () => {
const component = renderToString(
<AtAccordion isTest open>
</AtAccordion>
)
const component = renderToString(<AtAccordion open />)
expect(component).toMatchSnapshot()
})

it('render AtAccordion -- props icon', () => {
const component = renderToString(
<AtAccordion isTest icon={{ value: 'chevron-down', color: 'red' }}>
<AtAccordion icon={{ value: 'chevron-down', color: 'red' }}>
<View></View>
</AtAccordion>
)
Expand Down
Loading

0 comments on commit 13f927d

Please sign in to comment.