日常及初入React Native开发问题总结

2,428 阅读3分钟
  • 本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

前言

  • 作为一个开发人员,在开发过程中肯定会遇到各种各样的技术问题,尤其在使用一个新的技术的时候。本文记录了一些我最近遇到的一些思考和问题,包含一些低级的错误,我们应该避免。

循环引用

// A.js
import { bname } from './B.js';
console.log('A Module,bname=', bname);
export const aname = 'A';

// B.js
import { aname } from './A.js';
console.log('B Module,aname=', aname);
export const bname = 'B';

代码性能

  • 实现同样的功能,不同的写法性能肯定是不一样的。

1:提前返回

  • 例如当我们需要查找一个值是否在一个数组的某个对象中时,我们会去遍历,遍历的方式就有很多可以选了,例如:forEach、map、for、for...of、for...in等等。
  • for, for...in,for...of,forEach, map 的区别?
const target = ''
const list = []
// 正常写法
list.forEach(item => {
    if(item.key === target){
        // ...
    }
})
// 优化
const len = list.length
for(let i = 0; i < len; i ++) {
    if(item.key === target){
        // ...
        break;
    }
}

例2:有更快的方法

  • 原生的 Dom 操作大家肯定都很熟悉了,常用的 document.addEventListenerdocument.querySelector... 等等。新增的 API 有更强大的功能,但如果针对某些特定的条件,我们应该选择更快的 API
// 功能更全、更强的
document.querySelector
document.querySelectorAll
...
// 更快的
document.getElementById
document.getElementsByClassName
...

清除指定路径、域名下的 cookie

  • 当我们需要保存用于其他网站登录的 cookie 时,我们需要存到指定的路径下,不用时清除对应的 cookie
  • 设置 cookie 为已过期后,浏览器会自动清除对应的 cookie
const clearCookie = (path = '/', domain = document.domain) => {
  const keys = document.cookie.match(/[^ =;]+(?==)/g);
  const overdueTime = new Date(0).toUTCString();
  if (keys) {
    const len = keys.length;
    for (let i = 0; i < len; i++) {
      document.cookie = `${keys[i]}=0;path=${path};expires=${overdueTime}`; // 清除当前域名下的
      document.cookie = `${keys[i]}=0;path=${path};domain=${document.domain};expires=${overdueTime}`; // 清除当前域名下的
      document.cookie = `${keys[i]}=0;path=${path};domain=${domain};expires=${overdueTime}`; // 清除指定域名下
    }
  }
};

npm包无法安装

公共包

// 1. 切换 taobao 镜像源
npm config set registry https://registry.npm.taobao.org
// 2. 使用 cnpm
// 3. 开启翻墙/代理

私有包

  • 当我们需要安装一些私有发布的包(例如公司内部封装发布的)时,使用 yarn 等工具安装提示失败时。
// 1. 修改 yarn.lock
找安装成功的人看是否提交了对应的yarn.lock文件,修改对应包的文件配置,重新安装即可。
// 2. 设置镜像源为内部镜像源地址
npm config set registry [内部镜像源地址]

Chrome 调试手机端 h5

  • 使用Chrome://inspect调试 Android 设备上Webview
  • 注意:
    1. 需要手机打开一个 h5 页面;
    2. 手机和电脑连同一网络;
    3. App 内无法调试找原生(Android、iOS开发人员)看一下对应的包是否有问题;
    4. 进去一直白屏,打开翻墙/代理。

React Native 相关

  • 最近做 React Native 的开发遇到的一些问题。

App 返回拦截未生效

  • 调试拦截 App 内触发返回操作时,不要在 App 首页调试,App 首页会触发 App 的退出功能。

Chrome调试 VS 真机调试

  • 由于之前没做过 React Native 的开发,对它的运行机制不是很了解,导致出现了一个问题(判断手机的系统)。
  • 我在本地开发使用的 Chrome 浏览器中调试,所以我使用的是window.navigator.userAgent 来判断,调试也没有任何问题。
export function isAndroid_ios() {
    let u = window.navigator.userAgent
    let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //ios终端
    let isIOS1 = u.indexOf('iPhone') > -1 || u.indexOf('iOS') > -1
    return isiOS || isIOS1 ? 'ios' : 'android'
}
  • 当我发布后在手机上却导致功能无法使用,通过不断排查才找到问题原因就是手机上无法使用 window.navigator.userAgent。要使用 React Native 中的 Platform,通过它的 OS 属性来判断。
// 使用
import { Platform } from 'react-native';
Platform.OS === 'ios' ? 'ios' : 'other';

// 源码部分
export const Platform:
    | PlatformIOSStatic
    | PlatformAndroidStatic
    | PlatformWindowsOSStatic
    | PlatformMacOSStatic
    | PlatformWebStatic;
    
// 以 PlatformIOSStatic 为例
interface PlatformIOSStatic extends PlatformStatic {
    constants: PlatformConstants & {
        forceTouchAvailable: boolean;
        interfaceIdiom: string;
        osVersion: string;
        systemName: string;
    };
    OS: 'ios';
    isPad: boolean;
    isTVOS: boolean;
    Version: string;
}
  • 原因是两者使用的 JavaScript 引擎不同。当在 Chrome 中使用远程调试时,它几乎在浏览器中运行 RN 应用程序(然后使用 V8 JavaScript 引擎)并通过 WebSockets 与模拟器(或设备)通信。如果在没有启用远程调试的情况下运行,它将使用JavaScript Core。这些环境之间存在许多差异,这些差异可能会导致不一致,所以不要仅仅依靠启用 JS 调试来运行应用程序,它可能会给您带来错误错误或隐藏实际会导致实际设备出现问题的错误。
  • JavaScriptCore学习之JavaScriptCore

屏幕展示方向设置

获取屏幕的宽高

  • 通过 react-native-orientation 中的addOrientationListener 方法可以监听屏幕方向的变化,执行下面获取函数。
import { Dimensions } from 'react-native';

// Dimensions.get('window').height* 皆为无刘海高度(含安全区及全面屏模式)
// Dimensions.get('screen').height* 皆为有刘海高度(含安全区及全面屏模式)
// ExtraDimensions.get('REAL_WINDOW_HEIGHT')* 皆为含刘海高度(含安全区及全面屏模式)

export function getCurrentScreen(mode: 'window' | 'screen' = 'screen') {
  const width = Dimensions.get(mode).width;
  const height = Dimensions.get(mode).height;
  return [width, height];
}

App 前台、后台运行状态

// React Native
import { AppState } from 'react-native';
const _handleAppStateChange = (nextAppState) => {
    if (nextAppState !== null) {
        if ( nextAppState === 'active') { // 前台
            // ...
        } else if ( nextAppState === 'background') { // 后台
            // ...
        }
    }
}
// Web
document.addEventListener("visibilitychange", () => {
    if (document.hidden) { // 后台
        // ...
    } else { // 前台
        // ...
    }
});

结语

  • 欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送 100 份掘金周边,抽奖详情见活动文章。

往期精彩

「点赞、收藏和评论」

❤️关注+点赞收藏+评论+分享❤️,手留余香,谢谢🙏大家。