一丶 安装
通过 npm 安装 dva-cli 并确保版本是0.8.1或以上。
$ npm install dva-cli -g $ dva -v0.8.1
二丶创建新应用
安装完dva-cli之后,就可以在命令行里访问到dva命令(不能访问?)。现在,你可以通过dva new创建新应用。
$ dva new dva-quickstart $ npm start
之后浏览器就会打开 http://localhost:8000,你会看到dva的欢迎界面。
三丶使用antd组件库
通过 npm 安装 antd 和 babel-plugin-import。babel-plugin-import 是用来按需加载 antd 的脚本和样式的
$ npm install antd babel-plugin-import --save
编辑.roadhogrc,使 babel-plugin-import 插件生效。
"extraBabelPlugins": [ - "transform-runtime"+ "transform-runtime", + ["import", { "libraryName": "antd", "style": "css" }] ],
注:dva-cli 基于 roadhog 实现 build 和 server,更多.roadhogrc的配置详见 roadhog#配置
四丶准备工作以及文件之间的对应关系
首先在创建文件之前(一般安装的时候系统会自动生成一个默认的services文件下 Example.js 和 model文件下 example.js,两者都是一一对应)
react项目的推荐目录结构(如果使用dva脚手架创建,则自动生成如下)
|── /mock/ # 数据mock的接口文件 |── /src/ # 项目源码目录(我们开发的主要工作区域) | |── /components/ # 项目组件(用于路由组件内引用的可复用组件) | |── /routes/ # 路由组件(页面维度) | | |── route1.js | | |── route2.js # 根据router.js中的映射,在不同的url下,挂载不同的路由组件| | └── route3.js | |── /models/ # 数据模型(可以理解为store,用于存储数据与方法) | | |── model1.js | | |── model2.js # 选择分离为多个model模型,是根据业务实体进行划分| | └── model3.js | |── /services/ # 数据接口(处理前台页面的ajax请求,转发到后台) | |── /utils/ # 工具函数(工具库,存储通用函数与配置参数) | |── router.js # 路由配置(定义路由与对应的路由组件) | |── index.js # 入口文件 | |── index.less | └── index.html |── package.json # 项目信息 └── proxy.config.js # 数据mock配置
五丶创建接口文件New.js
在services文件下创建New.js, .yield call方法里面的usersService.fetch方法如下(PAGESIZE目前是常量) New.js代码如下:
import request from '../utils/request'; // data: [{Id, Text, CreateTime, UpdateTime, IsActive }]export function queryScaleMenu(start, limit) { let body = { start, limit } body = JSON.stringify(body); return request('http://192.168.10.45/GYHL.News/api/news/menu/query', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: body }); } export function queryScaleNews(start, limit, type) { let body = { start, limit, type } body = JSON.stringify(body); return request('http://192.168.10.45/GYHL.News/api/news/new/query', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: body }); }
然后在models中创建对应的New.js, 因为services下的New.js 和models下的New.js 两者是react 调入接口和接收接口参数 密不可分的文件。
import * as services from './../services/News';export default { namespace: 'News', state: { detail:[], data: [], }, subscriptions: { steup({dispatch, history}) { return history.listen((location) => { // console.log(location); let start = 0; let limit = 1000; let type = "7ad2c8db-ff04-4736-81c9-1b7c6fb276b3"; dispatch({type: "fetchMenu",payload:{start,limit}}); dispatch({type: "fetchNews",payload:{start,limit,type}}); }) } }, effects: { * fetchMenu({ payload: { start, limit, ...rest } },{ call, put }){ var nextMenu = yield call(services.queryScaleMenu, start, limit ); // console.log(nextMenu); var startNews = nextMenu.data.data; yield put({ type: "save", payload: { detail:startNews}}); }, * fetchNews({ payload: { start, limit, type, ...rest }}, { call, put }){ var nextNews = yield call(services.queryScaleNews, start, limit, type); // console.log(nextNews); var lastNews = nextNews.data.data; yield put({ type: "save", payload: { data:lastNews }}); } }, reducers: { save(state, action){ return { ...state, ...action.payload} } }, };
六丶把components文件下Example.js组件修改一下
import React from 'react';import styles from './style.css';import { connect } from 'dva';function Example({ dispatch, data}) { // console.log(data); let detail = []; if (data.length != 0) { detail = data; } return ( <div> <div> { detail.length != 0? detail.map(item =>( <div className={styles.code}> <div className={styles.one}> <img src={item.Img} alt="" /> </div> <p>{item.Memo}</p> <p className={styles.pade}>{item.Title}</p> <p className={styles.sade}></p> </div> )):""} </div> </div> ); }; Example.propTypes = { }; export default connect(({News}) => ({...News}))(Example);
七丶在 routes文件下 IndexPage.js进行数据渲染
import React from 'react';import Example from '../components/Example';import { connect } from 'dva';import styles from './IndexPage.css';import Button from 'antd/lib/button';import 'antd/lib/button/style';import Carousel from 'antd/lib/carousel';import 'antd/lib/carousel/style';import Tabs from 'antd/lib/tabs';import 'antd/lib/tabs/style';const TabPane = Tabs.TabPane;function IndexPage({ dispatch, detail, data}) { let T1,T2,T3,T4, I1,I2,I3,I4 = ""; if (detail.length != 0) { T1 = detail[0].Text; T2 = detail[1].Text; T3 = detail[2].Text; T4 = detail[3].Text; I1 = detail[0].Id; I2 = detail[1].Id; I3 = detail[2].Id; I4 = detail[3].Id; };// 建议小伙伴不要这样去渲染,最好是把它写成循环的方式去写,因为我的方法是最笨订的方法(数据多了还是循环实用些) function callback(key){ // console.log("--------------s") // console.log(key); let type = key; let start = 0; let limit = 1000; dispatch({type: "News/fetchNews",payload:{start,limit,type}}); }; return ( <div className={styles.box}> <div className={styles.slickslide}> <Carousel autoplay className={styles.slickslide}> <div>222</div> <div>333</div> <div>444</div> <div>555</div> </Carousel> </div> <Tabs defaultActiveKey="1" size="small" onChange={callback}> <TabPane tab={T1} key={I1}> <Example ></Example> </TabPane> <TabPane tab={T2} key={I2}> <Example></Example> </TabPane> <TabPane tab={T3} key={I3}> <Example></Example> </TabPane> <TabPane tab={T4} key={I4}> <Example></Example> </TabPane> </Tabs> </div> ); }; IndexPage.propTypes = { };export default connect(({News}) => ({...News}))(IndexPage);
总结:
整体看看我的方法和数据渲染方式不是太好,毕竟是目前还在学习状态,所以react学习开发之路还很漫长,所以我觉得在这个前端发展迅速的年代中要不停地去汲取精华,去取糟粕。扩充自己前端主流框架的学习及运用。祝愿前端的小伙伴们在未来有个好的发展方向,
作者:sidney_c
链接:https://www.jianshu.com/p/55702d52593b