文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
三、计数器例子
$ dva new myapp
目录结构介绍
.
├── mock // mock 数据文件夹
├── node_modules // 第三方的依赖
├── public // 存放公共 public 文件的文件夹
├── src // 最重要的文件夹,编写代码都在这个文件夹下
│ ├── assets // 可以放图片等公共资源
│ ├── components // 就是 react 中的木偶组件
│ ├── models // dva 最重要的文件夹,所有的数据交互及逻辑都写在这里
│ ├── routes // 就是 react 中的智能组件,不要被文件夹名字误导。
│ ├── services // 放请求借口方法的文件夹
│ ├── utils // 自己的工具方法可以放在这边
│ ├── index.css // 入口文件样式
│ ├── index.ejs // ejs 模板引擎
│ ├── index.js // 入口文件
│ └── router.js // 项目的路由文件
├── .eslintrc // bower 安装目录的配置
├── .editorconfig // 保证代码在不同编辑器可视化的工具
├── .gitignore // git 上传时忽略的文件
├── .roadhogrc.js // 项目的配置文件,配置接口转发,css_module 等都在这边。
├── .roadhogrc.mock.js // 项目的配置文件
└── package.json // 当前整一个项目的依赖
首先是前端的页面,我们使用 class 形式来创建组件,原例子中是使用无状态来创建的。react 创建组件的各种方式,大家可以看 React 创建组件的三种方式及其区别
我们先修改 route/IndexPage.js
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.css';
class IndexPage extends React.Component {
render() {
const { dispatch } = this.props;
return (
<div className={styles.normal}>
<div className={styles.record}>Highest Record: 1</div>
<div className={styles.current}>2</div>
<div className={styles.button}>
<button onClick={() => {}}>+</button>
</div>
</div>
);
}
}
export default connect()(IndexPage);
同时修改样式 routes/IndexPage.css
.normal {
width: 200px;
margin: 100px auto;
padding: 20px;
border: 1px solid #ccc;
box-shadow: 0 0 20px #ccc;
}
.record {
border-bottom: 1px solid #ccc;
padding-bottom: 8px;
color: #ccc;
}
.current {
text-align: center;
font-size: 40px;
padding: 40px 0;
}
.button {
text-align: center;
button {
width: 100px;
height: 40px;
background: #aaa;
color: #fff;
}
}
在 model
处理 state
,在页面里面输出 model
中的 state
- 首先我们在 index.js 中将
models/example.js
,即将 model 下一行的的注释打开
import dva from 'dva';
import './index.css';
// 1. Initialize
const app = dva();
// 2. Plugins
// app.use({});
// 3. Model
app.model(require('./models/example')); // 打开注释
// 4. Router
app.router(require('./router'));
// 5. Start
app.start('#root');
接下来我们进入 models/example.js
,将 namespace
名字改为 count
, state
对象加上 record
与 current
属性。如下
export default {
namespace: 'count',
state: {
record: 0,
current: 0,
},
...
};
接着我们来到 routes/indexpage.js
页面,通过的 mapStateToProps
引入相关的 state
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.css';
class IndexPage extends React.Component {
render() {
const { dispatch, count } = this.props;
return (
<div className={styles.normal}>
<div className={styles.record}>
Highest Record: {count.record} // 将 count 的 record 输出
</div>
<div className={styles.current}>
{count.current}
</div>
<div className={styles.button}>
<button onClick={() => {} } >
+
</button>
</div>
</div>
);
}
}
function mapStateToProps(state) {
return { count: state.count };
} // 获取 state
export default connect(mapStateToProps)(IndexPage);
通过 +
发送 action
,通过 reducer
改变相应的 state
- 首先我们在
models/example.js
,写相应的reducer
export default {
...
reducers: {
add1(state) {
const newCurrent = state.current + 1;
return { ...state,
record: newCurrent > state.record ? newCurrent : state.record,
current: newCurrent,
};
},
minus(state) {
return { ...state, current: state.current - 1 };
},
},
};
在页面的模板 routes/IndexPage.js
中 +
号点击的时候, dispatch
一个 action
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.css';
class IndexPage extends React.Component {
render() {
const { dispatch, count } = this.props;
return (
<div className={styles.normal}>
<div className={styles.record}>Highest Record: {count.record}</div>
<div className={styles.current}>{count.current}</div>
<div className={styles.button}>
<button
+ onClick={() => { dispatch({ type: 'count/add1' });}
}>+</button>
</div>
</div>
);
}
}
function mapStateToProps(state) {
return { count: state.count };
}
export default connect(mapStateToProps)(IndexPage);
接下来我们来使用 effect
模拟一个数据接口请求,返回之后,通过 yield put()
改变相应的 state
- 首先我们替换相应的
models/example.js
的effect
effects: {
*add(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'minus' });
},
},
这里的 delay
,是我这边写的一个延时的函数,我们在 utils
里面编写一个 utils.js
,一般请求接口的函数都会写在 servers
文件夹中
export function delay(timeout) {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
}
订阅订阅键盘事件,使用 subscriptions
,当用户按住 command+up
时候触发添加数字的 action
- 在
models/example.js
中作如下修改
+import key from 'keymaster';
...
app.model({
namespace: 'count',
+ subscriptions: {
+ keyboardWatcher({ dispatch }) {
+ key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });
+ },
+ },
});
- 在这里你需要安装
keymaster
这个依赖
npm install keymaster --save
- 现在你可以按住
command+up
就可以使current
加 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论