好久没有写文章了,因为最近比较忙,也没时间写开源项目,最近抽出了一点时间改善 IceE 这个项目,写一篇教程供大家使用吧
github:https://github.com/IceEmblem/IceE
本文使用的是 icetf 0.3.1 版本,不同版本代码稍有差别
大多数的企业Web站点和移动RNApp都会有相同的JS逻辑(比如下单的验证,支付的验证等),那么我们要维护2份一模一样的代码吗?IceE 就是解决这个问题,你可以将公共的JS代码分离到公共的 package 中,下面是IceE的框架结构,看了这个结构,你应该猜到 ice-core 就是那个公共的 package
下面项目:git clone https://github.com/IceEmblem/IceE.git
安装包:yarn install
运行
Web 端:yarn start:web
android 端:yarn start:android
ios 端:yarn start:ios
注:IceE
的模块在框架启动时会初始化该模块,模块可以向框架注册他的功能,比如页面,主题等,你安装后访问到该模块提供的页面或主题等功能,你无需编写一行代码
通过如下教程完成 mymodule 模块的编写
1. 简单的模块
1)执行 node icee cw mymodule 命令,生成 mymodule 模块,生成成功后 packages 下面会多出一个文件夹,这就是我们的模块了
2)执行 yarn install 安装依赖
3)现在我们将 Module.js 代码改为如下:
该代码向框架注册一个页面
import React from 'react'
import {
BaseModule, PageProvider, ModuleFactory, Page} from 'icetf'
import {
Module as CoreModule} from 'ice-core';
export default class Module extends BaseModule
{
initialize(){
// 注册页面,访问 /mymodule 将显示这个页面
PageProvider.register(new Page("mymodule", "/mymodule", (props) => <div>Hello MyModule!!!</div>));
}
}
ModuleFactory.register(Module, [CoreModule]);
4)执行 yarn start:web 运行站点,访问 /mymodule 页面,就可以看到我们注册的页面了
2. 应用redux
现在我们来应用 redux,IceE 对 redux 进行了封装,如果不清楚 redux,请查看官网文档。
1)新建一个Reduxs文件夹
其中包含3个文件
Action.js: 存放我们的 action 类型和 createAction 函数,如下
// 加
export const Add = "Add";
export function createAdd(num) {
return {
type: Add,
num: num
}
}
// 减
export const Subtract = "Subtract";
export function createSubtract(num) {
return {
type: Subtract,
num: num
}
}
Reducer.js: 存放我们的 reducer,如下
import {
Add, Subtract} from './Actions'
export function reducer(state = {
num: 0 }, action)
{
if(action.type == Add){
return {
num: state.num + action.num
}
}
if(action.type == Subtract){
return {
num: state.num - action.num
}
}
return state;
}
MyRedux.js: 该类就相当与命名空间,时我们的 acion 和其他模块的 action 不冲突,其代码很简单,如下
import {
BaseIceRedux } from 'icetf';
import {
reducer } from "./Reducer";
class Redux extends BaseIceRedux {
reducer = reducer;
constructor() {
// 命名,用于区分其他模块的 action
super("My");
}
}
export default new Redux();
2)在Module中注册我们的 reducer
import {
BaseModule, ModuleFactory, IEStore} from 'icetf'
import {
Module as CoreModule} from 'ice-core';
import MyRedux from './Reduxs/MyRedux'
export default class Module extends BaseModule {
initialize() {
// 注册当前模块的 reducer
IEStore.register(MyRedux);
}
}
ModuleFactory.register(Module, [CoreModule]);
3)在代码中使用 redux
现在我们编写一个页面
其代码如下:
import React from 'react'
import MyRedux from '../Reduxs/MyRedux'
import {
createAdd, createSubtract} from '../Reduxs/Actions'
class MyPage extends React.Component {
render() {
return <div>
<div>总数:{
this.props.num}</div>
{
/* 加1按钮 */}
<button onClick={
() => {
this.props.add(1);
}}>+1</button>
{
/* 减1按钮 */}
<button onClick={
() => {
this.props.subtract(1);
}}>-1</button>
</div>
}
}
// redux 的 mapStateToProps
// state 就是当前模块的 state
const mapState = (state, props) => {
return state;
}
// redux 的 mapDispatchToProps
const mapDispost = (dispatch, props) => {
return {
add: (num) => {
return dispatch(createAdd(num));
},
subtract: (num) => {
return dispatch(createSubtract(num));
}
}
}
// 使用 MyRedux 的 connect 生成组件
export default MyRedux.connect(mapState, mapDispost)(MyPage)
4)在module中注册页面
import {
BaseModule, ModuleFactory, IEStore, PageProvider, Page} from 'icetf'
import {
Module as CoreModule} from 'ice-core';
import MyRedux from './Reduxs/MyRedux'
import MyPage from './MyPage'
export default class Module extends BaseModule {
initialize() {
// 注册当前模块的 reducer
IEStore.register(MyRedux);
// 注册页面
PageProvider.register(new Page("MyPage", "/MyPage", MyPage));
}
}
ModuleFactory.register(Module, [CoreModule]);
5)访问 /MyPage 就能看到我们的页面了
3. 注册中间件
现在我们注册一个打印 redux action 的中间件
1)编写代码
其代码如下:
// 注册一个 Redux 中间件
export default (store) => (next) => (action) => {
console.log(action);
return next(action)
}
2)在module中注册中间件
import {
BaseModule, ModuleFactory, IEStore, PageProvider, Page, MiddlewareFactory} from 'icetf'
import {
Module as CoreModule} from 'ice-core';
import MyRedux from './Reduxs/MyRedux';
import MyPage from './MyPage';
import LogMiddlewares from './Middlewares/LogMiddlewares'
export default class Module extends BaseModule {
initialize() {
// 注册当前模块的 reducer
IEStore.register(MyRedux);
// 注册页面
PageProvider.register(new Page("MyPage", "/MyPage", MyPage));
// 注册中间件
MiddlewareFactory.register(LogMiddlewares);
}
}
ModuleFactory.register(Module, [CoreModule]);
3)查看效果
Icetf 对 fetch 进行了一个封装,其封装类为IceFetch,ice-core 的 Module 文件做了一个简单的示例
preInitialize(){
// 注册 fetch 后面可以使用 IceFetch 进行网络请求
// fetchData: fetch 请求的数据
// 返回值: Promise<Response>
IceFetch.registerFetch((fetchData: any) => {
return fetch(fetchData.url, fetchData.header)
});
// 注册一个结果处理器,使用 IceFetch 请求的结果会先通过该处理器处理
// responst: fetch 请求结果
// fetchData: fetch 请求的数据
// actionType: redux 的 action 类型
// 返回值: 处理后的数据,会作为下一个 handler 的 responst
IceFetch.registerHandler((responst: Response, fetchData: any, actionType: string) => {
return responst;
})
}
registerFetch: 当前使用的请求函数。
registerHandler: 请求接受后的处理器。
IceFetch提供的网络请求函数
1)IceFetch.createThunkAction(fetchData: any, actionType: string)
用于生成异步 action,fetchData 原样转给注册的 fetch 函数,在请求时 IceFetch 向 redux 分发 “IEFecth_Request” 类型的 action,在接收后 IceFetch 向 redux 分发 actionType 类型的 action,在出错后,IceFetch 向 redux 分发 “IEFecth_Error” 类型的 action。
2)IceFetch.ieReduxFetch(fetchData: any)
ieReduxFetch 是一个网络请求函数,不是一个 createAction 函数,其通过 createThunkAction 生成异步 action 并直接发生给 redux ,其使用的 actionType 类型为 “IEFecth_Receive”