ReactNative爬坑之路--万字总结

2,287 阅读18分钟

当前项目 react-native 版本 "0.64.0",

坑位

exclude 'classes.dex' exclude '**.**'

stackoverflow.com/questions/6…

待审查 挨个问好? blog.csdn.net/IT_fighter/…

Direct local .aar file dependencies are not supported when building an AAR 问题 出现在支付宝支付的库上

developer.android.com/studio/buil…

opensupport.alipay.com/support/fee…

stackoverflow.com/questions/6…

github.com/OpenFlutter…

---最后发现一个 issue

github.com/notifee/rea…

- ./gradlew assembleRelease
+ ./gradlew :app:assembleRelease

stackoverflow.com/questions/6…

android 开启 Hermes 打包过程会出现各种 waring

github.com/facebook/re…

例如等诸多 warning

the variable "requestAnimationFrame" was not declared in function

github.com/facebook/he…

hermesFlagsRelease: ["-w"]

react-native-wechat-lib 使用的androidx.annotation导致其他项目 android.support.annotation炸裂

只能快捷操作 Ctrl + Shift + R

全局替换androidx.annotation

github.com/facebook/re… 等等问题 issue

解决方案

cd android &&  ./gradlew clean : 如果使用androidStudio打包则不需要
yarn add jetifier
npx jetify
就可以了

避免俩套高德 key 或者微信 appid

android/app/build.gradle

release 和 debug 指定同一个

signingConfigs {
        debug {
            storeFile file('app.keystore')
            storePassword '...'
            keyAlias '...'
            keyPassword '...'
        }
        release {
            storeFile file('app.keystore')
            storePassword '...'
            keyAlias '...'
            keyPassword '...'
        }
    }
    buildTypes {
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://reactnative.dev/docs/signed-apk-android.
            signingConfig signingConfigs.release
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
        debug {
            signingConfig signingConfigs.debug
        }
    }

android 开启了 打包正式报错 java.lang.outofmemoryerror

stackoverflow.com/questions/5…

Task :app:packageRelease FAILED + FAILURE: Build completed with 2 failures +1: Task failed with an exception

可以尝试清除缓存

cd ./android && ./gradlew clean

D8: java.lang.OutOfMemoryError: Java heap space

blog.csdn.net/shving/arti…

Task orphaned for request <NSMutableURLRequest...

github.com/facebook/re…

ios textinput bug 拼音会限制到 maxlength 上

www.dazhuanlan.com/2019/10/14/…

虚线的问题 android

github.com/facebook/re…

禁用系统字体

blog.csdn.net/qq_39910762…

不随系统的显示大小

DispUtility.java

package com.gunner;

import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.view.Display;

import java.lang.reflect.Method;

/**
 * Author : monkey0928
 * E-mail : hanbao@xwtec.c
 * Date : 2020/6/29 17:54
 * DESCRIBE :禁用 7.0(23)以上字体大小和显示大小随系统变化
 */
public final class DispUtility {

    /**
     * 禁用7.0(23)以上显示大小改变和文字大小
     */
    public static Resources disabledDisplayDpiChange(Resources res) {
        Configuration newConfig = res.getConfiguration();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //字体非默认值
            if (res.getConfiguration().fontScale != 1) {
                newConfig.fontScale = 1;
            }
            newConfig.densityDpi = getDefaultDisplayDensity();
            res.updateConfiguration(newConfig, res.getDisplayMetrics());
        } else {
            //字体非默认值
            if (res.getConfiguration().fontScale != 1) {
                newConfig.fontScale = 1;//设置默认
                res.updateConfiguration(newConfig, res.getDisplayMetrics());
            }
        }
        return res;
    }

    /**
     * 获取手机出厂时默认的densityDpi
     */
    public static int getDefaultDisplayDensity() {
        try {
            Class aClass = Class.forName("android.view.WindowManagerGlobal");
            Method method = aClass.getMethod("getWindowManagerService");
            method.setAccessible(true);
            Object iwm = method.invoke(aClass);
            Method getInitialDisplayDensity = iwm.getClass().getMethod("getInitialDisplayDensity", int.class);
            getInitialDisplayDensity.setAccessible(true);
            Object densityDpi = getInitialDisplayDensity.invoke(iwm, Display.DEFAULT_DISPLAY);
            return (int) densityDpi;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

}
public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
+   DispUtility.disabledDisplayDpiChange(this.getResources());
  }

ios http 请求 的 info.plist

reactnative.dev/docs/integr…

reactnative.dev/docs/integr…

github.com/axios/axios…

App Transport Security Settings 需要一个Allow Arbitrary Loads

e.g

<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
		<key>NSExceptionDomains</key>
		<dict>
			<key>localhost</key>
			<dict>
				<key>NSExceptionAllowsInsecureHTTPLoads</key>
				<true/>
			</dict>
			<key>https://restapi.amap.com/v3</key>
			<dict>
				<key>NSExceptionAllowsInsecureHTTPLoads</key>
				<true/>
			</dict>
		</dict>
	</dict>

pod install --verbose 可以查看进度

pod install 卡在 Flipper 或者 'event2/event-config.h' file not found

(答案来源于)[stackoverflow.com/questions/6…]

pod install 卡在 Flipper 是自身遇到,修改直接成功了 2021/3/19 --下载显示的版本是 0.75.1--实在是 pod 不下来,总结下来就是指定版本

ios/Podfile 修改

- use_flipper!()
+ use_flipper!({ 'Flipper' => '0.74.0' })

ios run 需要有 team 账号--没有的需要注册

位置:XCode选中项目>TARGETS>Signing&Capabilities>Signing

axios 的问题 android9 以上不支持 http ios 不支持 http

AndroidManifest.xml

 <!-- https://github.com/axios/axios/issues/973 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Info.plist

加上这俩段

<key>NSAppTransportSecurity</key>
	<dict>
+		<key>NSAllowsArbitraryLoads</key>
+		<true/>
    </dict>

禁止首页 tanbar 存在的页面因为键盘把 tabbar 顶上去

    <activity
        android:name=".MainActivity"
+       android:windowSoftInputMode="adjustPan"

goBack() 回调传参

www.jianshu.com/p/ef61005bc…

禁止旋转

android

    <activity
        android:name=".MainActivity"
+       android:screenOrientation="portrait"

ios

位置:XCode选中项目>TARGETS>General>Deployment Info>Device Orientation

Bundle Identifier不能够重复

只选中第一个就好

在同一台电脑不能同时执行 run IOS 和 Android

比如 IOS 用 Xcode RUN 了一个到 IOS 虚拟机上,然后直接敲命令yarn run android 会被 Connection refused: connect

MACadb

brew install android-platform-tools

You need the android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag 报错

小米手机需要开启USB调试(安全设置)

全局范围的扩大仅可直接嵌套在外部模块中或环境模块声明中

declare global {
    interface String {
        hump(input: string): string;
    }
}
// 注意: 修改"全局声明"必须在模块内部, 所以至少要有 export{}字样
// 不然会报错❌: 全局范围的扩大仅可直接嵌套在外部模块中或环境模块声明中
export {}

忽略 ts 类型

  • 忽略当前文件的ts检测
/* eslint-disable */
  • 忽略下一行的ts检测
// eslint-disable-next-line
  • 忽略库的 ts 类型检测
// @ts-ignore

使用别名路径

yarn add --dev babel-plugin-module-resolver

babel.config.js

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    [
      'module-resolver',
      {
        root: ['./src'],
        extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
        alias: {
          '@components': './src/components',
          '@pages': './src/pages',
          '@type': './src/types',
          '@assets': './src/assets',
          '@utils': './src/utils',
          '@store': './src/store',
          '@config': './src/config',
          '@api': './src/api'
        }
      }
    ],
    [
      '@babel/plugin-proposal-decorators',
      {
        legacy: true
      }
    ]
  ]
}

tsconfig.json

{
+    "baseUrl": ".",
+    "paths": {
+         "@components/*": ["src/components/*"],
+         "@pages/*": ["src/pages/*"],
+         "@type/*": ["src/types/*"],
+         "@assets/*": ["src/assets/*"],
+         "@utils/*": ["src/utils/*"],
+         "@store/*": ["src/store/*"],
+         "@config/*": ["src/config/*"],
+         "@api/*": ["src/api/*"]
+    },
    "exclude": [
        "node_modules", "babel.config.js", "metro.config.js", "jest.config.js"
    ]
}

xcode 报错 Command PhaseScriptExecution failed with a nonzero exit code

mac 内存不足的问题

No version of NDK matched the requested version 22.0.7026061. Versions available locally: 23.0.7123448, 23.0.7123448

打开 AndroidStudio>Preferences>Appearance & Behavior>System Setting>Android SDK tab 选项卡到SDK Tools,把 NDK 勾选上然后下载

点击右下角 Show Package Details 找到版本 22.0.7026061 下载

VScode 安装 prettier前提下

.prettierrc

{
  "singleQuote": true,
  "semi": false,
  "tabWidth": 2,
  "useTabs": false,
  "trailingComma": "none",
  "endOfLine": "lf"
}

metro & babel

我们在 TS 配置中涉及到了 metro.config.js、.babelrc、tsconfig 等一系列的配置文件,这里简单总结下他们之间的关系。

metro:是 Facebook 开发的一个专门为 React Native 提供 JS 的 bundler,作用和前端中的 webpack 类似,也有人尝试使用 metro 作为前端的编译打包工具。

metro 通过调用 babel 提供将 ES6、JSX、TS 等编译成 ES5 的 JS 代码。

metro.config.js、.babelrc 则是编译期间需要使用的配置文件,tsconfig 目前更多的是给 VSCode、WebStorm 等开发工具使用做 TS 校验

React Native 0.64版本

zhuanlan.zhihu.com/p/356940165

iOS开启支持Hermes引擎

    1. 此次版本更新也正是开启了 iOS 平台上支持了 Hermes。开启 Hermes 支持也很简单,在 Podfile 文件中设置 hermes_enabled 为 true,然后在执行 pod install 就可以了。
use_react_native!(
   :path => config[:reactNativePath],
   # to enable hermes on iOS, change `false` to `true` and then install pods
-  :hermes_enabled => false
+  :hermes_enabled => true
)

app/build.gradle

project.ext.react = [
-    enableHermes: false, // clean and rebuild if changing
+    enableHermes: true,  // clean and rebuild if changing
]

- def enableHermes = project.ext.react.get("enableHermes", false);
+ def enableHermes = project.ext.react.get("enableHermes", true);

hermes_enabled 这个库 483M,会碰到 pod 很慢的情况,最好通过pod install --verbose 进行观察原因,基本是网慢,最快一百多 K 每秒,是在弄不下来就 false 吧,我勉强拉下来了幸运花了一个多小时

    1. 默认启用 Inline Requires

Inline Requires 是一个 Metro 配置选项,它通过延迟加载 JavaScript 模块的执行,来缩短启动时间,提交加载速度。其作为可选配置选择已经存在很多年,现在新版本应用中默认开启,以此帮助用户无需额外配置就可以快速使用 React Native.

Inline Requires 是一种 Babel 变换,它可以将模块导入并转换为 inline。例如,Inline Requires 将这个模块导入调用从文件的 top 转换到使用它的地方。

-  import { MyFunction } from 'my-module';

const MyComponent = (props) => {
-  const result = MyFunction();
+  const result = require('my-module').MyFunction();

  return (<Text>{result}</Text>);
};
    1. 支持 React 17

e.g: 不需要使用import React from 'react'就可以使用jsx

- import React from 'react';

function App() {
  return <h1>Hello World</h1>;
}
- import React from 'react';
+ import { useState } from 'react';

function App() {
-  const [text, setText] = React.useState('Hello World');
+  const [text, setText] = useState('Hello World');
   return <h1>{text}</h1>;
}

mac 安卓安装 jdk

www.jianshu.com/p/a85658902…

android 报错Direct local .aar file dependencies are not supported when building an AAR

直接用 androidStudio 打而不是用命令。。。。【因为我打出来了,命令就是报这个错误】

android 会出现层级问题【ios 表现正常】

添加样式

elevation:0.001

后来发现可能跟位置有关

textarea[多行的 textarea]

www.react-native.cn/docs/textin…

配置 eslint

  • eslint-import-resolver-typescript:和 eslint-import-resolver-webpack 类似,主要是为了解决 alias 的问题
  • eslint-plugin-react: React 专用的校验规则插件
  • eslint-plugin-jsx-a11y: 该依赖包专注于检查 JSX 元素的可访问性
  • eslint-plugin-react-native: React-Native 专用的校验规则插件
  • eslint-plugin-import: 该插件想要支持对 ES2015+ (ES6+) import/export 语法的校验, 并防止一些文件路径拼错或者是导入名称错误的情况
  • eslint-plugin-promise: promise 规范写法检查插件,附带了一些校验规则

ts 部分

  • @typescript-eslint/parser:ESLint 的解析器,用于解析 typescript,从而检查和规范 Typescript 代码
  • @typescript-eslint/eslint-plugin:这是一个 ESLint 插件,包含了各类定义好的检测 Typescript 代码的规范
yarn add eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-native eslint-import-resolver-typescript eslint-plugin-promise eslint-plugin-import @typescript-eslint/parser @typescript-eslint/parser @typescript-eslint/eslint-plugin -D

.eslintrc.js

module.exports = {
  root: true,
  env: {
    es6: true,
    browser: true,
    node: true,
    jest: true,
    'react-native/react-native': true
  },
  plugins: [
    // ESLint 支持使用第三方插件。在使用插件之前,你必须使用 npm 安装它。
    'react',
    'react-native'
  ],
  extends: [
    '@react-native-community',
    'plugin:react-native/all',
    'plugin:@typescript-eslint/recommended'
  ],
  parser: '@typescript-eslint/parser', // 解析器
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
    ecmaFeatures: {
      tsx: true, //允许解析tsx Allows for the parsing of JSX
      jsx: true
    }
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    /* allow async-await */
    'generator-star-spacing': 'off',
    'no-empty': 2,
    /* 方法名和刮号之间需要有一格空格  --禁用 */
    'space-before-function-paren': 0,
    'comma-dangle': [2, 'never'],
    camelcase: 0,
    /* 末尾不需要分号结束 */
    semi: 0,
    /* 使用单引号 */
    quotes: ['error', 'single'],
    // 样式排序
    'react-native/sort-styles': 0
  }
}

禁用掉部分区域的滑动手势

github.com/zgatrying/r…

规范提交commit

yarn add commitizen cz-customizable husky@4.3.8 commitlint-config-cz lint-staged cz-conventional-changelog @commitlint/cli @commitlint/config-conventional -D
  • commitlint.config.js 资料 文档

    第一位:0 为 disable,1 为 warning,2 为 error

    第二位:应用与否,可选 always|never

    第三位:rule 的值

    type(scope?): subject
    body?
    footer?
    
    scope 指 commit 的范围(哪些模块进行了修改)
    
    subject 指 commit 的简短描述
    
    body 指 commit 主体内容(长描述)
    
    footer 指 commit footer 信息
    
    • type-enum:类型在值中找到
    • subject-full-stop:
    • type-case:类型大小写
    • scope-empty:修改范围
    • scope-case:scope 值的情况 ....
  • 配置 package.json

    husky hoosks 根据 commitlint.config.js 配置

    lint-staged 里面加 eslint 的 hooks

    "scripts":{
      "commit": "git-cz"
    },
    "config": {
      "commitizen": {
        "path": "cz-customizable"
      }
    },
    "husky": {
      "hooks": {
          "pre-commit": "lint-staged",
          "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
      }
    },
    "lint-staged": {
      "*.{js,jsx,vue}": []
    },
    
  • .cz-config.js

    'use strict';
    module.exports = {
        types: [
            { value: 'feat', name: 'feat:       增加新功能' },
            { value: 'fix', name: 'fix:       修复bug' },
            { value: 'ui', name: 'ui:       更新UI' },
            { value: 'refactor', name: 'refactor:       代码重构' },
            { value: 'release', name: 'release:       发布' },
            { value: 'docs', name: 'docs:       修改文档' },
            { value: 'test', name: 'test:       增删测试' },
            { value: 'chore', name: 'chore:       更改配置文件' },
            { value: 'style', name: 'style:       代码样式修改不影响逻辑' },
            { value: 'revert', name: 'revert:       版本回退' },
            { value: 'add', name: 'add:       添加依赖' },
            { value: 'del', name: 'del:       删除代码/文件' },
            { value: 'build', name: 'del:       修改项目构建系统' },
            { value: 'perf', name: 'perf:       性能优化' },
            { value: 'breaking change', name: 'breaking change:       重大改变' },
             { value: 'types', name: 'types:       修改定义文件' }
        ],
        scopes: [],
        messages: {
            type: '选择更改类型:\n',
            scope: '请输入更改的范围:\n',
            // 如果allowcustomscopes为true,则使用
            // customScope: 'Denote the SCOPE of this change:',
            subject: '简短描述:\n',
            body: '详细描述. 使用"|"换行:\n',
            breaking: 'Breaking Changes列表:\n',
            footer: '关闭的issues列表. E.g.: #31, #34:\n',
            confirmCommit: '确认使用以上信息提交?(y)'
        },
        allowCustomScopes: true,
        allowBreakingChanges: ["feat", "fix"]
    };
    
  • commitlint.config.js

    module.exports = {
        extends: ['@commitlint/config-conventional', "cz"],
        rules: {
            'type-enum': [
                2,
                'always',
                [
                    "release",/* 腹部 */
                    "del",/* 删除代码/文件 */
                    "add",/* 新增依赖 */
                    "ui",/* 更新UI */
                    "feat",/* 新增功能 */
                    "fix",/* 修复bug */
                    "docs",/* 修改文档 */
                    "style",/* 代码样式修改不影响逻辑 */
                    "refactor",/* 代码重构 */
                    "test",/* 增删测试 */
                    "chore",/* 更改配置文件 */
                    "revert",/* 回滚代码 */
                    "breaking change",/* 重大改变 */
                    "types",/* 修改定义文件 */
                    "perf",/* 性能优化 */
                    "build"/* 修改项目构建工具 */
                ]
            ],
            'type-empty': [2, 'never'],
            'type-case': [0],
            'scope-empty': [0],
            'subject-full-stop': [0, 'never'],
            'subject-empty': [2, 'never'], /* 提交不符合规范时,也可以提交,但是会有警告 */
            'subject-case': [0, 'never'],
            'scope-case': [2, 'always', 'lower-case'],
            'header-max-length': [2, 'always', 72],
        }
    }
    

扩展库

react-native-extended-stylesheet

提供了样式的提供的扩展功能

yarn add react-native-extended-stylesheet

index.js 入口文件

import EStyleSheet from 'react-native-extended-stylesheet';

// 你不使用全局变量也需要在入口文件进行build
EStyleSheet.build({
  $textColor: '#0275d8'
});
全局变量
// 入口文件
EStyleSheet.build({
  $textColor: '#0275d8'
});
// 在组件样式中使用
const styles = EStyleSheet.create({
  text: {
    color: '$textColor'
  }
});
// 作为内联样式或者组件属性使用
<View style = {{
  backgroundColor: EStyleSheet.value('$textColor')
}}>
</View>
局部变量

局部变量优先于全局变量,可以覆盖全局变量,局部变量可以直接通过 styles.$textColor 获取数值。

const styles = EStyleSheet.create({
  $textColor: '#0275d8',
  text: {
    color: '$textColor'
  },
  icon: {
    color: styles.$textColor
  },
});
媒体查询
// global level
EStyleSheet.build({
  '@media ios': {
    $fontSize: 12,
  },
  '@media android': {
    $fontSize: 16,
  },
});

// sheet level
const styles = EStyleSheet.create({
  column: {
    width: '80%',
  },
  '@media (min-width: 350) and (max-width: 500)': {
    column: {
      width: '90%',
    }
  }
});

// style level
const styles = EStyleSheet.create({
  header: {
    '@media ios': {
      color: 'green',
    },
    '@media android': {
      color: 'blue',
    },
  }
});
数值操作

任何的值都可以包含+,-,*,/数值操作,操作数可以是数值,变量,和百分比

const styles = EStyleSheet.create({
  $size: 20,
  circle: {
    width: '$size',
    height: '$size',
    borderRadius: '0.5 * $size'
  }
});
REM 单位

与 CSS3 的 rem unit 允许定义相对于根元素的一个整数值,rem 默认值是 16。依赖屏幕的尺寸或者其他条件可以很容易的去扩展应用。

// component
const styles = EStyleSheet.create({
  text: {
    fontSize: '1.5rem',
    marginHorizontal: '2rem'
  }
});
// app entry
let {height, width} = Dimensions.get('window');
EStyleSheet.build({
  $rem: width > 340 ? 18 : 16
});
百分比

百分比支持是从 React Native 0.43 开始的。EStyleSheet 通过扩展原有的 StyleSheet 可以使用百分比计算。百分比算通过应用的屏幕去计算。

const styles = EStyleSheet.create({
  column: {
    width: '100% - 20'
  }
});
缩放

通过设置一个特殊变量去缩放(改变组件的 width,height,以及 margin)组件

const styles = EStyleSheet.create({
  $scale: 1.5,
  button: {
    width: 100,
    height: 20,
    marginLeft: 10
  }
});

可以通过传递一个属性去控制组件的尺寸

class Button extends React.Component {
  static propTypes = {
    scale: React.PropTypes.number
  };
  render() {
    let style = getStyle(this.props.scale)
    return (
      <View style={style.button}>
      </View>
    );
  }
}

let getStyle = function (scale = 1) {
  return EStyleSheet.create({
    $scale: scale,
    button: {
      width: 100,
      height: 20,
      marginLeft: 10
    }
  });
}

剩余的文档

下拉刷新加载库

借鉴 https://github.com/bozaigao/react-native-refresh-loadmore-recyclerlistviewhttps://github.com/bolan9999/react-native-largelist 以及 recyclerlistview

yarn add ts-object-utils

lodash==>[直接把 debounce 从 lodash 源码扣下来] debounce

yarn add @react-native-community/async-storage

cd ios && pod install

视频组件

github.com/A-ANing/rea…

  • react-native-orientation 旋转监听 Q.需要配置

IOS

cd ios && pod install

AppDelegate.m

+ #import "Orientation.h" // <--- import

@implementation AppDelegate

  // ...

+ - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
+  return [Orientation getOrientation];
+ }

@end

ANDROID

MainActivity.java

package com.technicianuser;

+ import android.content.Intent; // <--- import
+ import android.content.res.Configuration; // <--- import
import com.facebook.react.ReactActivity;


public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "technicianUser";
  }

+  /**
+   * 监听App旋转
+   */
+  @Override
+  public void onConfigurationChanged(Configuration newConfig) {
+    super.onConfigurationChanged(newConfig);
+    Intent intent = new Intent("onConfigurationChanged");
+    intent.putExtra("newConfig", newConfig);
+    this.sendBroadcast(intent);
+  }

}
  • react-native-slider 滑条 Q.不需要配置
yarn add react-native-video react-native-slider react-native-orientation
IOS 配置
cd ios && pod install

重新编译

ANDROID 配置

gradle.properties

+ android.useAndroidX=true
+ android.enableJetifier=true

图片缓存库

github.com/DylanVann/r…

yarn add react-native-fast-image
cd ios && pod install

重新编译安装程序

学习

github.com/katanyaJATI…

学习所得

aspectRatio 用法

在保持宽高比的情况下,我们应该尽可能使用 aspectRatio 来实现,比如,有个图片,在 750 设计稿 里量来是 126*134 ,宽度占父级的 50%,我们可以这样来实现:

const style = {
    width: '50%',
    // **注意**,下面这个 height: undefined 样式,在加载 **本地图片** 时,是必须的!
    height: undefined,
    aspectRatio: 126 / 134,
};
//later in render
<Image style={style}></Image>

两侧间距固定,中间自适应

const style = {
    marginHorizontal: 20,
    alignSelf: 'stretch',
};
//render
<View style={style}></View>

渐变组件

github.com/react-nativ…

yarn add react-native-linear-gradient
cd ios && pod install

重新编译

webview 组件

github.com/react-nativ…

yarn add react-native-webview
cd ios && pod install

重新编译

Android

  • react-native-webview 版本>=6.X。X:请通过编辑 android/gradle 确保你的项目中启用了 AndroidX。属性和添加 2 行:

gradle.properties 默认应该是有的

android.useAndroidX=true
android.enableJetifier=true

删除 console.*

在运行打好了离线包的应用时,控制台大量打印语句可能会拖累 JavaScript 线程。注意有些第三方调试库也可能包含控制台打印语句,比如 redux-logger,所以在发布应用前请务必仔细检查,确保全部移除。

有个 babel 插件可以帮你移除所有的 console.*调用。首先需要使用 yarn add --dev babel-plugin-transform-remove-console 来安装,然后在项目根目录下编辑(或者是新建)一个名为·.babelrc`的文件,在其中加入:

{
  "env": {
    "production": {
      "plugins": ["transform-remove-console"]
    }
  }
}

HOC 高阶函数 工具

hoist-non-react-statics

使用高阶组件遇到的问题:静态方法丢失 ,当使用高阶组件包裹原始组件,返回的新组件会丢失原始组件的所有静态方法。 使用 hoist-non-react-statics 来帮你自动处理,它会自动拷贝所有非 React 的静态方法;(react-router 里 withRouter 就使用了这个包)

yarn add hoist-non-react-statics

模态框

由于 react-native-modal 是原始 react native 模态的扩展,它以类似的方式工作

react-native-modal

github.com/react-nativ…

yarn add react-native-modal

android 做到全屏 状态栏不存在

blog.csdn.net/weixin_4117…

github.com/facebook/re…

github.com/listenzz/re…

github.com/23mf/react-…

  • 方法二

react-native-modal 与 react-native-translucent-modal 结合源码到本地

yarn add react-native-animatable react-native-translucent-modal
  • 方法一有点丑 他是一个隐藏
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.ReactNative.AppCompat.Light.NoActionBar.FullScreen">
        <!-- Customize your theme here. -->
    </style>
    <style name="AppTheme.Launcher">
        <item name="android:windowBackground">@drawable/launch_screen</item>
    </style>
</resources>

图片查看器

---- 可以学习 github.com/indulgeIn/Y…

react-native-image-zoom-viewer

github.com/ascoders/re…

yarn add react-native-image-zoom-viewer

为了做到保存图片功能

github.com/ascoders/re…

@react-native-community/cameraroll

yarn add @react-native-community/cameraroll
cd ios && pod install

报错

Error: Unable to resolve module fbjs/lib/invariant

解决

yarn add fbjs

Android

blog.csdn.net/kevinlwf/ar…

借助库

rn-fetch-blob

github.com/joltup/rn-f…

yarn add rn-fetch-blob

虽然ios不会用到这个库 ,但是还是弄一下好了

cd ios && pod install

从 Android 10 开始,介绍了作用域存储的概念。目前,要使它与改变工作,你必须添加

AndroidManifest.xml

<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>
+   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+   <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />

....

<intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
+           <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
        </intent-filter>

ios 警告

 Require cycle: node_modules/rn-fetch-blob/index.js -> node_modules/rn-fetch-blob/polyfill/index.js -> node_modules/rn-fetch-blob/polyfill/Fetch.js -> node_modules/rn-fetch-blob/index.js

解决

github.com/joltup/rn-f… 这个 pr 不合并 哎 自己搞

save 方法

在 Android 上,标签必须是本地的图像或视频 URI,例如"file:///sdcard/img.png"。

在 iOS 上,标签可以是任何图像 URI(包括本地、远程资产库和 base64 数据 URI)或本地视频文件 URI(此时不支持远程或数据 URI 来保存视频)。

为了做到能够不直接在页面写组件而能显示出各种组件

react-native-root-siblings

github.com/magicismigh…

yarn add react-native-root-siblings

表情

github.com/hewking/rea…

图片选择器

github.com/syanbo/reac…

github.com/baronha/rea…

react-native-syan-image-picker

yarn add react-native-syan-image-picker

IOS 配置

  • 安装
cd ios && pod install
  • 添加相册相关权限

Info.plist

 Privacy - Camera Usage Description 是否允许此App使用你的相机进行拍照?
 Privacy - Photo Library Usage Description 请允许访问相册以选取照片
 Privacy - Photo Library Additions Usage Description 请允许访问相册以选取照片
 Privacy - Location When In Use Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据
  • 中文适配
添加中文 PROJECT -> Info -> Localizations 点击"+"按钮,选择Chinese(Simplified)

Android 配置

AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

UI 框架

github.com/rilyu/tease…

有值得学习借鉴的地方

便于数据的操作与易用的数据类型

轻量级的 immutable.js {Immer.js}+可简易操作的对象 useImmer

blog.csdn.net/zsy_snake/a…

yarn add immer use-immer

网络状态

@react-native-community/netinfo

github.com/react-nativ…

yarn add @react-native-community/netinfo
 cd ios && pod install

新增启动图

react-native-splash-screen

github.com/crazycodebo…

yarn add react-native-splash-screen
cd ios && pod install

IOS

AppDelegate.m

+ #import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "RNSplashScreen.h"  // 添加这一句

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // ...other code

+    [RNSplashScreen show];  // 添加这一句,这一句一定要在最后
    return YES;
}

@end


直接修改 LaunchScreen.storyboard就好了

ANDROID

package com.technicianuser;

import com.facebook.react.ReactActivity;

+ import org.devio.rn.splashscreen.SplashScreen;
+ import android.os.Bundle;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "technicianUser";
  }

+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    SplashScreen.show(this);  // here
+    super.onCreate(savedInstanceState);
+  }
}

main/res/layout/launch_screen.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
<!-- https://developer.android.com/guide/topics/ui/layout/relative?hl=zh-cn-->
            <TextView
                android:id="@+id/appName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="@string/app_name"
                android:textColor="#F2A160"
                android:layout_marginTop="200dp"
                android:textSize="36sp" />
            <TextView
                android:id="@+id/desc"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="@string/app_desc"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="50dp"
                />
</RelativeLayout>

打分星星

react-native-ratings

学习 github.com/youzan/vant…

github.com/Monte9/reac…

yarn add react-native-ratings

获取设备信息

react-native-device-info

github.com/react-nativ…

yarn add react-native-device-info

ios

cd ios && pod install

清除缓存

react-native-clear-cache

github.com/sowlutions/…

  • package.json
+ "react-native-clear-cache": "https://github.com/sowlutions/react-native-clear-cache"

ios

cd ios && pod install

侧滑

react-native-swipeable

github.com/jshanson7/r…

yarn add react-native-swipeable

bug:github.com/jshanson7/r…

解决:github.com/jshanson7/r…

自动激活:github.com/jshanson7/r…

毛玻璃

github.com/Kureev/reac…

react-native-blur

yarn add @react-native-community/blur
cd ios && pod install

github.com/Kureev/reac…

应用处理离线状态

react-native-offline

github.com/rgommezz/re…

yarn add react-native-offline
yarn add @react-native-community/netinfo
cd ios && pod install

城市索引选择

github.com/HuangZhe007…

yarn add react-native-spring-scrollview react-native-largelist-v3 react-native-spinkit
cd ios && pod install

react-native-spring-scrollview 可能会遇到以下这个错误

react-native-spring-scrollview 弹性滚动

react-native-spring-scrollview

/Library/work/technicianUser/node_modules/react-native-spring-scrollview/ios/SpringScrollView/STSpringScrollView.m:25:42: Expected a type

最顶上加一个

#import "STSpringScrollView.h"

+ #import "RCTEventDispatcher.h"

---->直接下载到本地【从本地导到 node_modules】

github.com/bolan9999/r…

currentlyFocusedField => currentlyFocusedInput

这个 bug 也需要修复一下

SpringScrollView.js

- import * as TextInputState from "react-native/lib/TextInputState";
+ import * as TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState'

避免远程 bug 未修复从而出现错误,自己手动改

package.json 直接连接到本地

react-native-spring-scrollview/src[只要这 src 里面的] 文件下新增 react-native-spring-scrollview.podspec

require "json"

package = JSON.parse(File.read(File.join(__dir__, "package.json")))

Pod::Spec.new do |s|
  s.name         = "react-native-spring-scrollview"
  s.version      = package["version"]
  s.summary      = package["description"]
  s.description  = <<-DESC
                  react-native-spring-scrollview
                   DESC
  s.homepage     = "https://github.com/bolan9999/react-native-spring-scrollview"
  s.license      = "MIT"
  # s.license    = { :type => "MIT", :file => "FILE_LICENSE" }
  s.authors      = { "Your Name" => "yourname@email.com" }
  s.platforms    = { :ios => "9.0", :tvos => "10.0" }
  s.source       = { :git => "https://github.com/bolan9999/react-native-spring-scrollview.git", :tag => "#{s.version}" }

  s.source_files = "ios/**/*.{h,m,swift}"
  s.requires_arc = true

  s.dependency "React"

  # s.dependency "..."
end

因为没有使用 src 里面的,报了以下错误

报错 "The react-native-spring-scrollview pod failed to validate due to 1 error: - ERROR | attributes: Missing required attribute summary"

package.json 加 description 字段[description 不能为空]

tab 块选择

github.com/App2Sales/r…

github.com/kirankalyan…

轮播

react-native-swiper

yarn add react-native-swiper

Tab 选项卡

react-native-tab-view 结合 react-native-head-tab-view

github.com/zyslife/rea…

react-native-tab-view版本 3 需要多安装react-native-pager-view

yarn add react-native-head-tab-view react-native-gesture-handler react-native-reanimated react-native-tab-view-collapsible-header react-native-tab-view react-native-pager-view

android react-native-reanimated 安装需要加代码

docs.swmansion.com/react-nativ…

babel.config.js

module.exports = {
   presets: ['module:metro-react-native-babel-preset'],
+  plugins: ['react-native-reanimated/plugin'],
};

配置完还是报错Reanimated 2 failed to create a worklet, maybe you forgot to add Reanimated's babel plugin? :有缓存

yarn start --reset-cache

@surajj2223:github.com/software-ma…

IOS

cd ios && pod install

地图选择 下拉选择做准备

github.com/osdnk/react…

yarn add reanimated-bottom-sheet

Now we need to install react-native-gesture-handler and react-native-reanimated.

查看更多 源码

github.com/fawaz-ahmed…

左滑 菜单类似 QQ

github.com/Kureev/reac…

picker

github.com/iberHK/reac…

地图

地图

github.com/qiuxiang/re…

ios 存在问题 github.com/qiuxiang/re…

api 定位

github.com/qiuxiang/re…

github.com/qiuxiang/re…

优化打包 bundle

github.com/microsoft/r…

github.com/feixue1232/…

Android 生成 keystore

keytool -genkey -v -keystore app.keystore -alias zhiyue -keyalg RSA -keysize 2048 -validity 100000

解决弧度曲线

react-native-svg

yarn add react-native-svg

cd ios && pod install

解决阴影

github.com/tokkozhin/r…

yarn add @react-native-community/art react-native-neomorph-shadows

cd ios && pod install

权限 API 管控

yarn add react-native-permissions

⚠️ If you see a No permission handler detected error: Make sure that you have at least one permission handler set up. In some cases the Xcode cache needs to be cleared (Xcode -> Product -> Clean Build Folder)

github.com/zoontek/rea…

这里面选几条加到 Podfile 里面

iOS 隐私权限和通过 openURL 实现跳转

www.jianshu.com/p/9e5bd79a2…

系统级别的 toast

react-native-toast-native

github.com/onemolegame…

yarn add react-native-toast-native

github.com/onemolegame…

查看更多

github.com/kashishgrov…

github.com/fawaz-ahmed…

学习如何写自己模块

github.com/Gnotes/reac…

学习别人的的大框架

github.com/HarishJangr…

画虚线

react-native-dash

yarn add react-native-dash react-native-measureme

可以研究一下 setNativeProps

生成二维码

react-native-qrcode

github.com/cssivision/…

yarn add react-native-qrcode

github.com/cssivision/…

----不太行的样子

github.com/awesomejerr…

直接源码重写

图片合成

github.com/gre/react-n…

yarn add react-native-view-shot

关于地图计算的库

github.com/manuelbieh/…

跟微信相关 登录分享 库

github.com/little-snow…

集成 qq 相关 登录

github.com/haxibiao/re…

极光推送

fish.iwhalecloud.com/fish-mobile…

状态管理

blog.csdn.net/sakura55520…

文档

oss-labs.gitbook.io/dva-docs/mo…

时间库

github.com/iamkun/dayj…

获取最新省市区脚本

升级 python 到 3 --blog.csdn.net/alice_tl/ar…

blog.csdn.net/MHTios/arti…

台湾+香港+台湾数据整合 blog.csdn.net/u010318957/…

---- 记录获取港澳台数据 github.com/youzan/vant…

// vant 获取数据
var a={....}
var b={....}
var arr=[]
for(let i in a){
    let area=[]
    for(let j in b){
        if(j.indexOf(i.slice(0,4))>-1){
            area.push({code:j,value:b[j],label:b[j]})
        }

    }
    arr.push({code:i,value:a[i],label:a[i],children:area})
}

codechina.csdn.net/mirrors/wu-…

# -*- coding: UTF-8 -*-

import json
import urllib.request
# import requests
import urllib.parse
import ssl
import os
import time
from bs4 import BeautifulSoup

# config #

year = '2019'       # 年份,目前国家统计局官网有2009-2019年的数据
level = 3           # 可选:3|5   获取的层级 3层为省-市-区  最多5级省-市-区-县(街道)-乡镇(居委会)
digit = 6           # 可选:6|12  行政区划代码位数  层级为3级时通常使用6位代码 如110000,层级为5级时使用12位代码 如 110000000000
head_url = "index"  # 可选:index|各省行政区划前两位  要从哪开始获取 index为全国所有省份  要获取单独的省份修改为省行政区划的前两位

# config #


context = ssl._create_unverified_context()
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'
}
mainUrl = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/'
attrsClassArr = ['provincetr', 'citytr', 'countytr', 'towntr', 'villagetr']


def is_CN(word):
    for ch in word:
        if '\u4e00' <= ch <= '\u9fff':
            return True
    return False


def retry(times):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            i = 0
            while i < times:
                try:
                    if i > 0:
                        print('正在尝试第%d次请求' % (i+1))
                    return func(*args, **kwargs)
                except:
                    #	此处打印日志  func.__name__ 为say函数
                    print('%s 请求失败!' % (args[0]))
                    # print("logdebug: {}()".format(func.__name__))
                    i += 1
        return inner_wrapper
    return wrapper


@retry(5)
def fetchAreaData(url, index, attrsClass, area):
    if index < level:
        try:
            with urllib.request.urlopen(url, context=context, timeout=3) as response:
                soup = BeautifulSoup(response.read(), 'html.parser')
                tag = soup.find_all(attrs={"class": attrsClass})
                for tg in tag:
                    villageArr = []
                    for tgc in tg.children:
                        if tgc.a:
                            if is_CN(tgc.a.get_text()):
                                print('正在请求', '/'.join(url.split('/')
                                                       [0:-1]) + '/' + tgc.a.attrs['href'], tgc.a.get_text())
                                if index + 1 == level:
                                    area.append(
                                        {"value": tgc.a.attrs['href'].split('/')[-1].replace('.html', '').ljust(digit, '0'), "label": tgc.a.get_text()})
                                else:
                                    content = {"value": tgc.a.attrs['href'].split(
                                        '/')[-1].replace('.html', '').ljust(digit, '0'), "label": tgc.a.get_text(), "children": []}
                                    area.append(content)
                                    fetchAreaData(
                                        '/'.join(url.split('/')[0:-1]) + '/' + tgc.a.attrs['href'], index+1, attrsClassArr[index+1], area[len(area)-1]['children'])
                        elif attrsClass == 'villagetr':
                            villageArr.append(tgc.get_text())
                    if len(villageArr) > 0:
                        area.append(
                            {"value": villageArr[0], "label": villageArr[2]})
        except urllib.request.URLError as e:
            print("出现异常: "+str(e))


position = 0
areas = []
if head_url != 'index':
    position = 1

fetchAreaData(mainUrl+year+'/'+head_url+'.html',
              position, attrsClassArr[position], areas)
with open(head_url+'_'+year+'_'+"_level_" + str(level)+'.json', "w", encoding='utf-8') as json_file:
    json.dump(areas, json_file, ensure_ascii=False)
    print("写入%s完成" % (head_url+'_'+year+'_'+"_level_" + str(level)+'.json'))


# code = ['11', '12', '13', '14', '15', '21', '22','23', '31', '32', '33', '34', '35', '36', '37',
#         '41', '42', '43', '44', '45', '46', '50', '51', '52', '53', '54', '61', '62', '63', '64', '65']
# for index in range(24):
#     areas = []
#     head_url = code[index]
#     position = 0
#     if head_url != 'index':
#         position = 1
#     fetchAreaData(mainUrl+year+'/'+head_url+'.html',
#                   position, attrsClassArr[position], areas)
#     with open('province/level_5/'+head_url+'_'+year+'_'+"_level_" + str(level)+'.json', "w", encoding='utf-8') as json_file:
#         json.dump(areas, json_file, ensure_ascii=False)
#         print("写入%s完成" % (head_url+'_'+year+'_'+"_level_" + str(level)+'.json'))

React Hooks 请求库

github.com/vercel/swr

有点东西

ReactNative App 版本升级封装 ,支持 Android 、iOS

github.com/songxiaolia…

zhuanlan.zhihu.com/p/93824106

flutter 高仿 wechat --学习 flutter 做准备

github.com/CoderMikeHe…

github.com/DiscoverFor…

github.com/simplezhli/…