派大星

vuePress-theme-reco 派大星    2021 - 2022
派大星 派大星
主页
博客
  • 前端
  • JavaScript文章
  • 三级目录
  • 笔记
  • 学习笔记
  • 页面
  • CSS
  • HTML
  • 技术
  • 技术文档
  • GitHub技巧
  • 技术笔记
  • 实用工具
  • Nodejs
  • 博客搭建
  • 更多
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • JavaScript
  • 浏览器&网络
  • 前端框架
  • 资源工具
  • 持续集成
  • 小程序
  • 杂谈
  • React
  • Mysql
  • 面试题
  • uniapp
  • 《ES6 教程》笔记
  • 《Git》学习笔记
  • 《JavaScript教程》笔记
  • 《React》笔记
  • 核心概念
  • 高级指引
  • Hook
  • 案例演示
  • 《TypeScript 从零实现 axios》
  • 初识 TypeScript
  • TypeScript 常用语法
  • ts-axios 项目初始化
  • ts-axios 基础功能实现
  • ts-axios 异常情况处理
  • ts-axios 接口扩展
  • ts-axios 拦截器实现
  • ts-axios 配置化实现
  • ts-axios 取消功能实现
  • ts-axios 更多功能实现
  • ts-axios 单元测试
  • ts-axios 部署与发布
  • 《Vue》笔记
  • 基础
  • 组件
  • 过渡&动画
  • 工具
  • 规模化
  • 可复用性&组合
  • 其他
  • Vuex
标签
时间轴
关于
author-avatar

派大星

272

文章

69

标签

主页
博客
  • 前端
  • JavaScript文章
  • 三级目录
  • 笔记
  • 学习笔记
  • 页面
  • CSS
  • HTML
  • 技术
  • 技术文档
  • GitHub技巧
  • 技术笔记
  • 实用工具
  • Nodejs
  • 博客搭建
  • 更多
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • JavaScript
  • 浏览器&网络
  • 前端框架
  • 资源工具
  • 持续集成
  • 小程序
  • 杂谈
  • React
  • Mysql
  • 面试题
  • uniapp
  • 《ES6 教程》笔记
  • 《Git》学习笔记
  • 《JavaScript教程》笔记
  • 《React》笔记
  • 核心概念
  • 高级指引
  • Hook
  • 案例演示
  • 《TypeScript 从零实现 axios》
  • 初识 TypeScript
  • TypeScript 常用语法
  • ts-axios 项目初始化
  • ts-axios 基础功能实现
  • ts-axios 异常情况处理
  • ts-axios 接口扩展
  • ts-axios 拦截器实现
  • ts-axios 配置化实现
  • ts-axios 取消功能实现
  • ts-axios 更多功能实现
  • ts-axios 单元测试
  • ts-axios 部署与发布
  • 《Vue》笔记
  • 基础
  • 组件
  • 过渡&动画
  • 工具
  • 规模化
  • 可复用性&组合
  • 其他
  • Vuex
标签
时间轴
关于

React学习篇章七

vuePress-theme-reco 派大星    2021 - 2022

React学习篇章七

派大星 2021-01-07 React脚手架

# React07

# 回顾

ReactNative 的组件使用

View 组件 根组件 容器组件 没有一些相关样式 color fontSize

Image 组件 图片

image-20220118142919798

Text 文本组件

  • RN 中文本必须放在 Text 组件中
  • 可以修饰文字相关的样式 color fontSize
  • numberOfLines 显示几行 其它隐藏不显示 ...代替

按钮组件

  • button
  • touchableOpacity 透明容器 有点击反馈效果
    • 背景色 填充 圆角
    • 文字使用文本组件 文字大小 颜色 间距

状态栏和背景图

可穿透的状态栏 透明的

背景图 ImageBackground 需要动态获取屏幕的宽高 设置背景的图的宽高

  • 背景图组件标签作为根标签使用,把其它内容都包裹起来

开关和输入框

Switch、TextInput

活动提示器 loading 小图标

登录页面

# RN 学习

# 登录页面完善

// rnc
import React, { Component } from "react";
import {
  Text,
  View,
  StatusBar,
  ImageBackground,
  Image,
  TextInput,
  TouchableOpacity,
  StyleSheet,
  Dimensions,
} from "react-native";
// 获取宽高
const { width, height } = Dimensions.get("window");
// rpx转物理像素  使用 例如: 35rpx rpx(35)
const rpx = (x) => (width / 750) * x;
export default class App extends Component {
  state = { rememberPwd: false };
  // 判断是否记住密码的状态 返回对应的图片地址
  img_remember() {
    return this.state.rememberPwd
      ? require("./assets/check.png")
      : require("./assets/uncheck.png");
  }
  render() {
    return (
      <ImageBackground
        source={require("./assets/bg1.jpg")}
        style={{ width, height }}
        blurRadius={6}
      >
        {/* 沉浸式状态栏 */}
        <StatusBar backgroundColor="transparent" translucent></StatusBar>
        {/* 撑一个高度为状态栏高度的容器 把状态栏的高度部分撑出来 防止状态栏被内容覆盖 */}
        <View style={{ height: StatusBar.currentHeight }}></View>
        {/* 把页面其它内容包裹到容器 */}
        <View style={ss.content}>
          {/* 用户名 */}
          <View style={ss.area_input}>
            <Image
              style={ss.area_input_icon}
              source={require("./assets/user.png")}
            ></Image>
            <TextInput
              style={ss.area_input_text}
              placeholder="用户名"
              placeholderTextColor="white"
            ></TextInput>
          </View>
          {/* 密码 */}
          <View style={[ss.area_input, { marginTop: rpx(30) }]}>
            <Image
              style={ss.area_input_icon}
              source={require("./assets/pwd.png")}
            ></Image>
            <TextInput
              secureTextEntry
              style={ss.area_input_text}
              placeholder="密码"
              placeholderTextColor="white"
            ></TextInput>
          </View>
          {/* 账户操作区域 */}
          <View
            style={{
              marginTop: rpx(30),
              flexDirection: "row",
              justifyContent: "space-between",
            }}
          >
            <View style={{ flexDirection: "row" }}>
              <TouchableOpacity
                style={{ padding: rpx(5) }}
                onPress={() =>
                  this.setState({ rememberPwd: !this.state.rememberPwd })
                }
              >
                <Image
                  source={this.img_remember()}
                  style={{ width: rpx(35), height: rpx(35) }}
                ></Image>
              </TouchableOpacity>
              <Text style={{ fontSize: rpx(35), color: "white" }}>
                记住密码
              </Text>
            </View>
            <TouchableOpacity activeOpacity={0.7}>
              <Text style={{ fontSize: rpx(35), color: "white" }}>
                忘记密码
              </Text>
            </TouchableOpacity>
          </View>
          {/* 登录按钮 */}
          <TouchableOpacity
            activeOpacity={0.7}
            style={{
              backgroundColor: "#55c596",
              paddingVertical: rpx(10),
              alignItems: "center",
              borderRadius: rpx(10),
              marginTop: rpx(50),
            }}
          >
            <Text
              style={{
                color: "white",
                fontSize: rpx(40),
                letterSpacing: rpx(15),
              }}
            >
              登录
            </Text>
          </TouchableOpacity>
          {/* 新用户注册 */}
          <TouchableOpacity
            style={{
              paddingVertical: rpx(10),
              alignItems: "center",
              borderRadius: rpx(10),
              marginTop: rpx(50),
            }}
            activeOpacity={0.7}
          >
            <Text style={{ color: "white", fontSize: rpx(35) }}>
              新用户注册
            </Text>
          </TouchableOpacity>
        </View>
        {/* 其它登录方式 */}
        <View
          style={{
            position: "absolute",
            bottom: rpx(150),
            alignSelf: "center",
          }}
        >
          {/* 文字 */}
          <View style={{ flexDirection: "row", alignItems: "center" }}>
            <View style={ss.line}></View>
            <View>
              <Text
                style={{
                  fontSize: rpx(28),
                  color: "white",
                  marginHorizontal: rpx(20),
                }}
              >
                其它方式登录
              </Text>
            </View>
            <View style={ss.line}></View>
          </View>
          {/* 图标 */}
          <View
            style={{
              marginTop: rpx(30),
              flexDirection: "row",
              justifyContent: "space-around",
              alignItems: "center",
            }}
          >
            <TouchableOpacity activeOpacity={0.7} style={ss.btn_third}>
              <Image
                source={require("./assets/qq.png")}
                style={ss.btn_third_icon}
              ></Image>
            </TouchableOpacity>
            <TouchableOpacity activeOpacity={0.7} style={ss.btn_third}>
              <Image
                source={require("./assets/wx.png")}
                style={ss.btn_third_icon}
              ></Image>
            </TouchableOpacity>
            <TouchableOpacity activeOpacity={0.7} style={ss.btn_third}>
              <Image
                source={require("./assets/phone.png")}
                style={ss.btn_third_icon}
              ></Image>
            </TouchableOpacity>
          </View>
        </View>
      </ImageBackground>
    );
  }
}

const ss = StyleSheet.create({
  content: {
    paddingTop: rpx(200),
    paddingHorizontal: rpx(50),
  },
  area_input: {
    backgroundColor: "rgba(0,0,0,0.4)",
    padding: rpx(10),
    borderRadius: rpx(10),
    flexDirection: "row",
    alignItems: "center",
  },
  area_input_icon: {
    width: rpx(50),
    height: rpx(50),
    marginHorizontal: rpx(20),
  },
  area_input_text: {
    fontSize: rpx(40),
    color: "white",
    flex: 1,
  },
  line: {
    backgroundColor: "#55c596",
    height: 5,
    width: rpx(200),
  },
  btn_third_icon: {
    width: rpx(80),
    height: rpx(80),
  },
  btn_third: {
    backgroundColor: "#55c596",
    borderRadius: rpx(60),
    padding: rpx(10),
  },
});

# 网络请求

// rnc
/***
 * View: 不可以滚动
 *
 * ScrollView: 可以滚动
 *
 * 将接口数据展示到页面上 实现的基本步骤:
 * 发送请求=>接收返回数据=>存储本地=>展示渲染
 *
 */
import React, { Component } from "react";
import { Text, View, Dimensions, Image, ScrollView } from "react-native";
// rpx计算
const rpx = (x) => (Dimensions.get("window").width / 750) * x;
export default class App extends Component {
  // state 组件状态
  state = { result: [] };
  // 组件挂在时触发
  componentDidMount() {
    const url = "https://api.apiopen.top/getWangYiNews";
    // 发送请求调用接口
    fetch(url)
      .then((res) => res.json())
      .then((res) => {
        console.log(res);
        /***
         * RN中 控制台打印的信息  需要在命令行控制台查看
         * 使用起来不方法,RN提供了debug调试模式
         * 注意:调试模式目前还不是太稳定,需要时候打开它,不使用的时候关闭。否则,会出现一些奇怪的问题。异常的报错,一些功能异常失效。
         * 调试模式打开方式:
         * 1.cmd里 敲d 打开开发者菜单
         * 2.模拟器里选择菜单  debug
         * 3.浏览器弹出debug ui工具
         * 打开console就可以看到打印信息了
         *
         * 关闭和打开过程类似 先cmd里敲d 模拟器选择stopping dugging
         *
         *  */
        this.setState({ result: res.result });
      });
  }
  showNews() {
    return this.state.result.map((item, index) => {
      return (
        <View
          key={index}
          style={{ flexDirection: "row", borderBottomWidth: 1 }}
        >
          <Image
            source={{ uri: item.image }}
            style={{ width: rpx(250), height: rpx(150) }}
          ></Image>
          <View style={{ flex: 1, justifyContent: "space-between" }}>
            <Text style={{ fontSize: rpx(25) }}>{item.title}</Text>
            <Text style={{ fontSize: rpx(25) }}>{item.passtime}</Text>
          </View>
        </View>
      );
    });
  }
  render() {
    return (
      // 用ScrollView替换原来的View 使页面可以滚动
      <ScrollView>
        {/* 调用方法 实现页面的展示 */}
        {this.showNews()}
      </ScrollView>
    );
  }
}

# FlatList

高能性能列表组件,提供了多个属性使用。方便开发者快速开一些功能。

# 核心属性

FlatList 三个核心属性:

  • data 需要显示的数组数据
  • renderItem 数组每个元素对应的 UI 界面标签和样式
  • keyExtractor 每一个 UI 标签的唯一标识
// rnc
import React, { Component } from "react";
// 导入组件FlatList
import { Text, View, FlatList } from "react-native";

export default class App extends Component {
  skills = [
    "Vue",
    "React",
    "Angular",
    "HTML",
    "CSS",
    "JavaScript",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
    "测试1",
    "测试2",
  ];
  render() {
    return (
      // FlatList 核心属性
      // data 遍历的数据
      // renderItem 处理每个元素的标签和样式 调用方法为了和属性的名称进行区分 习惯加_
      // keyExtractor 唯一值key 渲染时提供效率

      <FlatList
        data={this.skills}
        renderItem={this._renderItem}
        keyExtractor={(item, index) => index}
      ></FlatList>
    );
  }
  // 传入的参数是每一个数组元素的对象形式
  // {index,item} 把传入的数据进行了解构 只获取item和index
  _renderItem = ({ index, item }) => (
    <Text style={{ fontSize: 35 }}>
      {index + 1}、{item}
    </Text>
  );
  // one是数组中每个数据项  传入的是对象形式 后续解构使用
  _renderItem1 = (one) => {
    console.log(one);
    const { index, item } = one;
    return (
      <Text style={{ fontSize: 35 }}>
        {index}。{item}
      </Text>
    );
  };
}

# 可选属性

ItemSeparatorComponent 行与行之间的分隔组件

ListHeaderComponent 显示到 FlatList 组件头部

ListFooterComponent 显示到 FlatList 组件尾部

// rnc
import React, { Component } from "react";
import { FlatList, Text, View } from "react-native";
/***
 * 通过FlatList 遍历显示数组对象数据
 * 核心属性:
 * data 数据
 * renderItem 每一个元素标签样式
 * keyExtractor key 唯一值
 * 可选属性  不是必需的 使用可以实现一些效果
 * ItemSeparatorComponent  行与行之间的分隔组件
 * ListHeaderComponent  显示到FlatList组件头部
 * ListFooterComponent  显示到FlatList组件尾部
 *
 *
 *
 */

export default class App extends Component {
  heros = [
    { name: "后羿", job: "射手", price: 3888 },
    { name: "孙尚香", job: "射手", price: 6888 },
    { name: "廉颇", job: "游走", price: 13888 },
    { name: "韩信", job: "打野", price: 13888 },
    { name: "扁鹊", job: "法师", price: 8888 },
  ];
  render() {
    return (
      <FlatList
        data={this.heros}
        renderItem={this._renderItem}
        keyExtractor={(item, index) => index}
        ItemSeparatorComponent={this._ItemSeparatorComponent}
        ListHeaderComponent={this._ListHeaderComponent}
        ListFooterComponent={this._ListFooterComponent}
      ></FlatList>
    );
  }
  // 尾部组件
  _ListFooterComponent() {
    return (
      <Text style={{ fontSize: 35, color: "green" }}>本场红方英雄为5个</Text>
    );
  }
  // 头部组件
  _ListHeaderComponent = () => (
    <Text style={{ fontSize: 35, color: "red" }}>本局红方阵容:</Text>
  );
  // 分隔组件
  _ItemSeparatorComponent = () => (
    <View style={{ height: 3, backgroundColor: "gray" }}></View>
  );
  _renderItem = ({ item }) => {
    return (
      <View>
        <Text style={{ fontSize: 30 }}>名称:{item.name}</Text>
        <Text style={{ fontSize: 30 }}>职业:{item.job}</Text>
        <Text style={{ fontSize: 30 }}>价格:{item.price}</Text>
        {/* <View style={{height: 3, backgroundColor: 'gray'}}></View> */}
      </View>
    );
  };
}

# 加载更多、下拉刷新、回到顶部

// rnc
import React, { Component } from "react";
import {
  Text,
  View,
  FlatList,
  Dimensions,
  Image,
  ActivityIndicator,
  TouchableOpacity,
} from "react-native";
const { width, height } = Dimensions.get("window");
const rpx = (x) => (width / 750) * x;
export default class App extends Component {
  // data 接口返回数据 refreshing 下拉刷新状态 showBtn 回到顶部显示状态
  state = { data: null, refreshing: false, showBtn: false };
  url(page = 1) {
    return "https://api.jiasiyuan.cn/news?page=" + page;
  }
  componentDidMount() {
    fetch(this.url())
      .then((res) => res.json())
      .then((res) => {
        console.log(res);
        // 详细格式化的数据 可以通过调试模式
        this.setState({ data: res });
      });
  }
  render() {
    // 判断远程数据未返回时,不渲染
    if (this.state.data === null) return <View></View>;
    return (
      <View>
        <FlatList
          data={this.state.data.result}
          renderItem={this._renderItem}
          keyExtractor={(item, index) => index}
          ItemSeparatorComponent={this._ItemSeparatorComponent}
          ListHeaderComponent={this._ListHeaderComponent}
          ListFooterComponent={this._ListFooterComponent}
          // 触底事件
          onEndReached={this._onEndReached}
          // 触底的阈值 未显示高度的百分比 默认是50% 触发太早了,习惯上修改为10%
          onEndReachedThreshold={0.1}
          // 下拉刷新事件
          onRefresh={this._onRefresh}
          // 刷新动画动态 bool类型 true为刷新 false为不刷新
          refreshing={this.state.refreshing}
          // 监控滚动
          onScroll={this._onScroll}
          // 子元素组件方法的调用 需要先绑定ref
          // el 当前FlatList组件标签
          // f1 代表绑定的变量
          ref={(el) => (this.f1 = el)}
        ></FlatList>
        {/* 回到顶部按钮 */}
        {/* 根据判断showBtn 确定是否显示按钮 */}
        {this.state.showBtn ? (
          <TouchableOpacity
            onPress={() => this.f1.scrollToIndex({ index: 0 })}
            activeOpacity={0.7}
            style={{
              position: "absolute",
              bottom: rpx(100),
              right: rpx(50),
              backgroundColor: "red",
              padding: rpx(10),
              borderRadius: rpx(10),
            }}
          >
            <Text style={{ fontSize: rpx(30), color: "white" }}>回到顶部</Text>
          </TouchableOpacity>
        ) : null}
      </View>
    );
  }
  // 监控滚动事件处理方法
  _onScroll = (e) => {
    // 获取竖向滚动距离  和顶部的距离
    // RN的事件处理方式  经过特殊处理的 如果需要打印其中的值  需要在之前调用persist()
    // e.persist();
    // console.log(e.nativeEvent.contentOffset.y);
    // 距离1500以上时  showBtn为true 显示按钮
    this.setState({ showBtn: e.nativeEvent.contentOffset.y > 1500 });
  };
  // 下拉刷新事件处理方法
  _onRefresh = () => {
    console.log("下拉刷新触发了");
    // 下拉之后loading加载 当下拉数据返回之后,再修改为false关闭
    this.setState({ refreshing: true });
    fetch(this.url())
      .then((res) => res.json())
      .then((res) => {
        console.log(res);
        this.setState({ data: res, refreshing: false });
      });
  };
  // 触底事件处理方法
  _onEndReached = () => {
    // console.log('触底了加载数据吧');
    // 加载翻页数据 当前页+1
    // page当前页数  pageCount最大页数
    const { page, pageCount } = this.state.data;
    // 判断当前页数等于最大页数 后续没有数据 不进行请求了
    if (page == pageCount) {
      return;
    }
    fetch(this.url(page + 1))
      .then((res) => res.json())
      .then((res) => {
        console.log(res);
        // 拼接数据 拼数组
        res.result = [...this.state.data.result, ...res.result];
        this.setState({ data: res });
      });
  };
  // 头部组件
  _ListHeaderComponent = () => (
    <View style={{ backgroundColor: "red", alignItems: "center" }}>
      <Text style={{ color: "white", fontSize: rpx(40), fontWeight: "800" }}>
        网易新闻
      </Text>
    </View>
  );
  // 底部组件 加载组件
  _ListFooterComponent = () => {
    // 获取当前页数和最大页数
    const { page, pageCount } = this.state.data;
    // 判断当前页就是最大页 后续没有数据 返回没有数据的文本信息
    if (page == pageCount) {
      return (
        <View
          style={{
            alignItems: "center",
            padding: rpx(10),
            backgroundColor: "#cccccc",
          }}
        >
          <Text style={{ fontSize: rpx(30) }}>
            生活就像卫生纸,扯着扯着就没了~
          </Text>
        </View>
      );
    }
    return (
      <View
        style={{
          alignItems: "center",
          padding: rpx(10),
          backgroundColor: "#cccccc",
        }}
      >
        <ActivityIndicator color="red" size="large"></ActivityIndicator>
        <Text style={{ fontSize: rpx(30) }}>加载中...</Text>
      </View>
    );
  };
  // 分隔组件
  _ItemSeparatorComponent = () => (
    <View style={{ height: 1, backgroundColor: "#757575" }}></View>
  );
  // 每个元素的渲染
  _renderItem = ({ item }) => (
    <View style={{ flexDirection: "row" }}>
      <Image
        source={{ uri: item.image }}
        style={{
          width: rpx(250),
          height: rpx(150),
          marginRight: rpx(10),
        }}
      ></Image>
      <View style={{ flex: 1, justifyContent: "space-between" }}>
        <Text style={{ fontSize: rpx(30) }}>{item.title}</Text>
        <Text style={{ fontSize: rpx(30) }}>{item.passtime}</Text>
      </View>
    </View>
  );
}