美文网首页javascriptf8app
F8app代码学习的要点(3)-button组件

F8app代码学习的要点(3)-button组件

作者: smartphp | 来源:发表于2016-10-27 19:26 被阅读328次

    Button组件
    路径:f8app/js/common/Button.js
    Button组件很简单,但是也用到了很多子组件,一个一个来看看

     /*f8app/js/common/Button.js*/
      'use strict';
    var F8Colors = require('F8Colors');//引入颜色常量
    var Image = require('Image');//image组件
    var LinearGradient = require('react-native-linear-gradient');//渐变色组件,github登录按钮的样式
    var React = require('React');
    var StyleSheet = require('StyleSheet');
    var { Text } = require('F8Text'); //f8app包装的组件,打包了一些和文本有关的子组件
    var TouchableOpacity = require('TouchableOpacity');//相当于bootstrap的button组件。
    var View = require('View');
    
    class F8Button extends React.Component {
      props: {  //属性的类型检测
        type: 'primary' | 'secondary' | 'bordered';
        icon: number;
        caption: string;
        style: any;
        onPress: () => void;
      };
    
      render() {
        const caption = this.props.caption.toUpperCase();
        let icon;
        //如果传入图片的属性,则使用这个属性,icon是图标,caption是按钮的文字
        if (this.props.icon) {
          icon = <Image source={this.props.icon} style={styles.icon} />;
        }
        let content;
        if (this.props.type === 'primary' || this.props.type === undefined) {
          content = (
            <LinearGradient
              start={[0.5, 1]} end={[1, 1]}
              colors={['#6A6AD5', '#6F86D9']}
              style={[styles.button, styles.primaryButton]}>
              {icon}
              <Text style={[styles.caption, styles.primaryCaption]}>
                {caption}
              </Text>
            </LinearGradient>
          );
        } else {
          var border = this.props.type === 'bordered' && styles.border;
          content = (
            <View style={[styles.button, border]}>
              {icon}
              <Text style={[styles.caption, styles.secondaryCaption]}>
                {caption}
              </Text>
            </View>
          );
        }
        return (
          <TouchableOpacity
            accessibilityTraits="button"
            onPress={this.props.onPress}
            activeOpacity={0.8}
            style={[styles.container, this.props.style]}>
            {content}
          </TouchableOpacity>
        );
      }
    }
    
    const HEIGHT = 50;
    
    var styles = StyleSheet.create({
    //...看源码,此处省略
    });
    
    module.exports = F8Button; 
    
    

    F8Text组件

    /*f8app/js/common/F8Text.js*/
    'use strict';
    
    import React, {StyleSheet, Dimensions} from 'react-native';
    import F8Colors from 'F8Colors';
    //封装text
    export function Text({style, ...props}: Object): ReactElement {
      return <React.Text style={[styles.font, style]} {...props} />;
    }
    //封装标题
    export function Heading1({style, ...props}: Object): ReactElement {
      return <React.Text style={[styles.font, styles.h1, style]} {...props} />;
    }
    //段落内容主体
    export function Paragraph({style, ...props}: Object): ReactElement {
      return <React.Text style={[styles.font, styles.p, style]} {...props} />;
    }
    //使用Dimensions组件获取实际硬件的宽度
    const scale = Dimensions.get('window').width / 375;
    //根据实际硬件宽度放大得到实际尺寸的动态缩放
    function normalize(size: number): number {
      return Math.round(scale * size);
    }
    
    const styles = StyleSheet.create({
     
      h1: {
        fontSize: normalize(24),  //normalize函数的使用。
        lineHeight: normalize(27),
        color: F8Colors.darkText,
        fontWeight: 'bold',
        letterSpacing: -1,
      }
      //省略部分代码
    });
    

    TouchableOpacity 组件封装了ios和android不同的类型

      /*f8app/js/common/F8Touchable.js*/
     'use strict';
    
    import React, {
      TouchableHighlight,
      TouchableNativeFeedback,
      Platform,
    } from 'react-native';
    
    function F8TouchableIOS(props: Object): ReactElement {
      return (
        <TouchableHighlight
          accessibilityTraits="button"
          underlayColor="#3C5EAE"
          {...props}
        />
      );
    }
    //根据动态或的的操作系统加载不同的组件
    const F8Touchable = Platform.OS === 'android'
      ? TouchableNativeFeedback
      : F8TouchableIOS;
    
    module.exports = F8Touchable;
    

    以上几个组件LoginButton组件中使用.
    关键的几个地方:根据状态加载组件的文字,es6的异步竞争操作,redux的connect函数的使用。

    /*f8app/js/common/LoginButton.js*/
    'use strict';
    
    const React = require('react-native');
    const {StyleSheet} = React;
    const F8Button = require('F8Button');
    
    const { logInWithFacebook } = require('../actions'); //loginbutton要dispatch的函数
    const {connect} = require('react-redux'); //connect函数
    
    class LoginButton extends React.Component {
      props: {
        style: any;
        source?: string; // For Analytics
        dispatch: (action: any) => Promise;
        onLoggedIn: ?() => void;
      };
      state: {
        isLoading: boolean;
      };
      _isMounted: boolean;
    
      constructor() {
        super();
        this.state = { isLoading: false };
      }
    
      componentDidMount() {
        this._isMounted = true;
      }
    
      componentWillUnmount() {
        this._isMounted = false;
      }
    
      render() {
    //根据isLoading的状态决定加载那个组件
        if (this.state.isLoading) {
          return (
            <F8Button
              style={[styles.button, this.props.style]}
              caption="Please wait..."
            />
          );
        }
    
        return (
          <F8Button
            style={[styles.button, this.props.style]}
            icon={require('../login/img/f-logo.png')}
            caption="Log in with Facebook"
            onPress={() => this.logIn()}
          />
        );
      }
    //登录的异步操作
      async logIn() {
        const {dispatch, onLoggedIn} = this.props; //通过connect注入的dispatch和onLOggedIN函数
    
        this.setState({isLoading: true});//点击登录按钮,改变isLoading的状态
        try {
          await Promise.race([ //下面两个异步函数式竞争关系,第一个在1.5秒没完成就会执行超时函数tiemout
            dispatch(logInWithFacebook(this.props.source)),//dispatch登录函数
            timeout(15000),//超时函数
          ]);
        } catch (e) {
          const message = e.message || e;
          if (message !== 'Timed out' && message !== 'Canceled by user') {
            alert(message);
            console.warn(e);
          }
          return;
        } finally {
          this._isMounted && this.setState({isLoading: false});
        }
    
        onLoggedIn && onLoggedIn();
      }
    }
    
    async function timeout(ms: number): Promise {
      return new Promise((resolve, reject) => {
        setTimeout(() => reject(new Error('Timed out')), ms);
      });
    }
    
    var styles = StyleSheet.create({
      button: {
        alignSelf: 'center',
        width: 270,
      },
    });
    //connect应该是redux学习的一个难点和突破点,UI组件通过connect
    //可以获取全局的所有的state,redux里面只有一个state树。但是
    //LoginButton的状态是自己决定的,因此没有注入state
    //redux还可接受UI组件的dispatch函数传递的action和相应的实参,
    //如果这里的action和redux的actiontype想匹配就就导致相应的State的改变。
    //这个组件state应该返回登录的token供其他组件来使用。
    module.exports = connect()(LoginButton);
    
    

    相关文章

      网友评论

        本文标题:F8app代码学习的要点(3)-button组件

        本文链接:https://www.haomeiwen.com/subject/lsdsuttx.html