初探react-native(当前仅基于ios)

一. 环境搭建(当前为mac)

需要安装的依赖有:Node(v10版本以上),WatchMan,React Native以及Xcode。

Node,Watchman

官方推荐的是用HomeBrew来安装WatchMan

brew install watchman

Node建议更改npm镜像

npm config set registry https://registry.npm.taobao.org --global

npm config set disturl https://npm.taobao.org/dist --global

Yarn、React Native 的命令行工具(react-native-cli)

React Native 的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务

npm install -g yarn react-native-cli

安装完 yarn 后同理也要更改镜像源:

yarn config set registry https://registry.npm.taobao.org --global

yarn config set disturl https://npm.taobao.org/dist --global

Xcode

mac的话可以去app store一键进行安装

初始化一个Demo

使用 React Native 命令行工具来创建一个名为"AwesomeProject"的新项目,init 命令默认会创建最新的版本。

react-native init AwesomeProject

在这个阶段可能会在CocoaPods安装相关依赖时卡住,因为其仓库不在国内,可以尝试更换成国内镜像,更换之后直接切换当前目录,启动项目。

cd AwesomeProject

react-native run-ios

如若遇到以下错误,可以尝试切换设备型号


image
react-native run-ios --simulator="iPhone 11"

如下所示,我们的环境就已经搭建好了。


image

二. react-native布局

react-native使用的布局模式是FlexBox,不过值得注意的是它跟我们之前所接触的css3的FlexBox还是有所不同的。
  • flexDirection : react-native默认为 'column',而在css3中默认为 'row'。
  • alignItems : react-native中默认为 'stretch',而在css3中默认为 'flex-start'。
  • react-native中flex不接受多参数,不像css3中类似这种:flex: 2 2 20%。
  • 不支持的属性: align-content,flex-basis,order,flex-flow,flex-shrink。
其他的就给一张图参考下吧
Flex.jpg

三. navigation 导航器

1. 相关依赖安装

进入当前初始化好的react-native项目,我们首先得安装react-navigation,以及navigation所依赖的第三方库,并将其关联至react-native。这边我是通过yarn包管理器进行安装的:

yarn add react-navigation

yarn add react-native-gesture-handler

react-native link react-native-gesture-handler 

// 我这里ReactNative版本是0.6x的,所以最后一步link操作略不同,如下所示:
cd ios 

pod install

cd..

2. 路由创建及切换

在ReactNative中使用createStackNavigator()来配置路由,这个方法接收一个路由对象参数。假设我们对Home唯一的路由配置是页面组件,我们不需要使用{screen:HomeScreen}配置格式,可以直接使用页面组件。通过initialRouteName我们可以设置默认路由。而createAppContainer()这个函数返回的是一个React组件,并将createStackNavigator创建的 React 组件 作为参数,可以直接从App.js 导出,用作我们应用程序的根组件。

import {createAppContainer} from 'react-navigation';

import {createStackNavigator} from 'react-navigation-stack';

const AppNavigator = createStackNavigator(
  {
    Home: HomeScreen,
    Details: DetailsScreen,
  },
  {
    initialRouteName: 'Home',
  },
);

export default createAppContainer(AppNavigator);
路由间的切换使用this.props.navigation.navigate('XXX'),如下所示:
  • this.props.navigation:navigation通过prop 传递给每个在 stack navigator 中定义的屏幕组件。
  • navigate('Details'):navigator()里面所传参数就是用户定义的路由名,支持第二个参数作为跳转路由携带的参数。
  • this.props.navigation.getParam(): 通过这个方法可以读取参数。
点击跳转至与当前所处路由相同,参数不同的业务场景:

因为当前机制识别跳转路由与当前路由相同时,不会做任何操作,我们需要使用push来进行实现。

this.props.navigation.push('Details', {
      itemId: Math.floor(Math.random() * 100),
})

3. 导航头

导航头Bar配置

通过navigationOptions这个静态属性对其进行配置,可以返回一个静态对象,也可以通过返回方法动态实现。

  • 静态方式
static navigationOptions = {
    title: 'Home',
  };
  • 动态方式
static navigationOptions = ({navigation}) => {
    return {
      title: navigation.getParam('otherParam', 'zwzwzw'),
    };
  };
  render() {
    return (
      
        Home Screen
        

头部样式:

  • 全部路由共享的默认样式
const AppNavigator = createStackNavigator(
  {
    Home: HomeScreen,
    Details: DetailsScreen,
  },
  {
    initialRouteName: 'Home', 
    defaultNavigationOptions: {
      headerStyle: {
        backgroundColor: '#f4511e', // header外层view的样式,这里设置的为bar的背景色
      },
      headerTintColor: '#fff', // 返回按钮和标题都使用这个属性作为它们的颜色
      headerTitleStyle: {
        fontWeight: 'bold', // 如果我们想为标题定制fontFamily,fontWeight和其他Text样式属性,我们可以用它来完成。
      },
    },
  },
);
  • 覆盖默认样式
static navigationOptions = ({navigation, navigationOptions}) => {
    const {params} = navigation.state;
    return {
      title: params ? params.otherParam : 'detail页面',
      headerStyle: {
        backgroundColor: navigationOptions.headerTintColor,
      },
      headerTintColor: navigationOptions.headerStyle.backgroundColor,
    };
  };
  • 使用自定义样式(参考官方文档案例,引用图片组件)
class LogoTitle extends React.Component {
  render() {
    return (
      
    );
  }
}

class HomeScreen extends React.Component {
  static navigationOptions = {
    // headerTitle instead of title
    headerTitle: () => ,
  };
}
  • 标题按钮

IOS 上的后退按钮使用的标题字符串, 或 null 禁用标签。 默认为上一个场景的 headerTitle

从下图可以发现返回按钮为上一个页面的title,所以我们得对其覆盖。


image.png
StackNavigator({
  A: {
    screen: AScreen,
    navigationOptions: () => ({
      title: `zwzwzw`,
      headerBackTitle: null, //对其重写或自定义
    }),
  },
  B: {
    screen: BScreen,
    navigationOptions: () => ({
      title: `anything you want here`,
    }),
  },
});

至于头与页面之间的交互可以参考官方文档计数器案例。

modal堆栈

我理解的modal堆栈就是重新使用createStackNavigator()方法创建一个新的stackNavigator,然后将之前的页面stackNavigator嵌套进去,如下所示:

const RootStack = createStackNavigator(
  {
    Main: {
      screen: MainStack,
    },
    MyModal: {
      screen: ModalScreen,
    },
  },
  {
    mode: 'modal', // modal的进入样式,ios默认为modal,由下而上,card则为左右切换样式。
    headerMode: 'none', // 头部样式,这样写的话是全屏模式。
  }
);

modal的样式很像苹果手机的激活提示,由下而上弹出请激活。

列表组件

1.FlatList

这是一个简单的高性能列表组件,直接上个简单的例子,熟悉一些基础的组件属性:

const CITY_NAME = ['益阳', '株洲', '长沙', '湘潭', '宁乡'];
class DetailsScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      data: CITY_NAME,
    };
  }
  static navigationOptions = ({navigation, navigationOptions}) => {
    const {params} = navigation.state;
    return {
      title: params ? params.otherParam : 'detail页面',
      headerStyle: {
        backgroundColor: navigationOptions.headerTintColor,
      },
      headerTintColor: navigationOptions.headerStyle.backgroundColor,
    };
  };

  _renderItem(data) {
    return (
      
        {data.item}
      
    );
  }

  loadData(flag) {
    if (flag) {
      this.setState({
        loading: true,
      });
    }

    setTimeout(() => {
      let arr = [];
      if (flag) {
        for (let i = this.state.data.length - 1; i >= 0; i--) {
          arr.push(this.state.data[i]);
        }
      } else {
        arr = this.state.data.concat(CITY_NAME);
      }

      this.setState({
        data: arr,
        loading: false,
      });
    }, 2000);
  }

  genIndicator() {
    return (
      
        
        正在加载更多...
      
    );
  }

  render() {
    const {navigation} = this.props;
    return (
      
         this._renderItem(data)}
          refreshControl={                            //下拉刷新
             {                    //刷新状态控制
                this.loadData(true);
              }}
            />
          }
          ListFooterComponent={() => this.genIndicator()}      //底部加载更多样式实现
          onEndReached={() => this.loadData()}                      //触底后进行的操作
        />
      
    );
  }
}
基本样式
image.png

image.png

2. SectionList

sectionList的使用方式跟FlatList差不多,区别在于接受的数据源的属性以及数据源的类型不同。

  • sectionList的数据源实例
const CITY_NAME = [
  {data: ['益阳', '株洲', '长沙', '湘潭', '宁乡'], title: '湖南'},
  {data: ['虎门', '广州', '河源'], title: '广东'},
];
  • 接收数据源的属性
sections={this.state.data}
  • title渲染属性
renderSectionHeader={data => this._renderHeader(data)} // 组标题渲染

// 以下为方法
  _renderHeader({section}) {
    return (
      
        {section.title}
      
    );
  }
  • 分割线属性
 ItemSeparatorComponent={() => } // 分割线样式

// 样式设置
 separator: {
    height: 1,
    backgroundColor: 'gray',
    flex: 1,
  },
下面是粗糙成品(有点丑哈哈哈)
image.png

本来研究下了swipeableList的,不过0.61的react-native库源码中没有相关引入,只能空闲时候研究下原因然后下次笔记补上~

你可能感兴趣的:(初探react-native(当前仅基于ios))