返回介绍

三、计数器例子

发布于 2024-09-07 12:09:16 字数 7129 浏览 0 评论 0 收藏 0

$ 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 名字改为 countstate 对象加上 recordcurrent 属性。如下

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.jseffect
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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文