框架下载:
首先设置npm镜像
npm set registry http://npm.1024.team
在此镜像下注册一个账号
npm adduser --registry http://npm.1024.team
全局安装脚手架程序
$ npm install -g best-cli
下载react四合一框架的话,找到合适的位置
$ tc init
回车后输入react_4in1
,再回车输入项目名称
这样四合一框架就下载下来了
如果没有自动下载依赖npm install
安装依赖,再进入node_modules/atool-build/
再npm install
,
如果sass报错了,先npm install cnpm -g
然后cnpm install node-sass
框架文件夹下有readme.md
文件,可以阅读一下,了解所涉及技术栈,命名规范及运行方法
项目结构
先理清楚文件间的引用关系
src下的index.html引用了index.js,
index.js又引用了router和models
router接收到路由并渲染routes文件夹下的子页面
子页面引用了子组件和models,并将它们渲染出来
开始编写
1、绘制页面###
以游币商城的兑换页为例
先是注册一个路由
import exchangePage from './routes/exchangePage';
export default function({ history }) {
return (
<Router history={history}>
<Route path="/" component={IndexPage} />
<Route path="/exchange" component={exchangePage} />
</Router>
);
};
在routes文件夹下新建一个子页面
import React, { Component, PropTypes } from 'react';
import { connect } from 'dva';
import { Link } from 'dva/router';
import styles from './exchangePage.css';
function exchangePage() {
return (
<div>
exchangePage
</div>
);
}
exchangePage.propTypes = {
};
export default connect()(exchangePage);
分析页面,大概可以分为三个组件
import React, { Component, PropTypes } from 'react';
import { connect } from 'dva';
import { Link } from 'dva/router';
import styles from './exchangePage.css';
import Address from '../components/exchange/address';
import Exchange from '../components/exchange/exchange';
import Pay from '../components/exchange/pay';
function exchangePage() {
return (
<div>
<Address/>
<Exchange/>
<Pay/>
</div>
);
}
exchangePage.propTypes = {
};
export default connect()(exchangePage);
给组件暂时先写点东西
import React, { Component, PropTypes } from 'react';
const Address = () => {
return (
<div>
This is address
</div>
);
}
export default Address;
给组件写入简单的html和样式
import React, { Component, PropTypes } from 'react';
import styles from './address.css';
const Address = () => {
return (
<section className={styles.top} onClick="">
<div className={styles.change_address}>
<h2>测试 15150110408</h2><p>江苏苏州工业园区同程大厦</p>
</div>
</section>
);
}
export default Address;
同理,把Exchange
组件和Address
组件的内容丰富一下
2、绑定models###
models中主要还是分为路由事件、异步数据和同步数据,先来一个较为简单的同步数据
export default{
namespace:'exchange',
state:{
},
subscriptions: {
},
effects:{
},
reducers:{
getAddress(state){
const mock={
reciverName:'测试',
reciverMobileNumber:'15150000000',
reciverProvinceName:'江苏',
reciverCityName:'苏州',
reciverDistrictName:'工业园区',
reciverStreetAddress:'同程大厦',
};
return {...state,...mock}
}
}
}
import React, { Component, PropTypes } from 'react';
import styles from './address.css';
const Address = ({
reciverName,
reciverMobileNumber,
reciverProvinceName,
reciverCityName,
reciverDistrictName,
reciverStreetAddress,
changeAddress
}) => {
return (
<section className={styles.levatop}>
<div className={styles.top} onClick={changeAddress}>
![](src/assets/icon_indicator_mall_detail_arrive_rest.png)
![](src/assets/arrow_list_common_right.png)
<div className={styles.change_address}>
<h2>{reciverName} {reciverMobileNumber}</h2><p>{reciverProvinceName+reciverCityName+reciverDistrictName+reciverStreetAddress}</p>
</div>
</div>
</section>
);
}
export default Address;
触发reducer中的getAddress(action)就可以渲染数据到页面了,可以写在声明周期里,也可以写在路由事件里。我们这里写在路由事件里了
export default{
namespace:'exchange',
state:{
},
subscriptions: {
setup({ dispatch, history }) {
history.listen(location => {
if (location.pathname === '/exchange') {
dispatch({
type: 'getAddress',
payload: {}
});
}
});
},
},
effects:{
},
同步数据看完了,来看一个异步处理数据
咱们平时解决异步的方法一般都是用callback,可是dva要求我们使用generator函数
由于调bridge是采用callback的,我们要先处理成promise类的
function addressBridge(){
return new Promise(resolve=>{
_tc_bridge_user.get_mailing_address({
param:{},
callback: resolve
})
})
}
在effect中写入generator函数
},
},
effects:{
*changeAddress({ payload }, { select, call, put }){
const addressInfo=JSON.parse((yield call(addressBridge)).CBData).addressInfo;
console.log(addressInfo)
if(addressInfo){
yield put({
type:'changeAddressSuccess',
payload: {
...addressInfo
}
})
}
}
},
reducers:{
changeAddressSuccess(state,action){
return {...state, ...action.payload};
},
其中call为调用一个方法返回一个promise
put为触发一个action,这个action携带一个payload可以传递给reducers中的方法
reducers内返回了一个新的state触发了自动更新视图
调用方法:
更新视图的方法有了,想要用事件触发的话,
如果在主视图调用的话,直接dispatch({type: 'exchange/changeAddress'})
就可以了
如果子组件想要调用的话,一般是把方法传递给子组件
function exchangePage({ location, dispatch, exchange }) {
const addressProp={
...exchange,
changeAddress:()=>{dispatch({type: 'exchange/changeAddress'})}
}
return (
<div>
<Address {...addressProp}/>
然后子组件调用父组件内的方法
const Address = ({
reciverName,
reciverMobileNumber,
reciverProvinceName,
reciverCityName,
reciverDistrictName,
reciverStreetAddress,
changeAddress
}) => {
return (
<section className={styles.levatop}>
<div className={styles.top} onClick={changeAddress}>
![](src/assets/icon_indicator_mall_detail_arrive_rest.png)
![](src/assets/arrow_list_common_right.png)
<div className={styles.change_address}>
<h2>{reciverName} {reciverMobileNumber}</h2><p>{reciverProvinceName+reciverCityName+reciverDistrictName+reciverStreetAddress}</p>
</div>
</div>
</section>
);
}