一、描述

rax-counter 实际上是一个辅助组件,我猜想是服务淘宝的下单的增加或者减少商品而可以开发的。

因为这个组件本身其实没有什么特别大的作用,有点鸡肋,直接实现也不是很难,毕竟不需要基于 weex 来实现一些东西。

不过这个组件默认的样式非常丑(毕竟不是基于业务的,为了通用性,rax 的组件样式都满足基本的使用)

文档地址:

可以设置默认值、起始值等。

二、源码

其实这个源码没有什么可研究的,因为 rax 的实现和自己去实现的思想是差不多的,这在许多拥有 counter 组件的 web UI 框架中也有类似实现思想。

1、维护的 state

Counter 并不是一个无状态组件,维护了三个状态,其中 count 表示当前的计算值,初始有 props 传入,而 incrementColordecrementColor 则是按钮颜色,如果无法继续点击了,则会更换为静态常量 DISABLE_COLOR


const BOTTOM_COLOR = '#666666';
const DISABLE_BOTTOM_COLOR = '#a1a1a1';

this.state = {
  count: props.value,
  incrementColor: BOTTOM_COLOR,
  decrementColor: BOTTOM_COLOR,
};

2、increment 方法和 decrement 方法

increment 方法和 decrement 方法差不多,只介绍一个方法的实现

increment 方法是在按钮 press 的时候触发,主要完成如下流程:

  • 判断 count 是否比 props.end
  • 如果没有超出 end,则执行增加操作
  • 执行完增加操作后,触发 onChange
  • 执行完增加操作后,判断是否与 props.end 相同,从而绑定新的按钮文字颜色
  • 都完成后,触发 onComplete

需要注意的是,onComplete 类似与生命周期一样,每次完成后都会执行一次回调

decrement 方法则和其差不多,只不过是和 props.start 作比较。

increment = () => {
  let {onComplete, onChange, end} = this.props;
  if (this.state.count < end) {
    this.state.count++;
    onChange && onChange(this.state.count);
    this.state.count == end
      ? this.state.decrementColor = DISABLE_BOTTOM_COLOR
      : this.state.incrementColor = BOTTOM_COLOR;
    this.setState(this.state);
    onComplete && onComplete(this.state.count);
  }
}

3、内容渲染

根据 rax-counter 的功能,其实主要就是两个按钮(使用 Touchable 实现),和中间一个 <Text>,其中两个 Touchable 中也需要 <Text> 装填按钮 +/- 字符。

三、实践

rax-counter 本身可定制的样式非常少,而且样式不能通过 props 传递,可能是样式太多了。

1、代码

import {createElement, Component} from 'rax';
import View from 'rax-view';
import Text from 'rax-text';
import Counter from 'rax-counter';
import styles from './App.css';
class App extends Component {
  state = {
    val:1,
    completed:false
  }
  changeHandle = (val) => {
    this.setState({
      val
    });
  }
  completeHandle = (val) => {
    this.setState({
      completed:!this.state.completed
    });
  }
  render() {
    return (
      <View style={styles.app}>
      <Text>值:{this.state.val}</Text>
      <Text>completed {this.state.completed}</Text>
       <Counter 
        style={styles.counter}
        value={1}
        end={10}
        start={0}
        onChange={this.changeHandle}
        onComplete={this.completeHandle}
       ></Counter>
      </View>
    );
  }
}
export default App;

2、效果

GIF.gif