taro 框架封装tab栏组件(其他组件类似)

**

内容中有代码解析

**

import Taro, { Component } from '@tarojs/taro'
import { View } from '@tarojs/components'
import './tabs.scss'

interface IProps {         //可以继承自父类,即可以从父组件中传递过来(这里面声明的必须的方法名,父组件中必须要传)
  tabList: Array<{           //要传入的值是数组,必须要尖括号包裹起来
    title: string,
    active?: boolean
  }>,
  flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse',    //问号的意思是可传可不传(是否换行的意思)
  maxOneRow?: number,        //每行最多几个
  current: number,     //没问号的意思是必传,后面的number是变量的类型
  onClick: any,
}  
 ***//定义的必要变量名是要在组件中传递过来的,可以由父组件来控制状态及数据变化***

export default class Tabs extends Component<IProps> {    //将定义的组件暴露出去,继承自组件的IProps属性
  _touchDot: number = 0          //手指触摸到的页面距离
  _timer: any = null                 //定时器,每100毫秒执行一次
  _interval: number = 0
  _isMoving: boolean = false     //是否移动了,以上几个都是组件内部需要用到的变量

  handleClick(current) {    //触发的点击事件
    const { onClick } = this.props     组件中onClick触发的方法,从父组件中传递过来,(传给父组件的方法,必须以on开头)
    onClick && onClick(...arguments)    //onClick存在(即为true时),执行后面的onClick方法,...arguments是展开伪数组
  }

  hadleTouchStart(e) {      //手指触摸屏幕事件
    this._touchDot = e.touches[0].pageX
    this._timer = setInterval(() => {
      this._interval++        //默认0
    }, 100)
  }

  hadleTouchMove(e) {         //开始滑动的事件,组件中的方法,但是用到了父组件的变量,需要传递进来,,通过手指的滑动,触发handleClick事件的current加一或者是减一
    const {
      current,
      tabList
    } = this.props

    const touchMove = e.touches[0].pageX      //手指触摸屏幕的位置
    const moveDistance = touchMove - this._touchDot      //手指移动的距离
    const maxIndex = tabList.length      //最大的index,即一共有多少块减一
//下面判断是左滑和右滑,   //_isMoving 肯定是false,取反,  //_interval ,一秒内滑动   //this._touchDot  滑动的距离大于20排序,限定滑动的条件
    if (!this._isMoving && this._interval < 10 && this._touchDot > 20) {
      // 向左滑动
      if (current + 1 < maxIndex && moveDistance <= -100) {
        this._isMoving = true
        this.handleClick(current + 1)

        // 向右滑动
      } else if (current - 1 >= 0 && moveDistance >= 100) {
        this._isMoving = true
        this.handleClick(current - 1)
      }
    }
  }

  handleTouchEnd(e) {      //滑动结束的事件,清除定时器,_interval 归零,_isMoving 归位
    clearInterval(this._timer)
    this._interval = 0
    this._isMoving = false
  }

  render() {
    Taro.createBLEConnection
    // flexWrap = 'nowrap',maxOneRow = 3  根据需要可自定义,也可写死,,先把this.props中的变量解构出来,下面用到的时候,就不用写那么长了
    const { tabList, current, flexWrap = 'nowrap', maxOneRow = 3, children } = this.props    
    return <View className='tabs'>  
      <View className='hd' style={`flex-wrap: ${flexWrap};`}>
        {tabList.map((tab, i) => {
          return <View
            className={`option ${i === current ? 'option_active' : ''}`}    //当当前的current等于对应的index时,添加对应的样式
            style={`width: ${
              flexWrap === 'nowrap'        //当不换行时,每个tab项的宽度是100/总项数(均衡)
                ? (100 / tabList.length)
                : (100 / maxOneRow)}%`}    //换行时,100/一行最多的个数
            onClick={this.handleClick.bind(this, i)}>
            {tab.title}
            <View className='underline'></View>
          </View>
        })}
      </View>
      <View className='bd' onTouchStart={this.hadleTouchStart.bind(this)} onTouchMove={this.hadleTouchMove.bind(this)} onTouchEnd={this.handleTouchEnd.bind(this)}>
        {children}
      </View>
    </View>
  }
}

下面是运用-------------------------------
1.import Tabs from ‘…/…/component/tabs/tabs’
2.state:any={
tabs: [ //传入的tab要以数组的形式(组件声明)传入进去
{ title: ‘租借’ },
{ title: ‘换电’ },
{ title: ‘赎回’ },
{ title: ‘共享’ },
{ title: ‘购买’ },
{ title: ‘线充’ },
],
}

 <Tabs tabList={tabs} onClick={this.tabClick.bind(this)} current={tabsCur}    flexWrap='wrap'>     //使用父组件本身定义的变量,本身的变量控制组件的状态
        <ScrollView               //tab组件下面的children即为此处的ScrollView 
          className='scroll'
          scrollY
          upperThreshold={10}
          lowerThreshold={10}
          onScrollToUpper={this.refreshList.bind(this)}
          onScrollToLower={orders.length >= limit && orders.length < total ? this.loadMore.bind(this) : () => { }}>
          {orders.map(order => {     //orders是父组件(即使用组件的页面),可以正常使用当前页面的变量
            if (order) {       //页面标签中加判断条件,必须要在遍历事件中,否则直接加判断条件的话,会报错,也不会执行
              return <OrderItem
                type={types}
                status={order.status}
                use_shop_benefit={order.use_shop_benefit}
                terminal={order.terminal}
                old_terminal={order.old_terminal}
                new_terminal={order.new_terminal}
                order_id={order.order_id}
                shop_name={order.shop_name}
                rent_time={order.rent_time}
                rebuy_time={order.rebuy_time}
                return_time={order.return_time}
                time={order.time}
                buy_time={order.buy_time}
                use_time={order.use_time}
                total_fee={order.total_fee}
                real_fee={order.real_fee}
                income={order.income}
                line_id={order.line_id}
                rent_total_time={order.rent_total_time}
                onRentBuy={this.rentBuy.bind(this, order.order_id)}
                onRentBuyTip={this.rentBuyTip.bind(this)}
                onLineRef={this.lineRefund.bind(this, order.order_id, order.line_id)}
                onRentPay={this.rentPay.bind(this, order.order_id)}
              />
            }
          })}
          {(!orders.length || orders.length >= total) && <View className='no_more'>-------- 没有更多订单了 --------</View>}
        </ScrollView>
      </Tabs >
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值