对于一项技术,我们不能停留在五分钟状态,特别喜欢一句话,用什么方式绘制UI界面一点不重要,重要的是底层的思维,解决问题和优化的思路。
React 的生态极为庞大,本文内容部分来自一些别人的汇总,至于原文只要还是能找到的,我都会贴上地址,谢谢前期贡献的作者,如果有没有被汇总到的,欢迎在下面补充。 React 官方推荐超大型项目使用的 TypeScript TypeScript 放在第一位,因为 TypeScript 在构建超大型应用时,多人协作可以极大的加快工作效率,特别是前后端交互特别多,业务情况特别复杂的状况下(比如 IM ),它的优势就凸显出来了。但是在一些中小型项目中,优势并不是那么的明显。(比如做完项目跑路后期不迭代这种)
TypeScript 并不是一个新语言,可以简单的认为 TS = js + Type .它只是一个 javascript 的超集,目前更新速度也是非常快,
Node.js 开发和 React native 以及大型 React 中使用 TypeScript 在下载官方的 react 脚手架中,包含了一个第三方的 ts 创建脚手架的命令
Create React App 中使用 TypeScript Create React App 内置了对 ·TypeScript` 的支持。 npx create-react-app my-app --typescript interface IState {
collapsed?: boolean,
}
interface IProps {
props?: string | Function
}
constructor(props: IState) {
super(props)
}
flag :number = 123
componentDidMount() {
const result = this.FunctionTest()
}
FunctionTest():Promise<number|string|object>{
return Promise.resolve(false)
}
TypeScript 写起来代码量会多一些,但是对于参数类型,返回类型,一眼明了,拥有静态类型检查,如果有问题,在编写代码时候就可以知道。 补充一点,现在 TS 的生态已经足够适应开发,像一般的 webpack 插件都有了 typescript 的文件支持,当然,并不是所有的第三包都支持 ts .在技术选型的时候就要考虑清楚这点,否则就会多做很多事情。
redux,mbox,redux-sage,dva 等开源库 react 数据管理
组件间数据的传递,依靠 props ,状态数据提升等完成,但是对于跨层级的组件间数据传递,就不那么友好了,尤其是大型项目后期的迭代维护
redux .
Redux
<App/> 里面抽取出来, 成为独立的 store , 页面逻辑就是 reducer <TodoList/> 及<AddTodoBtn/> 都是 Pure Component , 通过 connect 方法可以很方便地给它俩加一层 wrapper 从而建立起与 store 的联系: 可以通过 dispatch 向 store 注入 action , 促使 store 的状态进行变化, 同时又订阅了 store 的状态变化, 一旦状态有变, 被 connect 的组件也随之刷新 dispatch 往 store 发送 action 的这个过程是可以被拦截的, 自然而然地就可以在这里增加各种 Middleware , 实现各种自定义功能, eg: logging 在面试的时候,我觉得如果可以手写一个 redux 库,并且说清楚单向数据流的思维,是一个加分项。
dva ,感谢前辈的开源,解放了我们
dva
// 一个dva的模块文件 user.js
export default {
namespace: 'userinfo',
state: {
width: '-100%',
hasUserInfoActive: false,
info: undefined,
},
reducers: {
// 打开个人资料
open(state) {
return {
...state,
width: '0%',
hasUserInfoActive: true,
};
},
},
effects: {
* init(res, { put, select }) {
const { userinfo } = yield select();
if (userinfo.info === undefined) {
try {
const list = yield DATABASE.Friend().getSelfInfo();
// console.log(list);
yield put({ type: 'saveUserInfo', payload: list });
} catch (e) {
console.error(e);
}
}
},
},
};
// user.jsx,业务组件文件
import {connect} from 'dva'
class App extends Component {
componentDidMount(){
//省掉了mapActionsToPops这一步
this.props.dispatch({
type:"user/open"
})
}
}
export default connect(
//相当于mapStateToState,可以通过this.props.user拿到数据
(({user} )=>{
user
} )
)(App)
状态管理的最佳实践,应该说推荐 dva ,再次感谢前辈的开源。
UI 组件库,由于本人平时都不使用 UI 库了,所以可能会遗漏。 Ant-Design , pc 版 ,制作后台管理系统的神器,同样要感谢前辈们的开源。
webpack 按需加载,配置默认样式,
使用 babel-plugin-import(推荐)。
// .babelrc or babel-loader option
{
"plugins": [
["import", {
"libraryName": "antd",
"libraryDirectory": "es",
"style": "css" // `style: true` 会加载 less 文件
}]
]
}
然后只需从 antd 引入模块即可,无需单独引入样式。等同于下面手动引入的方式。
// babel-plugin-import 会帮助你加载 JS 和 CSS
import { DatePicker } from 'antd';
Ant-Degsin-mobile
使用 babel-plugin-import(推荐)。
// .babelrc or babel-loader option
{
"plugins": [
["import", { libraryName: "antd-mobile", style: "css" }]
// `style: true` 会加载 less 文件
]
}
然后只需从 antd-mobile 引入模块即可,无需单独引入样式。
// babel-plugin-import 会帮助你加载 JS 和 CSS
import { DatePicker } from 'antd-mobile';
Ant Design Mobile RN of React
在 react-native 中使用 Ant-Design
yarn add @ant-design/react-native 在 babel 配置中:
"plugins": [
["import", { libraryName: "@ant-design/react-native" }]
] React-native 组件中使用: import React from 'react';
import { View, Text, FlatList, SectionList, Alert } from 'react-native';
import { Button, Flex } from '@ant-design/react-native';
export default class Apps extends React.Component {
render() {
return (
<View>
<Button
onPress={() => {
Alert.alert(12312312);
}}
>
12345561
</Button>
</View>
);
}
}
Electron , PC 端跨平台技术方案,集成 Node ,可以开发极为复杂的应用
remote 模块或者 ipc 通信方式进行通信,进而可以呼叫原生接口 mac os , windows , linux 上的三端统一开发没有兼容性问题的框架 Electron 结合了 Chromium、Node.js 和用于调用操作系统本地功能的 API (如打开文件窗口、通知、图标等) Electron 的开发就像在开发网页,而且能够无缝地 使用 Node 。或者说:在构建一个 Node 应用的同时,通过 HTML 和 CSS 构建界面。另外,你只需为一个浏览器(最新的 Chrome )进行设计(即无需考虑兼容性等)
import React from 'react';
import { HashRouter, Route, Switch } from 'dva/router';
import { ipcRenderer, remote } from 'electron';
ipcRenderer.removeAllListeners();
ipcRenderer.on('loginSuccess', () => {
ipcRenderer.send('reply', 'loginSuccess');
props.history.push('/login/loading');
props.dispatch({ type: 'globalstate/saveStatus', payload: 1 });
});
这是一个非常不错,而且考验一位前端工程师底层技术的框架,可能会写到大量底层 Node.js 和原生 javascript ,目前开发 IM 项目很多使用这个框架。 github 上的 star 量也快 80K 了。
react-native ,移动端跨平台框架 跨平台开发首选 Mac ,没有为什么
react-native run-ios command+d
react 迁移到 react-native 成本并不高,难的是适配和踩坑,遇到问题要多百度, rn 的生态也很强大,而且给我们封装了很多内容,也可以使用一些原生的接口.
React-native 的层次架构:
Java层 :该层主要提供了 Android的UI渲染器UIManager (将JavaScript映射成Android Widget)以及一些其他的功能组件(例如:Fresco、Okhttp)等,在java层均封装为Module,java层核心jar包是 react-native.jar ,封装了众多上层的interface,如Module,Registry,bridge等。 C++层 :主要处理 Java与JavaScript 的通信以及执行JavaScript代码工作,该层封装了JavaScriptCore,执行对js的解析。基于JavaScriptCore,Web开发者可以尽情使用ES6的新特性,如class、箭头操作符等,而且 React Native运行在 JavaScriptCore 中的,完全不存在浏览器兼容的情况。Bridge桥接了java , js 通信的核心接口。JSLoader主要是将来自assets目录的或本地file加载javascriptCore,再通过JSCExectutor解析js文件。 Js层 :该层提供了各种供开发者使用的组件以及一些工具库。 Component :Js层通js/jsx编写的Virtual Dom来构建Component或Module,Virtual DOM是DOM在内存中的一种轻量级表达方式,可以通过不同的渲染引擎生成不同平台下的UI。component的使用在 React 里极为重要, 因为component的存在让计算 DOM diff 更高效。 ReactReconciler : 用于管理顶层组件或子组件的挂载、卸载、重绘。 https://webkit.org
家的jsc.so。
启动过程的解析:
ReactInstanceManager 创建时会配置应用所需的java模块与js模块,通过 ReactRootView 的 startReactApplication启动APP 。 ReactInstanceManager 同时会创建用于加载JsBundle的JSBundlerLoader,并传递给 CatalystInstance 。 CatalystInstance 会创建Java模块注册表及Javascript模块注册表,并遍历实例化模块。 CatalystInstance通过JSBundlerLoader 向Node Server请求Js Js与Java通信机制
Java 调用 Js
Java 通过注册表调用到 CatalystInstance 实例,透过ReactBridge的jni,调用到Onload.cpp中的callFunction,最后通过javascriptCore,调用BatchedBridge.js,根据参数{moduleID,methodID}require相应Js模块执行。流程如下图:
Java 处理的逻辑,而且 Java 超过 5ms 都没有来取走,那么 JavaScript 就会主动调用 Java 的方法,在需要调用调 Java 模块方法时,会把参数 {moduleID,methodID} 等数据存在 MessageQueue 中,等待Java的事件触发,把 MessageQueue 中的 {moduleID,methodID}返回给Java ,再根据模块注册表找到相应模块处理。流程如下图:
参考文章,react-native原理解析 ,看在 react-native 跨平台开发的无缝对接 js和react 份上,我决定坚定使用它。希望在1.0版本到来的时候,给我们一个惊喜。
Taro ,多端解决方案
Taro 是一套遵循 React 语法规范的 多端开发 解决方案。现如今市面上端的形态多种多样, Web、React-Native、 微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。 Taro ,我们可以只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信/百度/支付宝/字节跳动小程序、 H5、React-Native 等)运行的代码。
import Taro, { Component } from '@tarojs/taro'
import { View, Button } from '@tarojs/components'
export default class Index extends Component {
constructor () {
super(...arguments)
this.state = {
title: '首页',
list: [1, 2, 3]
}
}
componentWillMount () {}
componentDidMount () {}
componentWillUpdate (nextProps, nextState) {}
componentDidUpdate (prevProps, prevState) {}
shouldComponentUpdate (nextProps, nextState) {
return true
}
add = (e) => {
// dosth
}
render () {
return (
<View className='index'>
<View className='title'>{this.state.title}</View>
<View className='content'>
{this.state.list.map(item => {
return (
<View className='item'>{item}</View>
)
})}
<Button className='add' onClick={this.add}>添加</Button>
</View>
</View>
)
}
}
Taro 拥有自己的脚手架 脚手架配置 为什么会加入 Taro ,因为它是国产,基于 react ,应该支持。而且相信未来它应该有不错的前景。
环境搭建:
yarn global add @tarojs/cli taro init myApp
# yarn
$ yarn dev:weapp
$ yarn build:weapp
# npm script
$ npm run dev:weapp
$ npm run build:weapp
# 仅限全局安装
$ taro build --type weapp --watch
$ taro build --type weapp
# npx 用户也可以使用
$ npx taro build --type weapp --watch
$ npx taro build --type weapp
# yarn
$ yarn dev:h5
# npm script
$ npm run dev:h5
# 仅限全局安装
$ taro build --type h5 --watch
# npx 用户也可以使用
$ npx taro build --type h5 --watch
React Native # yarn
$ yarn dev:rn
# npm script
$ npm run dev:rn
# 仅限全局安装
$ taro build --type rn --watch
# npx 用户也可以使用
$ npx taro build --type rn --watch
Taro 也拥有自己的生态圈,非常庞大,非常感谢京东的开源,希望它的功能越来越强大。
React 本身很强大,生态圈非常强大,可以说任何平台的大型应用都可以让它来做,加上 hook 的出现,未来可期。 UI 并不重要,但是本人觉得 js 和 react 的无缝对接下更偏向 rn , taro , electron 这类型的框架开发跨平台应用。 react 的优化汇总,觉得写得不错的可以点个赞~谢谢