Closed sorrycc closed 8 years ago
@afc163 @yiminghe @benjycui 在此之前需要先准备一篇 《实际项目开发》吗? https://github.com/ant-design/antd-init/issues/82
项目开发实践要基于围绕 antd 吗?
《项目开发实践》纲要:
@afc163 看下是否可行?
可以,术语 API 什么的尽量保持最简单的就好,详细的链到 dva 的文档中去。
嗯,要说明在 dva 中如何使用 antd 。
👍 antd-init 除了 demo 之外的都删掉吧,保持简单
可以帮忙在 demo 中把 dora 升级至 0.4 ,dora-plugin-webpack 升级至 0.8 吗?
@zenany ok,2.0 里一起处理掉。
@sorrycc 你好,想问一下,现在到底用antd-init 还是 dva-cli创建项目,文档大概什么时候会上线呢?谢谢
@275287902 用 dva-cli,文档这个星期。
@sorrycc 好的,谢谢
antd-init 命令执行后的推荐文案:
antd-init@2 仅适用于 demo,如果你要开发项目,推荐使用 dva-cli 进行项目初始化。dva 是一个基于 react 和 redux 的轻量应用框架,概念来自 elm,支持 side effects、热替换、动态加载等,已在生产环境广泛应用。
antd-init@2 is for demo only. If you want to create projects, it's better to init with dva-cli. dva is a redux and react based application framework. elm concept, support side effects, hmr, dynamic load and so on.
Usage:
npm install dva-cli -g
dva-cli new myapp
cd myapp
npm start
Visit https://github.com/dvajs/dva to learn more.
项目开发实战:
dva 是一个基于 react 和 redux 的轻量应用框架,概念来自 elm,支持 side effects、热替换、动态加载、react-native、SSR 等,已在生产环境广泛应用。
本文会引导你使用 dva 和 antd 从 0 开始创建一个简单应用。
会包含以下内容:
通过 npm 安装 dva 。
$ npm install dva-cli -g
安装完 dva-cli 之后,就可以在 terminal 里访问到 dva
命令。现在,你可以通过 dva new
创建新应用。
$ dva new dva-quickstart
这会创建 dva-quickstart
目录,包含项目初始化目录和文件,并提供开发服务器、构建脚本、数据 mock 服务、代理服务器等功能。
然后我们 cd
进入 dva-quickstart
目录,并启动开发服务器:
$ cd dva-quickstart
$ npm start
几秒钟后,你会看到以下输出:
proxy: load rule from proxy.config.js
proxy: listened on 8989
📦 411/411 build modules
webpack: bundle build is now finished.
在浏览器里打开 http://localhost:8989 ,你会看到 dva 的欢迎界面。
通过 npm 安装 antd
和 babel-plugin-antd
。babel-plugin-antd
是用来自动引入 antd 的脚本和样式的,详见 repo 。
$ npm install antd babel-plugin-antd --save
编辑 webpack.config.js
,使 babel-plugin-antd
插件生效。
+ webpackConfig.babel.plugins.push(['antd', {
+ style: 'css'
+ }]);
注:这里不需要手动重启开发服务器,保存
webpack.config.js
后会自动重启。
我们要写个应用来先显示产品列表。首先第一步是创建路由,路由可以想象成是组成应用的不同页面。
新建 route component routes/Products.js
,内容如下:
import React from 'react';
const Products = (props) => {
return (
<h2>List of Products</h2>
);
};
exports default Products;
添加路由信息到路由表,编辑 router.js
:
+ import Products from './routes/Products';
...
+ <Route path="/products" component={Products} />
然后在浏览器里打开 http://localhost:8989/#/products ,你应该能看到前面定义的 <h2>
标签。
随着应用的发展,你会需要在多个页面分享 UI 元素 (或在一个页面使用多次),在 dva 里你可以把这部分抽成 component 。
我们来编写一个 ProductList
component,这样就能在不同的地方显示产品列表了。
新建 components/ProductList.js
文件:
import React, { PropTypes } from 'react';
import { Table, Popconfirm, Button } from 'antd';
const ProductList = ({ onDelete, products }) => {
const columns = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Actions',
render(text, record) {
return (
<Popconfirm title="Delete?" onConfirm={onDelete.bind(this, record.id)}>
<Button>删除</Button>
</Popconfirm>
);
},
},
];
return (
<Table
dataSource={products}
columns={columns}
/>
);
};
ProductList.proptypes = {
onDelete: PropTypes.func.isRequired,
products: PropTypes.array.isRequired,
};
export default ProductList;
完成 UI 后,现在开始处理数据和逻辑。
dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。
新建 model models/products.js
:
import dva from 'dva';
export default {
namespace: 'products',
state: [],
reducers: {
'delete'(state, { payload: id }) {
return state.filter(item => item.id !== id);
},
},
};
这个 model 里:
namespace
表示在全局 state 上的 keystate
是初始值,在这里是空数组reducers
等同于 redux 里的 reducer,接收 action,同步更新 state然后别忘记在 index.js
里载入他:
// 3. Model
+ app.model(require('./models/products'));
到这里,我们已经单独完成了 model 和 component,那么他们如何串联起来呢?
dva 提供了 connect 方法。如果你熟悉 redux,这个 connect 就是 react-redux 的 connect 。
编辑 routes/Products.js
,替换为以下内容:
import React from 'react';
import { connect } from 'dva';
import ProductList from '../components/ProductList';
const Products = (props) => {
function handleDelete(id) {
props.dispatch({
type: 'products/delete',
payload: id,
});
}
return (
<div>
<h2>List of Products</h2>
<ProductList onDelete={handleDelete} products={props.products} />
</div>
);
};
// export default Products;
export default connect(({ products }) => ({
products
}))(Products);
最后,我们还需要一些初始数据让这个应用 run 起来。编辑 index.js
:
- const app = dva();
+ const app = dva({
+ initialState: {
+ products: [
+ { name: 'dva', id: 1 },
+ { name: 'antd', id: 2 },
+ ],
+ },
+ });
刷新浏览器,应该能看到以下效果:
完成开发并且在开发环境验证之后,就需要部署给我们的用户了。先执行下面的命令:
$ npm run build
几秒后,输出应该如下:
Child
Time: 14008ms
Asset Size Chunks Chunk Names
index.html 255 bytes [emitted]
common.js 1.18 kB 0 [emitted] common
index.js 504 kB 1, 0 [emitted] index
index.css 127 kB 1, 0 [emitted] index
build
命令会打包所有的资源,包含 JavaScript, CSS, web fonts, images, html 等。然后你可以在 dist/
目录下找到这些文件。
我们已经完成了一个简单应用,你可能还有很多疑问,比如:
你可以:
@afc163 项目开发实践放哪里? 以及前面上手文档的改动,需要我发 pr 吗?
发 PR 到 ant design master 分支吧。双语哦。
如何统一处理出错,以及特定操作的出错 @sorrycc 这个我没有在User Dashboard项目里看到怎么处理的,建议在utils/request.js 这里面处理么?谢谢你。
@275287902 全局出错处理举例:
import { message } from 'dva';
const app = dva({
onError(error) {
message.destroy();
message.error(error);
},
});
@sorrycc 好的 非常感谢!
antd太高产了,大赞!!!
刚看了 @sorrycc 的dva-cli,文档全部看完了,我还好奇dva-cli
和antd-init 的 redux 脚手架
之间是什么关系呢,就看到这个Issues了。
谢谢antd团队的大神们提供了这么高质量的UI库,让很多创业的小团队和个人也能做出很nice的中台界面。
demo boilerplate 中是否可以使用 css 而非 less?如同 create-react-app 中的项目模板一样 https://github.com/facebookincubator/create-react-app/tree/master/template/src 。less + css module 对初学前端这还是有一定成本的。
文案调整建议:
antd-init@2 仅适用于 demo,如果你要开发项目
-> antd-init@2 仅适用于学习和体验 antd,如果你要开发正式项目
@zenany 认同,demo 保持最简单吧。其他人有不同想法吗? 没有的话我就按这个改了。
antd-init@2.0.0-beta2
(英文版)
Project Development Practice:
dva is a React and redux based, lightweight and elm-style framework, which supports side effects, hot module replacement, dynamic on demand, react-native, SSR. And it has been widely used in production environment.
This article will guide you to create a simple application from zero using dva and antd.
Include the following:
Install dva with npm.
$ npm install dva-cli -g
After installed dva-cli, you can have access to the dva
command in terminal. Now, create a new application with dva new
.
$ dva new dva-quickstart
This creates dva-quickstart
directory, that contains the project directories and files, and provides development server, build script, mock service, proxy server and so on.
Then cd
the dva-quickstart
directory, and start the development server.
$ cd dva-quickstart
$ npm start
After a few seconds, you will see thw following output:
proxy: load rule from proxy.config.js
proxy: listened on 8989
📦 411/411 build modules
webpack: bundle build is now finished.
Open http://localhost:8989 in your browser, you will see dva welcome page.
Install antd
and babel-plugin-antd
with npm. babel-plugin-antd
is used to automatically import scripts and stylesheets from antd. See repo 。
$ npm install antd babel-plugin-antd --save
Edit webpack.config.js
to integrate babel-plugin-antd
.
+ webpackConfig.babel.plugins.push(['antd', {
+ style: 'css'
+ }]);
Notice: No need to manually restart the server, it will restart automatically after you save the
webpack.config.js
.
We need to write an application displaying the list of products. The first step is to create a route.
Create a route component routes/Products.js
:
import React from 'react';
const Products = (props) => {
return (
<h2>List of Products</h2>
);
};
exports default Products;
Add routing infomation to router, edit router.js
:
+ import Products from './routes/Products';
...
+ <Route path="/products" component={Products} />
Then open http://localhost:8989/#/products in your browser, you should be able to see the <h2>
tag defined before.
As your application grows and you notice you are sharing UI elements between multiple pages (or using them multiple times on the same page), in dva it's called reusable components.
Let's create a ProductList
component that we can use in multiple places to show a list of products.
Create components/ProductList.js
and typing:
import React, { PropTypes } from 'react';
import { Table, Popconfirm, Button } from 'antd';
const ProductList = ({ onDelete, products }) => {
const columns = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Actions',
render(text, record) {
return (
<Popconfirm title="Delete?" onConfirm={onDelete.bind(this, record.id)}>
<Button>删除</Button>
</Popconfirm>
);
},
},
];
return (
<Table
dataSource={products}
columns={columns}
/>
);
};
ProductList.proptypes = {
onDelete: PropTypes.func.isRequired,
products: PropTypes.array.isRequired,
};
export default ProductList;
After complete the UI, we will begin processing the data and logic.
dva manages domain model with model
, with reducers for synchronous state update, effects for async logic, and subscriptions for data source subscribe.
Let's create a model models/products.js
and typing:
import dva from 'dva';
export default {
namespace: 'products',
state: [],
reducers: {
'delete'(state, { payload: id }) {
return state.filter(item => item.id !== id);
},
},
};
In this model:
namespace
represent the key on global statestate
is the initial value, here is an empty arrayreducers
is equal to reducer in redux, accepting action, and update state synchronouslyThen don't forget to require it in index.js
:
// 3. Model
+ app.model(require('./models/products'));
So far, wee have completed a seperate model and component. Then how to connect these together?
dva provides a connect
method. If you are familar with redux, this connect
is from react-router.
Edit routes/Products.js
and replace with following:
import React from 'react';
import { connect } from 'dva';
import ProductList from '../components/ProductList';
const Products = (props) => {
function handleDelete(id) {
props.dispatch({
type: 'products/delete',
payload: id,
});
}
return (
<div>
<h2>List of Products</h2>
<ProductList onDelete={handleDelete} products={props.products} />
</div>
);
};
// export default Products;
export default connect(({ products }) => ({
products
}))(Products);
Finally, we need some initial data to make the application run together. Edit index.js
:
- const app = dva();
+ const app = dva({
+ initialState: {
+ products: [
+ { name: 'dva', id: 1 },
+ { name: 'antd', id: 2 },
+ ],
+ },
+ });
Refresh your browser, you should see the following result:
Now that we've written our application and verified that it works in development, it's time to get it ready to deploy to our users. To do so, run the following command:
$ npm run build
After a few seconds, the output should be as follows:
Child
Time: 14008ms
Asset Size Chunks Chunk Names
index.html 255 bytes [emitted]
common.js 1.18 kB 0 [emitted] common
index.js 504 kB 1, 0 [emitted] index
index.css 127 kB 1, 0 [emitted] index
The build
command packages up all of the assets that make up your application —— JavaScript, templates, CSS, web fonts, images, and more. Then you can find these files in the dist /
directory.
We have completed a simple application, but you may still have lots of questions, such as:
You can:
exports default Products;
=> export default Products;
@sorrycc
exports default Products;
export 写错
export default Products;
@raisezhang @wheatma 感谢提醒,在 https://github.com/ant-design/ant-design/blob/master/docs/react/getting-started.zh-CN.md 已更新。
antd-init --demo
)