React-Native开发学习之基础部分

背景

世界杯期间开始了从安卓开发转到了React-Native开发的学习,现在记录一下学习过程。基本上都是参考React-Native的中文文档,链接如下:

https://reactnative.cn/docs/0.31/getting-started.html#content

我的开发环境是mac,并且之前已经安装了homeBrew、Android Studio,并且已然把AS的sdk目录添加到了环境变量$PATH中


搭建环境

1、安装node

brew install node

2、设置npm镜像

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

3、安装react-native-cli

npm install -g react-native-cli

4、安装watchman、flow

brew install watchman
brew install flow

5、新建目录,初始化项目

react-native init StudyOfRNListView

StudyOfRNListView是个项目名,随便取就行,这条命令执行完会在当前目录下,生成一个StudyOfRNListView文件夹,里面就是RN项目框架

这个过程可能很慢,不愿意等的可以直接从网上把别人的项目拷下来,把里面的逻辑代码都删掉

6、在StudyOfRNListView/android根目录下,新建local.properties文件,把sdk目录填进去,示例如下

sdk.dir=/Users/songzeceng/Library/Android/sdk

7、运行项目

这时要保证一个android手机或avd已经连接

cd StudyOfRNListView
react-native run-android

不出意外的话,应用就已经安装好了,点击就能运行



修改App.js

打开StudyOfRNListView目录,目录结构如下


主界面是index.js,内容如下

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('StudyOfRNListView', () => App);

第一行从react-native里导入了AppRegistry,用{}扩起来是为了在后面可以作为一个对象使用

第二行从当前目录下的App导入了App(其实就是复制粘贴,但没有{}扩住,就不能调用里面的东西)

第三行是注册组件,组件名是App,然后把它作为StudyOfRNListView的入口类


而后我们就打开App.js,把里面的内容删到只剩下

import React, {Component} from 'react';
import {
    AppRegistry,
    Text
} from 'react-native';


class StudyOfRNListView extends Component {
    render() { // render()方法用来渲染UI
        
    }
}

这样,应用就只剩下一个白板,我们开始正儿八经学习rn,而主要的改动,就是在这个App.js里面,以StudyOfRNListView为中心进行的

每修改一些东西,晃一晃手机,就会显示菜单,选择reload就可以刷新界面(avd的话,直接在键盘上双击r就可以刷新)


如果reload报错,说连不上服务器,可以先登录这个网站看看出错原因:

http://localhost:8081/index.android.bundle?platform=android

如果显示是找不到index.android.js,解决方法可以参考这篇文章,也就是重启服务器并清空缓存,然后在另一个命令行下,启动项目


显示图片

首先要从react-native中导入Image

import React, {Component} from 'react';
import {
    AppRegistry,
    Text,
    Image
} from 'react-native';

然后把StudyOfRNListView改成下面的样子

export default class App extends Component<Props> {
  render() {
    let pic = {
        uri: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=746951351,3068781139&fm=200&gp=0.jpg" // 注意是uri,不是url,这里赋值用:
    }
    return (
      <View>
        <Image source={pic} style={{width:200, height:200}}></Image> // source指定数据源,style用来指定样式
      </View>
    );
  }
}
效果如下



自定义模块

rn支持我们自定义模块类,方才说的StudyOfRNListView相当于一个主模块类

定义一个城市名的模块类,可以是这样:

class City extends Component { // 模块类必须继承自Component
    render() { // 至少要有一个render方法,这个方法用来渲染UI
        return ( // return的就是我们想要渲染的东西
            <Text>{this.props.name}</Text> // <Text>用来显示文字,开始标签和结束标签之间的内容表示显示的是props.name,这个我们可以在使用的时候指定
        );
    }
}

这里用到了属性props,这个东西一经设定就不能再改了,相应的可以改动的是状态state.

然后我们可以在主模块类StudyOfRNListView中使用

export default class App extends Component<Props> {
    render() {
        let pic = {
            uri: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=746951351,3068781139&fm=200&gp=0.jpg"
        }
        return (
            <View>
                <Image source={pic} style={{width: 200, height: 200}}></Image>
                <City name={"安阳"}/>
                <City name={"新乡"}/>
                <City name={"洛阳"}/>
            </View>
        );
    }
}

效果如下



state的使用-定时闪烁

属性一经设定不能再变,但状态可以。

新建一个组件Blink,添加构造方法和render方法如下

class Blink extends Component {
    constructor(props) {
        super(props); // 必须先调用父类构造方法
        this.state = {showText: true}; // 设定初始化state

        setInterval(() => { // 设置间隔的函数
            this.setState({showText: !this.state.showText}); // 参数1:回调函数,内容:setState()用来设置state,把showText取反
        }, 1000); // 参数2:间隔时间
    }

    render() {
        let display = this.state.showText ? "黄埃散漫风萧索,云栈萦纡登剑阁" : ""; // 根据state里的showText决定显示内容
        return (
            <Text>{display}</Text> // 显示display
        );
    }
}

在主模块调用

export default class App extends Component<Props> {
    render() {
        let pic = {
            uri: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=746951351,3068781139&fm=200&gp=0.jpg"
        }
        return (
            <View>
                <Image source={pic} style={{width: 200, height: 200}}></Image> // rn里的尺寸都是无单位的逻辑像素点,和设备无关
                <City name={"安阳"}/>
                <City name={"新乡"}/>
                <City name={"洛阳"}/>
                <Blink/> // 调用Blink
            </View>
        );
    }
}

效果



样式

我们可以向css那样自定义样式,调用的是StyleSheet.create()方法,所以要事先从'react-native'中导入StyleSheet

import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';

然后就可以自定义样式了,格式是json格式

const styles = StyleSheet.create({
    bigBlue: {
        color: "blue",
        fontWeight: "bold",
        fontSize: 30
    },

    red: {
        color: "red",
    }
});

样式在使用的时候,可以以数组的形式传入,在以数组的形式传入时,后面元素会覆盖前面的元素(当然只有相同类型的元素才会覆盖)

先在主模块里调用:

export default class App extends Component<Props> {
    render() {
        return (
            <View>
                <Text style={styles.bigBlue}>蓝色大号</Text>
                <Text style={styles.red}>红色</Text>
                <Text style={[styles.bigBlue, styles.red]}>蓝色大号,红色</Text> // 数组形式,先传入bigBlue,再传入red
                <Text style={[styles.red, styles.bigBlue]}>红色,蓝色大号</Text> // 数组形式,先传入red,再传入bigBlue
            </View>
        );
    }
}

效果



flexBox

flexBox用来指定子结点的展示形式,以根结点为例,用法如下

class StudyOfRNListView extends Component {
    render() { // render()方法用来渲染UI
        let pic = {
            uri: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=746951351,3068781139&fm=200&gp=0.jpg'
        };
        return ( // return的内容就是渲染的内容
            <View style={{
                alignItems: 'center',
                flex: 1,
                // flex是权重
                flexDirection: 'row',
                // flexDirection是排列方向,排成一列column或者排成一排row
                flexWrap: 'wrap',
                // flexWrap:内容包裹形式。nowrap:不换行,此为默认 wrap:换行,wrap-reverse:换行,第一行在下面
                justifyContent: 'space-around'
                // justifyContent意为内容的分布方式,可选项有:flex-start、center、flex-end、space-around、space-between
                // 以横向排列为例,意思依次是左对齐,居中,右对齐,每个子项两侧间隔相等(所以不会靠两侧),每个子项之间的间隔相等(所以会靠两侧)
            }}>
                <Image source={pic} style={{width: 200, height: 200}}/>
                <City name='安阳' fontSize={50}/>
                <City name='新乡' fontSize={30}/>
                <City name='洛阳' fontSize={20}/>
                <Text style={styles.red}>红色</Text>
                <Text style={styles.bigBlue}>蓝色大号</Text>
                <Text style={[styles.red, styles.bigBlue]}>红色、蓝色大号</Text>
                <Text style={[styles.bigBlue, styles.red]}>蓝色大号、红色</Text>
            </View>
        );
    }
}

效果如下



处理输入

正如Android里面的EditText一样,RN里面专门用来让用户输入的组件叫做TextInput,里面可以设置默认文字,事件处理等。

自定义一个组件,用来显示用户输入的内容

class CityInput extends Component {
    constructor(props) {
        super(props);
        this.state = {text: ""}; // 默认text是空
    }

    render() {
        return (
            <View>
                <TextInput
                    style={{height: 40}}
                    placeholder={"输入你要去的城市"} // 占位字符串
                    // onChangeText={ // 输入内容有变时调用
                    //     (text) => this.setState({text})
                    // }
                    onSubmitEditing={ // 按下软键盘上的确认键后调用,参数是event
                        (event) => this.setState({text:event.nativeEvent.text})
                        // 通过调用event.nativeEvent.text获取输入的字符串
                    }
                ></TextInput>

                <Text style={{padding: 10, fontSize: 30}}>
                    {
                        this.state.text.split('-').map( // split函数:分割,map函数:转换
                            (str) => "那就去" + str
                        ).join('\n') // 字符串拼接
                    }
                </Text>
            </View>
        );
    }
}

主模块中调用

export default class App extends Component<Props> {
    render() {
        return (
            <View style={{
                alignItems: 'center',
                flex: 1,
                // flex是权重
                flexDirection: 'row',
                // flexDirection是排列方向,排成一列column或者排成一排row
                flexWrap: 'wrap',
                // flexWrap:内容包裹形式。nowrap:不换行,此为默认 wrap:换行,wrap-reverse:换行,第一行在下面
                justifyContent: 'space-around'
                // justifyContent意为内容的分布方式,可选项有:flex-start、center、flex-end、space-around、space-between
                // 以横向排列为例,意思依次是左对齐,居中,右对齐,每个子项两侧间隔相等(所以不会靠两侧),每个子项之间的间隔相等(所以会靠两侧)
            }}>
                <CityInput/>
            </View>
        );
    }
}

效果



结语

这是rn最基本的使用,下面我会记录rn中ListView及其他东西的用法

猜你喜欢

转载自blog.csdn.net/qq_37475168/article/details/80733358