一、需求

rax 本身是有一个 Button 组件,但是我很不喜欢这个组件,因为什么样式都没有,或者说自带的样式非常丑,需要自己去写样式。

其实我觉得 Rax 定位有点尴尬,和 React 是不一样的,他作为一种 weex 的 DSL,本身并不是一种语言框架,因此他自带了很多默认的组件,这些组件只需要自己去实现样式就可以,在多容器环境下运行性能也不错。

然而相比于其他的组件库,又显得太弱了,可能是出于深度定制的考虑,没办法直接作为一个 UI 组件库来使用。

对我来说,rax 很多组件都需要重写,如果为了使用 rax 进行组件重用,基本上组件都可以重写。

这里只是用 Button 组件举个例子,基于 rax-touchable 开发一个 rax 的 Button 组件。

二、Button 组件的规划

Button 组件主要是为了复用,以及不需要进行基本的样式设置。

最终样式如下:

1.jpg

因为只是举例,所有的配色和功能我是照着 bootstrap 的 button 的样式弄的。

作为可复用的组件,除了基本的样式外,一些 prop 规划如下:

prop类型默认描述
typeStringdefault按钮类型,可选值为上图,默认 default
radiusBooleanfalse是否是圆角按钮
btnStyleObject{}自定义按钮样式,级别最高,会覆盖之前的样式
textStyleObject{}自定义文字样式,级别最高,会覆盖默认样式
onPressFunction()=>{}按钮点击事件

三、实现 Button 组件

基本的样式不重复,可以具体看 github 上的代码内容。

1、组件的 Render 方法

  render() {
    const {onPress, textStyle, btnStyle} = this.props;
    const {initBtnType, specTextsStyle, initRadius} = this;
    return (
      <Touchable
        onPress={onPress}
        style={[styles.raxBtn, initBtnType(), initRadius(), btnStyle]}>
        <Text style={[styles.raxBtnText, specTextsStyle(), textStyle]}>
          {this.props.children}
        </Text>
      </Touchable>
    );
  }

可以看到,在 <Touchable>style 是由四部分组成的, style={[styles.raxBtn, initBtnType(), initRadius(), btnStyle]}>,第一部分是按钮的默认样式,第二个是根据 type 覆盖,第三个是判断圆角的样式,第四个是用户自定义传入的样式,可以发现,用户自定义的样式是会覆盖掉组件默认样式。

除了获取到的 props 内容,还有三个方法分别是 initBtnType, specTextsStyle, initRadius

2、根据 type 返回不同类型样式

根据 type 返回对应的 style,(这点上来说,react 语法和 vue 语法相比繁琐很多,vue 一个 computed 就解决了)。

// type
  initBtnType = () => {
    switch (this.props.type) {
      case 'primary':
        return styles.primary;
        break;
      case 'warning':
        return styles.warning;
        break;
      case 'secondary':
        return styles.secondary;
        break;
      case 'info':
        return styles.info;
        break;
      case 'danger':
        return styles.danger;
        break;
      default:
        return styles.
      default;
        break;
    }
  }

3、 圆角样式

 // radius
  initRadius = () => {
    const {radius} = this.props;
    return radius
      ? styles.radius 
      : {};
  }

4、单独处理 warning 和 default 的样式

warning 和 default 需要字体是黑色的,需要单独处理一下。

 // default warning textColor默认是 #000000 但是依旧会被 textStyle 覆盖
  specTextsStyle = () => {
    const {type} = this.props;
    return type === 'warning' || type === 'default'
      ? styles.default
      : {};
  }

四、使用组件

引入组件之后,直接使用即可:

<Button type="default" btnStyle={styles.btnStyle} radius={true} onPress={this.clickHandle}>default</Button>

<Button type="warning" btnStyle={styles.btnStyle}  radius={true} onPress={this.clickHandle}>warning</Button>

<Button type="primary" btnStyle={styles.btnStyle}  radius={true} onPress={this.clickHandle}>primary</Button>

<Button type="danger" btnStyle={styles.btnStyle} onPress={this.clickHandle}>danger</Button>

<Button type="secondary" btnStyle={styles.btnStyle} onPress={this.clickHandle}>secondary</Button>

<Button type="info" btnStyle={styles.btnStyle} onPress={this.clickHandle}>info</Button>

五、github

把代码放到了 github 和 gitosc 上,主要是一种思路,包括其他组件也可以自己进行封装。

github:

gitosc: