Skip to content

Commit

Permalink
feat(component): 完成 SwipeAction 组件编写
Browse files Browse the repository at this point in the history
  • Loading branch information
SzHeJason committed Sep 21, 2018
1 parent 2e99976 commit 5651075
Show file tree
Hide file tree
Showing 8 changed files with 389 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class App extends Component {
'pages/action/modal/index',
'pages/action/progress/index',
'pages/action/action-sheet/index',
'pages/action/swipe-action/index',
'pages/action/activity-indicator/index',
'pages/navigation/drawer/index',
'pages/navigation/pagination/index',
Expand Down
150 changes: 150 additions & 0 deletions src/components/swipe-action/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import Taro from '@tarojs/taro'
import { View, Text } from '@tarojs/components'

import PropTypes from 'prop-types'
import classNames from 'classnames'
import _isFunction from 'lodash/isFunction'

import AtComponent from '../../common/component'
import AtSwipeActionOptions from './options/index'

import './index.scss'

export default class AtSwipeAction extends AtComponent {
constructor () {
super(...arguments)

this.startX = null
this.maxOffsetSize = 0
this.isTouching = false
this.endValue = 0

this.state = {
offsetSize: 0
}
}

handleTouchStart = e => {
const { clientX } = e.touches[0]

if (this.props.disabled) return

this.startX = clientX
this.isTouching = true
}

handleTouchEnd = () => {
this.isTouching = false

const { offsetSize } = this.state

this.endValue = offsetSize

const breakpoint = this.maxOffsetSize / 2
const absOffsetSize = Math.abs(offsetSize)

if (absOffsetSize > breakpoint) {
this.endValue = -this.maxOffsetSize
return this.setState({
offsetSize: -this.maxOffsetSize
})
}

this.endValue = 0

this.setState({
offsetSize: 0
})
}

handleTouchMove = e => {
const { clientX } = e.touches[0]
if (this.isTouching) {
const offsetSize = clientX - this.startX
const isRight = offsetSize > 0

if (this.state.offsetSize === 0 && isRight) return

const value = this.endValue + offsetSize
this.setState({
offsetSize: value >= 0 ? 0 : value
})
}
}

handleDomInfo = ({ width }) => {
this.maxOffsetSize = width
}

handleClick = (item, index, ...arg) => {
const { onClick, autoClose } = this.props
if (_isFunction(onClick)) {
onClick(item, index, ...arg)
}
if (autoClose) {
this.setState({
offsetSize: 0
})
}
}

render () {
const { offsetSize } = this.state
const { options } = this.props
const rootClass = classNames('at-swipe-action', this.props.className)

return (
<View
className={rootClass}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
onTouchStart={this.handleTouchStart}
>
<View
className='at-swipe-action__content'
style={{
transform: `translate3d(${offsetSize}px,0,0)`
}}
>
{this.props.children}
</View>

{Array.isArray(options) && options.length > 0 ? (
<AtSwipeActionOptions onQueryedDom={this.handleDomInfo}>
{options.map((item, key) => (
<View
key={key}
style={item.style}
onClick={this.handleClick.bind(this, item, key)}
className={classNames(
'at-swipe-action__option',
item.className
)}
>
<Text className='option__text'>{item.text}</Text>
</View>
))}
</AtSwipeActionOptions>
) : null}
</View>
)
}
}

AtSwipeAction.defaultProps = {}

AtSwipeAction.propTypes = {
disabled: PropTypes.bool,
autoClose: PropTypes.bool,
options: PropTypes.arrayOf(
PropTypes.shape({
text: PropTypes.string,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
className: PropTypes.oneOfType([
PropTypes.object,
PropTypes.string,
PropTypes.array
])
})
)
}
28 changes: 28 additions & 0 deletions src/components/swipe-action/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@import "../../style/mixins/index.scss";
@import "../../style/theme/default.scss";

.at-swipe-action {
position: relative;
overflow: hidden;

&__content {
background-color: white;
position: relative;
z-index: 2;
font-size: $font-size-lg;
transition: transform 200ms $timing-func;
}

&__option {
@include active;
@include align-items(center);

height: 100%;
background-color: $color-grey-2;
display: inline-flex;
color: $color-white;
font-size: $font-size-base;
padding: 0 $spacing-h-xl;
text-align: center;
}
}
54 changes: 54 additions & 0 deletions src/components/swipe-action/options/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'

// import PropTypes from 'prop-types'
import classNames from 'classnames'

import AtComponent from '../../../common/component'

import './index.scss'

const REM_LAYOUT_DELAY = 500

export default class AtSwiperActionOptions extends AtComponent {
delay = () =>
new Promise(resolve => {
if (Taro.getEnv() === Taro.ENV_TYPE.WEB) {
return setTimeout(() => {
resolve()
}, REM_LAYOUT_DELAY)
}
if (Taro.getEnv() === Taro.ENV_TYPE.WEAPP) {
return resolve()
}
})

componentDidMount () {
const selector = Taro.createSelectorQuery().in(this.$scope)

this.delay().then(() => {
selector
.select('.at-swipe-action__options')
.fields({
size: true
})
.exec(res => {
console.log(res[0])
this.props.onQueryedDom(res[0])
})
})
}

render () {
const rootClass = classNames(
'at-swipe-action__options',
this.props.className
)

return <View className={rootClass}>{this.props.children}</View>
}
}

AtSwiperActionOptions.defaultProps = {}

AtSwiperActionOptions.propTypes = {}
12 changes: 12 additions & 0 deletions src/components/swipe-action/options/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@import '../../../style/mixins/libs/flex.scss';

.at-swipe-action__options {
@include align-items(center);

display: inline-flex;
position: absolute;
top: 0;
right: 0;
z-index: 1;
height: 100%;
}
123 changes: 123 additions & 0 deletions src/pages/action/swipe-action/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/* eslint taro/custom-component-children: 0 */

import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'

import AtList from '../../../components/list/index'
import AtListItem from '../../../components/list/item/index'
import AtSwipeAction from '../../../components/swipe-action/index'

import DocsHeader from '../../components/doc-header'

import './index.scss'

const OPTIONS = [
{
text: '取消',
style: {
backgroundColor: '#6190E8'
}
},
{
text: '确认',
style: {
backgroundColor: '#FF4949'
}
}
]

export default class SwipeActionPage extends Taro.Component {
config = {
navigationBarTitleText: 'Taro UI'
}

handleClick = (item, key, e) => {
console.log('触发了点击', item, key, e)
}

render () {
return (
<View className='page swipe-action-page'>
{/* S Header */}
<DocsHeader title='SwipeAction 滑动按钮' />
{/* E Header */}

{/* S Body */}
<View className='doc-body'>
{/* 无 Title */}
<View className='panel'>
<View className='panel__title'>普通使用</View>
<View className='panel__content'>
<View className='example-item'>
<AtSwipeAction options={OPTIONS}>
<View className='normal'>AtSwipeAction 一般使用场景</View>
</AtSwipeAction>
</View>
</View>
</View>

<View className='panel'>
<View className='panel__title'>禁止滑动</View>
<View className='panel__content'>
<View className='example-item'>
<AtSwipeAction disabled options={OPTIONS}>
<View className='normal'>禁止滑动展示</View>
</AtSwipeAction>
</View>
</View>
</View>

<View className='panel'>
<View className='panel__title'>自动关闭</View>
<View className='panel__content'>
<View className='example-item'>
<AtSwipeAction autoClose options={OPTIONS}>
<View className='normal'>自动关闭展示</View>
</AtSwipeAction>
</View>
</View>
</View>

<View className='panel'>
<View className='panel__title'>传递点击事件</View>
<View className='panel__content'>
<View className='example-item'>
<AtSwipeAction onClick={this.handleClick} options={OPTIONS}>
<View className='normal'>点击事件展示</View>
</AtSwipeAction>
</View>
</View>
</View>

<View className='panel'>
<View className='panel__title'>与List组件使用</View>
<View className='panel__content'>
<View className='example-item'>
<AtList>
<AtSwipeAction options={OPTIONS}>
<AtListItem title='Item1' />
</AtSwipeAction>
<AtSwipeAction options={OPTIONS}>
<AtListItem title='Item2' />
</AtSwipeAction>
<AtSwipeAction
options={[
{
text: '警告',
style: {
backgroundColor: '#FFC82C'
}
}
]}
>
<AtListItem title='Item3' />
</AtSwipeAction>
</AtList>
</View>
</View>
</View>
</View>
</View>
)
}
}
5 changes: 5 additions & 0 deletions src/pages/action/swipe-action/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.swipe-action-page {
.normal {
line-height: 50px;
}
}
Loading

0 comments on commit 5651075

Please sign in to comment.