yaogengzhu / daily-share

个人博客记录、内容在issues
30 stars 4 forks source link

使用react封装一个组件以及如何调用(2019-08-05) #34

Open yaogengzhu opened 5 years ago

yaogengzhu commented 5 years ago

使用react封装一个组件

看封装组件的代码~~~~~

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

interface IProps {
    danger?: boolean,
    title?: string
}
interface IState {
    isShowDialog: boolean
}

export default class Popper extends Component<IProps, IState> {
    //放回私有的方法
    private resolve: () => void
    private reject: () => void

    //定义一些基本的属性
    static defaultProps = {
        danger: false,
        title: '提示'
    }
    // 定义一些数据
    constructor() {
        super(...arguments)
        this.state = {
            isShowDialog: false
        }
    }

    // 在引用的位置可以调用
    public open(): Promise<any> {
        this.setState({
            isShowDialog: true
        })
        return new Promise((resolve, reject) => {
            this.resolve = resolve
            this.reject = reject
        })
    }

    // 私有的方法,只有在内才能调用
    private cancel() {
        this.setState({
            isShowDialog: false
        })
        this.reject && this.reject()
    }

    private confirm() {
        this.setState({
            isShowDialog: false
        })
        this.resolve && this.resolve()
    }

    render () {
        return <View>
            <View className='popper-bg' hidden={!this.state.isShowDialog}>
                <View className='popper-box'>
                    {/* <View className='popper-title safe safe-boder'>提示</View> */}
                    <View className='popper-title danger danger-boder'>{this.props.title}</View>

                    <View className='popper-content'>
                        {this.props.children}
                    </View>
                    <View className='popper-btn'>
                        <View className='cancel' onClick={() => this.cancel()}>取消</View>
                        {/* <View className='confirm safe' onClick={() => this.resolve()}>确认</View> */}
                        <View className='confirm danger' onClick={() => this.confirm()}>确认</View>
                    </View>
                </View>
            </View>
        </View>
    }
}

看如何掉调用


import Taro, { Component } from '@tarojs/taro'
import { View, Text, Image } from '@tarojs/components'
import { Row, Col, Table, ColumnsProperties } from '@/components/base'
import fetch from '@/api'
import Popper from '@/components/popper/popper'

// 引入图片
import iconImg from '../../assets/images/a5.png'
import './main.scss'

interface IProps {}

interface IStates {
    dataSource: Array<any>
}

export default class Main extends Component<IProps, IStates> {
    private dialog: Taro.RefObject<Popper>
    constructor() {
        super(...arguments)
        this.state = {
            dataSource: []
        }
       // 使用Trao.createRef创建ref,  当ref被传递给render中的元素时,对该节点可以在ref的`current属性中访问`
        this.dialog = Taro.createRef<Popper>()
    }

    componentDidMount() {
        fetch
            .get({
                url: '/purchase/order/list',
                params: {
                    page: 0,
                    limit: 50
                }
            })
            .then(data => {
                this.setState({
                    dataSource: data.purchase_order_list
                })
                console.log('data', data)
            })
            .catch(e => {
                console.log(e)
            })
    }

    onTableScroll(e) {
        console.log(e)
    }

    onScrollToLower() {
        console.log('滚动到底部了')
    }

    openDialog() {
        if (this.dialog.current) {
            this.dialog.current.open().then(() => {
                console.log(1)
            }).catch(() => {
                console.log(2)
            })
        }
    }

    JumpToPage() {
        Taro.navigateTo({
            url: '/pages/forwardPurchase/forwardPurchase'
        })
    }

    render() {
        const columns: ColumnsProperties = [
            {
                title: '完成时间',
                dataIndex: 'date',
                key: 'date',
                width: 110
                // render: (
                //      <View>{record}{index}</View>
                // )
            },
            {
                title: '货品数',
                dataIndex: 'goods_num',
                key: 'goods_num',
                align: 'right'
            },
            {
                title: '总件数',
                dataIndex: 'total_amount',
                key: 'total_amount',
                align: 'right'
            },
            {
                title: '总支出/元',
                dataIndex: 'total_price',
                key: 'subtotal',
                align: 'right'
            },
            {
                title: '',
                dataIndex: '',
                key: '',
                width: 42
            }
        ]

        return (
            <View className='main-container'>
                <Popper ref={this.dialog}>
                    <View>
                        test
                    </View>
                </Popper>
                <View className='top'>
                    <View className='block-1' onClick={() => this.JumpToPage()}>
                        {/* 提前采购 */}
                        <View className='block-1-1'>
                            <Image src={iconImg} className='iconImag' />
                            <View className='content'>
                                <View className='title'>提前采购</View>
                                <View className='info'>产地直采、提前预定等采购,不受限于门店订货单</View>
                            </View>
                        </View>
                    </View>
                    <View className='block-2' onClick={() => this.openDialog()}>
                        <Text className='t1'>即时采购</Text>
                        <Text className='t2'>现场/短途采购,当天到货</Text>
                    </View>
                </View>
                <View className='bottom'>
                    <Table
                      onScroll={e => this.onTableScroll(e)}
                      onScrollToLower={() => this.onScrollToLower()}
                      renderHeader={
                            <Row columns={columns} type='header'>
                                {columns.map(cell => {
                                    return <Col align={cell.align}>{cell['title'] === '价格' ? <View style={{ color: '#f00' }}>{cell['title']}</View> : cell['title']}</Col>
                                })}
                            </Row>
                        }
                    >
                        {this.state.dataSource.map((row, index) => {
                            return (
                                <Row columns={columns} type='body' index={index} key={index}>
                                    {columns.map(cell => {
                                        return <Col {...cell}>{cell['dataIndex'] === 'price' ? <View style={{ color: '#f00' }}>{row[cell['key']]}</View> : row[cell['key']]}</Col>
                                    })}
                                </Row>
                            )
                        })}
                    </Table>
                </View>
            </View>
        )
    }
}
yaogengzhu commented 5 years ago

补充

在常规Taro数据流中,props 是父组件与子组件交互的唯一方式,要修改子元素,需要用新的props去重新渲染子元素,然而呢,在少数情况下,我们需要在常规的数据流外强制修改子元素,被修改的子元素可以是taro上的组件实例,或者是一个dom元素。

当然,我们会首先想到使用的是refs属性来更新组件,如果是这种情况。需要更多关注在组件中使用state。通常较高几杯的state更为的清楚表达,。;。。通常呢,相比在Dialog组件中暴露的open() 和close() 方法。最好传递isOpen属性 。

首先第一步创建refs

方式1 使用字符串方式创建

通过字符串创建的ref只要把一个字符串的名称赋值给ref prop. 然后可以通过this.refs访问到被定义组件和实例或DOM元素。

class  Commo extends Component { 
    componentDidMount () { 
    if ( process.env.TARO_ENV === 'wxapp' { 
    // 这里的this.refs.input 访问的时候,通过`wx.createSeletorQuery` 取到小程序的原生组件  
    }  else if ( process.env.TAEO_ENV === h5') {  
    //  这里的this.refs.input 访问到是 `@tarojs/components`中的`Input` 组件实例
} 
render () { 
   return <Input  ref='input' />
   }
}

通过函数的方式

class MyComponent extends Component {

  roar () {
    // 会打印 `miao, miao, miao~`
    this.cat.miao()
  }

  refCat = (node) => this.cat = node // `this.cat` 会变成 `Cat` 组件实例的引用

  render () {
    return <Cat ref={this.refCat} />
  }
}

class Cat extends Component {
  miao () {
    console.log('miao, miao, miao~')
  }

  render () {
    return <View />
  }
}

通过createRef 创建ref

Refs 还是使用 Taro.createRef() 创建的,并通过 ref 属性附加到 Taro 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。

当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。


class MyComponent extends Component {

  this.cat = Taro.createRef()

  roar () {
    // 会打印 `miao, miao, miao~`
    this.cat.current.miao()
  }

  render () {
    return <Cat ref={this.cat} />
  }
}

class Cat extends Component {
  miao () {
    console.log('miao, miao, miao~')
  }

  render () {
    return <View />
  }
}