From e6c406a4b7da68f5e7c3dfa717f18d12e989a7c5 Mon Sep 17 00:00:00 2001 From: sorrycc Date: Sun, 18 Sep 2016 17:39:11 +0800 Subject: [PATCH 1/2] docs: add Practical Projects --- docs/react/practical-projects.en-US.md | 271 +++++++++++++++++++++++++ docs/react/practical-projects.zh-CN.md | 271 +++++++++++++++++++++++++ 2 files changed, 542 insertions(+) create mode 100644 docs/react/practical-projects.en-US.md create mode 100644 docs/react/practical-projects.zh-CN.md diff --git a/docs/react/practical-projects.en-US.md b/docs/react/practical-projects.en-US.md new file mode 100644 index 0000000000..fa2f55d000 --- /dev/null +++ b/docs/react/practical-projects.en-US.md @@ -0,0 +1,271 @@ +--- +order: 3 +title: Practical Projects +--- + +[dva](https://github.com/dvajs/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 + +Install dva with npm. + +```bash +$ npm install dva-cli -g +``` + +## Create New App + +After installed dva-cli, you can have access to the `dva` command in terminal. Now, create a new application with `dva new`. + +```bash +$ 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. + +```bash +$ cd dva-quickstart +$ npm start +``` + +After a few seconds, you will see thw following output: + +```bash + 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. + +## Integrate antd + +Install `antd` and `babel-plugin-antd` with npm. `babel-plugin-antd` is used to automatically import scripts and stylesheets from antd. See [repo](https://github.com/ant-design/babel-plugin-antd) 。 + +```bash +$ npm install antd babel-plugin-antd --save +``` + +Edit `webpack.config.js` to integrate `babel-plugin-antd`. + +```diff ++ 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`. + +## Define Router + +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`: + +```javascript +import React from 'react'; + +const Products = (props) => { + return ( +

List of Products

+ ); +}; + +exports default Products; +``` + +Add routing infomation to router, edit `router.js`: + +```diff ++ import Products from './routes/Products'; +... ++ +``` + +Then open http://localhost:8989/#/products in your browser, you should be able to see the `

` tag defined before. + +## Write UI Components + +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: + +```javascript +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 ( + + + + ); + }, + }, + ]; + return ( + + ); +}; + +ProductList.proptypes = { + onDelete: PropTypes.func.isRequired, + products: PropTypes.array.isRequired, +}; + +export default ProductList; +``` + +## Define Model + +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: + +```javascript +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 state +- `state` is the initial value, here is an empty array +- `reducers` is equal to reducer in redux, accepting action, and update state synchronously + +Then don't forget to require it in `index.js`: + +```diff +// 3. Model ++ app.model(require('./models/products')); +``` + +## Connect + +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: + +```javascript +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 ( +
+

List of Products

+ +
+ ); +}; + +// export default Products; +export default connect(({ products }) => ({ + products +}))(Products); +``` + +Finally, we need some initial data to make the application run together. Edit `index.js`: + +```diff +- 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: + +

+ +

+ +## Build + +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: + +```bash +$ npm run build +``` + +After a few seconds, the output should be as follows: + +```bash +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. + +## What's Next + +We have completed a simple application, but you may still have lots of questions, such as: + +- How to dealing with async logic +- How to load initial data elegantly +- How to handle onError globally and locally +- How to load Routes and Models on demand +- How to implement HMR +- How to mock data +- and so on... + +You can: + +- Visit [dva offical website](https://github.com/dvajs/dva) +- View all the [API](https://github.com/dvajs/dva#api) +- View [toturial](https://github.com/dvajs/dva-docs/blob/master/v1/zh-cn/tutorial/01-%E6%A6%82%E8%A6%81.md), complete a medium application step by step +- View examples, such as [dva version of hackernews](https://github.com/dvajs/dva-hackernews) diff --git a/docs/react/practical-projects.zh-CN.md b/docs/react/practical-projects.zh-CN.md new file mode 100644 index 0000000000..42ba77055c --- /dev/null +++ b/docs/react/practical-projects.zh-CN.md @@ -0,0 +1,271 @@ +--- +order: 3 +title: 项目实战 +--- + +[dva](https://github.com/dvajs/dva) 是一个基于 react 和 redux 的轻量应用框架,概念来自 elm,支持 side effects、热替换、动态加载、react-native、SSR 等,已在生产环境广泛应用。 + +本文会引导你使用 dva 和 antd 从 0 开始创建一个简单应用。 + +会包含以下内容: + +--- + +## 安装 dva + +通过 npm 安装 dva 。 + +```bash +$ npm install dva-cli -g +``` + +## 创建新应用 + +安装完 dva-cli 之后,就可以在 terminal 里访问到 `dva` 命令。现在,你可以通过 `dva new` 创建新应用。 + +```bash +$ dva new dva-quickstart +``` + +这会创建 `dva-quickstart` 目录,包含项目初始化目录和文件,并提供开发服务器、构建脚本、数据 mock 服务、代理服务器等功能。 + +然后我们 `cd` 进入 `dva-quickstart` 目录,并启动开发服务器: + +```bash +$ cd dva-quickstart +$ npm start +``` + +几秒钟后,你会看到以下输出: + +```bash + 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 的欢迎界面。 + +## 使用 antd + +通过 npm 安装 `antd` 和 `babel-plugin-antd` 。`babel-plugin-antd` 是用来自动引入 antd 的脚本和样式的,详见 [repo](https://github.com/ant-design/babel-plugin-antd) 。 + +```bash +$ npm install antd babel-plugin-antd --save +``` + +编辑 `webpack.config.js`,使 `babel-plugin-antd` 插件生效。 + +```diff ++ webpackConfig.babel.plugins.push(['antd', { ++ style: 'css' ++ }]); +``` + +> 注:这里不需要手动重启开发服务器,保存 `webpack.config.js` 后会自动重启。 + +## 定义路由 + +我们要写个应用来先显示产品列表。首先第一步是创建路由,路由可以想象成是组成应用的不同页面。 + +新建 route component `routes/Products.js`,内容如下: + +```javascript +import React from 'react'; + +const Products = (props) => { + return ( +

List of Products

+ ); +}; + +exports default Products; +``` + +添加路由信息到路由表,编辑 `router.js` : + +```diff ++ import Products from './routes/Products'; +... ++ +``` + +然后在浏览器里打开 http://localhost:8989/#/products ,你应该能看到前面定义的 `

` 标签。 + +## 编写 UI Component + +随着应用的发展,你会需要在多个页面分享 UI 元素 (或在一个页面使用多次),在 dva 里你可以把这部分抽成 component 。 + +我们来编写一个 `ProductList` component,这样就能在不同的地方显示产品列表了。 + +新建 `components/ProductList.js` 文件: + +```javascript +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 ( + + + + ); + }, + }, + ]; + return ( +

+ ); +}; + +ProductList.proptypes = { + onDelete: PropTypes.func.isRequired, + products: PropTypes.array.isRequired, +}; + +export default ProductList; +``` + +## 定义 Model + +完成 UI 后,现在开始处理数据和逻辑。 + +dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。 + +新建 model `models/products.js` : + +```javascript +import dva from 'dva'; + +export default { + namespace: 'products', + state: [], + reducers: { + 'delete'(state, { payload: id }) { + return state.filter(item => item.id !== id); + }, + }, +}; +``` + +这个 model 里: + +- `namespace` 表示在全局 state 上的 key +- `state` 是初始值,在这里是空数组 +- `reducers` 等同于 redux 里的 reducer,接收 action,同步更新 state + +然后别忘记在 `index.js` 里载入他: + +```diff +// 3. Model ++ app.model(require('./models/products')); +``` + +## connect 起来 + +到这里,我们已经单独完成了 model 和 component,那么他们如何串联起来呢? + +dva 提供了 connect 方法。如果你熟悉 redux,这个 connect 就是 react-redux 的 connect 。 + +编辑 `routes/Products.js`,替换为以下内容: + +```javascript +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 ( +
+

List of Products

+ +
+ ); +}; + +// export default Products; +export default connect(({ products }) => ({ + products +}))(Products); +``` + +最后,我们还需要一些初始数据让这个应用 run 起来。编辑 `index.js`: + +```diff +- const app = dva(); ++ const app = dva({ ++ initialState: { ++ products: [ ++ { name: 'dva', id: 1 }, ++ { name: 'antd', id: 2 }, ++ ], ++ }, ++ }); +``` + +刷新浏览器,应该能看到以下效果: + +

+ +

+ +## 构建应用 + +完成开发并且在开发环境验证之后,就需要部署给我们的用户了。先执行下面的命令: + +```bash +$ npm run build +``` + +几秒后,输出应该如下: + +```bash +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/` 目录下找到这些文件。 + +## 下一步 + +我们已经完成了一个简单应用,你可能还有很多疑问,比如: + +- 如何处理异步请求 +- 如何优雅地加载初始数据 +- 如何统一处理出错,以及特定操作的出错 +- 如何动态加载路由和 Model,以加速页面载入速度 +- 如何实现 hmr +- 如何 mock 数据 +- 等等 + +你可以: + +- 访问 [dva 官网](https://github.com/dvajs/dva) +- 查看所有 [API](https://github.com/dvajs/dva#api) +- [教程](https://github.com/dvajs/dva-docs/blob/master/v1/zh-cn/tutorial/01-%E6%A6%82%E8%A6%81.md),一步步完成一个中型应用 +- 看看 [dva 版 hackernews](https://github.com/dvajs/dva-hackernews) 是[如何实现](https://github.com/sorrycc/blog/issues/9)的 From 681576d2c46a1615226975141d10f7ca52f3aede Mon Sep 17 00:00:00 2001 From: sorrycc Date: Sun, 18 Sep 2016 17:47:58 +0800 Subject: [PATCH 2/2] docs: upgrade Getting Started with antd-init@2 --- docs/react/getting-started.en-US.md | 6 +++--- docs/react/getting-started.zh-CN.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/react/getting-started.en-US.md b/docs/react/getting-started.en-US.md index 8802d404d2..12e81c89a5 100644 --- a/docs/react/getting-started.en-US.md +++ b/docs/react/getting-started.en-US.md @@ -45,7 +45,7 @@ A new project can be created using CLI tools. ```bash $ mkdir antd-demo && cd antd-demo -$ antd-init --type plain-react +$ antd-init ``` `antd-init` will run `npm install` after a project is created. If it fails, you can run `npm install` by yourself. @@ -55,7 +55,7 @@ $ antd-init --type plain-react By default, besides the scaffolding needed to start the development, a fully working Todo application is created. You may study this example later. For now, just follow this guide in order to get some experience working with the result of `antd-init`. -Replace the content of `src/entries/index.js` with the following code. +Replace the content of `index.js` with the following code. As you can see, there is no difference between antd's components and usual React components. ```jsx @@ -91,7 +91,7 @@ ReactDOM.render(, document.getElementById('root')); ### 4. Development & Debugging -Run your project and visit http://127.0.0.1:8989 +Run your project and visit http://127.0.0.1:8000 ```bash $ npm start diff --git a/docs/react/getting-started.zh-CN.md b/docs/react/getting-started.zh-CN.md index 467b9def76..05a3542c3c 100644 --- a/docs/react/getting-started.zh-CN.md +++ b/docs/react/getting-started.zh-CN.md @@ -44,7 +44,7 @@ $ npm install antd-init -g ```bash $ mkdir antd-demo && cd antd-demo -$ antd-init --type plain-react +$ antd-init ``` antd-init 会自动安装 npm 依赖,若有问题则可自行安装。 @@ -55,7 +55,7 @@ antd-init 会自动安装 npm 依赖,若有问题则可自行安装。 脚手架会生成一个 Todo 应用实例(一个很有参考价值的 React 上手示例),先不管它,我们用来测试组件。 -直接用下面的代码替换 `src/entries/index.js` 的内容,用 React 的方式直接使用 antd 组件。 +直接用下面的代码替换 `index.js` 的内容,用 React 的方式直接使用 antd 组件。 ```jsx import React from 'react'; @@ -90,7 +90,7 @@ ReactDOM.render(, document.getElementById('root')); ### 4. 开发调试 -一键启动调试,访问 http://127.0.0.1:8989 查看效果。 +一键启动调试,访问 http://127.0.0.1:8000 查看效果。 ```bash $ npm start