wiz-frameworks是wizlong的框架项目,封装了React项目的启动流程和一些框架工具。
npm install git+https://gitlab.wizlong.com/sgm/wiz-frameworks.git
import init from 'wiz-frameworks';
let app = init({
//路由参数
createRoutes,
//静态模型
models:[login,systemMenu],
//动态模型
appDevModels: appDevModels(),
//本地设置
initLocalSetting: {
env: require('./constants/constants_env'),
files: require('./constants/constants_file'),
urls: require('./constants/constants_url')
},
//全局变量
initGlobal: {
Storage:Storage,
wizNotice:WizNotice
},
//网络检查
networkCallback:(networkCallback)=>{
log.info('networkCallback:',networkCallback;
},
//插件
use:[
createLoading(),v
{ onError: exception }
],
//请求对象
request:{
...
},
//请求默认设置
requestConfig:{
...
},
//路由
router:{
...
},
//路由参数
createRoutes:{
...
},
//日志参数
recodeLog: true,
recodeLogParams: {
userLogKey: app_user_log_key,
sysLogKey: app_sys_log_key,
}
});
export default app;
MIT Copyright (c) 2018 - forever Naufal Rabbani
数据模型指的是Dva中的model(Dva中包含了Redux,model是Dva对Redux流程简化的一种用法),简单来说,Redux是为了统一管理多样和复杂的state(指的是React 的state),使用Redux帮助我们处理数据流转的过程。model中处理了核心的三件事情:注册state,处理state,返回新的state。
framework支持两种定义model的方式
2.1 静态模型
静态模型是Dva中model的使用方式,在项目启动时进行加载。 数据模型例子如下:
import { routerRedux } from '../../utils'
import { requestUrl } from 'wiz-frameworks'
export default {
//标记model
namespace: 'login',
state: {
loggedIn: false,
message: '',
user: {},
},
subscriptions: {
setup({ history, dispatch }) {
return history.listen((params) => {
let { pathname } = params;
if (pathname.indexOf('/sign/login') !== -1) {
storage.removeStorage('user');
storage.removeStorage('token');
}
});
}
},
//处理state
effects: {
*login({ payload }, { call, put }) {
if (network()) {
const { code, msg, token, data } = yield call(requestUrl.post, constants.urls.kUrlLogin, payload);
if (code == 0) {
storage.setStorage('user', data);
storage.setStorage('token', token)
log.info('storage.getStorageInfo():',storage.getStorageInfo())
yield put({
type: 'loginSuccess',
payload: data
});
yield put(routerRedux.replace('/home'));
} else {
yield put({
type: 'loginError',
payload: { message: msg }
});
}
} else {
wizNotice.error('请求失败,当前网络不可用');
}
},
*logout(_, { put }) { }
},
//返回新的state
reducers: {
loginSuccess(state, { payload }) {
return {
...state,
loggedIn: true,
message: '',
user: payload
};
},
loginError(state, { payload }) {
let timeStamp = new Date().getTime();
return {
...state,
loggedIn: false,
message: payload.message,
loginTimeStamp: timeStamp
};
},
}
};
2.2 动态模型
动态模型是framework提供的快速配置model的方式,主要用于从接口获取数据。model可以在localDevModel.js中进行配置(也提供从接口中获取的方式) 动态模型配置方式如下:
let modelConfig = {
businessName: 'testLogin',//业务名称
modelType: 'entity',
action: {
doLogin: {//action方法名
api: urls.kUrlLogin,//url是全局变量
methodType: 'POST',//接口的请求方式
params: ['password', 'username'],//接口需要传参
returnField: {}//返回值的获取
},
},
initData: {}//初始化state
}
在framework中,数据模型的使用分为三个步骤: 3.1 doAction作出获取数据的动作
this.doAction({
path: 'testLogin/doLogin',
payload: {
key: 'test@Login',
apiParams: { pageNum: 1, pageSize: 1 }
},
})
3.2 从Redux的state中获取数据
const mapStateToProps = (state, ownProps) => {
const { testLogin } = state;
//根据businessName 和 key 获取数据
const test = modelUtils.getModelEntity(testLogin, 'test@Login');
//获取loading的方式
const load = modelUtils.getLoadingState(state,'testLogin')
//将数据放入容器的props
return {
testLogin: test,
...load
};
};
3.3 通过propsAndStateOnChange监听实例属性的变化
//对所需要的实例属性进行监听
propsAndStateOnChange = {
testLogin: this._testLogin.bind(this)
}
//监听方法,入参与shouldComponentUpdate的相同
_testLogin(nextProps,nextState){
//do something
}
组件化是React中的重要概念,framework使用的是wiz-components封装的WizComponent(wiz-components中已介绍,此处不再赘述)
Dan(React的作者)认为可以把组件分为两类,一类是纯展示类(外貌协会的,只负责UI,更关心长成什么样),另一类是容器类(靠脑子的组织者,一般不直接包含UI,而是内部再包着 纯展示类或容器类组件,更关心怎么工作的)。至此,framework把页面称为容器,一个容器代表了页面上面的一个页面,组件组成了容器。所以WizContainer诞生了。
######WizContainer做了什么?
- WizContainer继承了WizComponent(当然,WizContainer也是组件,但是framework把它定义为容器)
- 封装了生命周期的所有方法,在WizContainer中使用生命周期请在方法前加上
_
,例如_componentDidMount
在JavaScript的变量名或函数名前加“_” 。 在变量名或函数名前加下划线,一般表示“私有”。是约定俗成的开发规范,没有强制限制,类似于类名首字母大写。加下划线,还能有效防止重名。
- 提供了Redux的dispatch的封装
doAction
this.doAction({
path: 'testLogin/doLogin',
payload: {
key: 'testLogin',
apiParams: { username: 'mll', password: '123456' }
},
})
- 提供了路由工具
jumpPage
this.jumpPage('replace', '/sys', { name: 'mll', age: 18 })
启动流程的基础是参照dva的启动项目流程
// 创建应用
const app = dva();
// 注册 Model
app.model({
namespace: 'count',
state: 0,
reducers: {
add(state) { return state + 1 },
},
effects: {
*addAfter1Second(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'add' });
},
},
});
// 注册视图
app.router(() => <ConnectedApp />);
// 启动应用
app.start('#root');
框架是通过framworks中的init()方法进行启动,启动流程中处理的内容如下:
设置全局的constants内容,目前constants中存放了urls、env、file的内容。url存放接口调用地址,env存放系统的业务设置,file记录了文件地址
let logo = constants.file.sys_main_logo
let loginUrl = constants.urls.kUrlLogin
let htmlTitle = constants.env.app_html_title
全局变量是将常用的组件或者工具等放入global中,方便直接使用,目前框架默认存放了log、storage、wizNotice、network。
log.info('项目启动后,全局变量在任何地方都可以直接使用')
wizNotice.error('请求失败,当前网络不可用')
storage.setStorage('mll','mll so cool')
if(network.getNetworkState()){
log.info('网络畅通!')
}else{
log.info('断线了!')
}
网络监控主要是监控网络连接状态,当网络连接状态变化时进行相关提醒
在framework启动时将动态模型和静态模型配置到dva中
插件指的是Dva配套的一些工具的使用,目前framework默认使用dva-loading(Dva的插件)和onError(framework提供)
framework启动时设置了默认的请求对象,目的对请求的统一管理和简化请求的使用方式,目前使用的请求工具是cmn-utils的request
framework启动时设置了默认的loading渲染工具
framwork主要记录用户行为日志和系统日志,主要记录在Storage,后续待实现上传服务器
1. 系统日志 目前系统日志记录了错误日志,当浏览器页面Error时记录。
2. 用户行为日志 2.1 路由日志 当路由发生变化时记录的日志,通过监听路由路径实现。
2.2 接口路由 当请求发送时记录日志,通过记录用户doAction时的状态变化实现。
2.3 操作路由
当用户点击元素时记录日志,记录标记有两种:
2.3.1 页面元素中含有data-wiz-log
标记
2.3.2 init方法中传入需要监控的元素的标签,比如:['button','a']
frameworks会在项目启动时初始化路由,并且简化了配置路由的方式,详细见rotue目录内index.js
const _routesConfig = [{
path: '/',
title: '',
indexRoute: '/home',
component: MainLayout,
childRoutes: [
{ key: 'login', title: '登录', path: '/sign/login', component: Login },
{ key: 'home', title: '首页', path: '/home', component: Home },
{ key: '404', title: '页面没有找到', path: '', component: P404 },
]
}]
framework引入模版概念是想通过配置的方式完成前台的一些页面,模版的概念就是将一些组件可以通过配置的方式渲染出来。项目默认将wiz-components中的组件全部模版化了。
不使用模版的页面:
import { WizRate } from 'wiz-components'
class Test {
render(){
return(
<WizRate
key = {'WizRate'}
allowHalf = {true}
defaultValue = {2.5}
/>
)}
}
使用模版的界面:
import { templateUtils } from 'wiz-frameworks'
class Test {
render(){
return templateUtils.getComponentByConfi([{
name: 'WizRate',
params: {
key: 'WizRate',
allowHalf: true,
defaultValue: 2.5
}
}])
}
}
framework的init()
中的启动流程提供了单独使用的方法,可以单独使用
初始化模版组件内已描述,此处不再赘述
容器与组件内已描述,此处不再赘述
通用布局模版组件,基于Antd的Layout,实现配置化。用法详见sgm-lmsweb-react-demo的例子
通用获取数据模版组件,实现了通过配置即可以通过动态模型获取数据。用法详见sgm-lmsweb-react-demo的例子