Skip to content
This repository has been archived by the owner on Nov 4, 2018. It is now read-only.

讨论:antd-init@2.0 #101

Closed
sorrycc opened this issue Aug 8, 2016 · 28 comments
Closed

讨论:antd-init@2.0 #101

sorrycc opened this issue Aug 8, 2016 · 28 comments

Comments

@sorrycc
Copy link
Contributor

sorrycc commented Aug 8, 2016

  1. 移除 plain-react, redux 的版本,默认生成现在的 demo 版本 (antd-init --demo)
  2. 添加提示,引导项目级应用使用 dva-cli
@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 8, 2016

@afc163 @yiminghe @benjycui
在此之前需要先准备一篇 《实际项目开发》吗? #82

@afc163
Copy link
Member

afc163 commented Aug 8, 2016

  • 改造现有的 上手文档antd-init --demo。在 自行构建 前加上项目开发的简单说明和下面的文档链接。
  • 准备 dva 上手文档:《项目开发实践》。

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 8, 2016

项目开发实践要基于围绕 antd 吗?

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 8, 2016

《项目开发实践》纲要:

  1. 安装 dva-cli
  2. 创建新应用
  3. 安装 antd 和 babel-plugin-antd
  4. 定义路由
  5. 写一个 Component
  6. 写一个 Model
  7. connect 起来

@afc163 看下是否可行?

@afc163
Copy link
Member

afc163 commented Aug 8, 2016

可以,术语 API 什么的尽量保持最简单的就好,详细的链到 dva 的文档中去。

@afc163
Copy link
Member

afc163 commented Aug 8, 2016

嗯,要说明在 dva 中如何使用 antd 。

@afc163
Copy link
Member

afc163 commented Aug 8, 2016

项目的 dva 例子代码可以略微复杂一些,可以包括基本的 antd 布局。类似全栈指引平台的例子。

@yiminghe
Copy link
Contributor

yiminghe commented Aug 8, 2016

👍 antd-init 除了 demo 之外的都删掉吧,保持简单

@zenany
Copy link

zenany commented Aug 19, 2016

可以帮忙在 demo 中把 dora 升级至 0.4 ,dora-plugin-webpack 升级至 0.8 吗?

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 19, 2016

@zenany ok,2.0 里一起处理掉。

@tianlizhao
Copy link

@sorrycc 你好,想问一下,现在到底用antd-init 还是 dva-cli创建项目,文档大概什么时候会上线呢?谢谢

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 22, 2016

@275287902 用 dva-cli,文档这个星期。

@tianlizhao
Copy link

@sorrycc 好的,谢谢

@sorrycc sorrycc mentioned this issue Aug 23, 2016
@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 25, 2016

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.

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 25, 2016

项目开发实战:


dva 是一个基于 react 和 redux 的轻量应用框架,概念来自 elm,支持 side effects、热替换、动态加载、react-native、SSR 等,已在生产环境广泛应用。

本文会引导你使用 dva 和 antd 从 0 开始创建一个简单应用。

会包含以下内容:

  • 安装 dva
  • 创建新应用
  • 使用 antd
  • 定义路由
  • 编写 UI Component
  • 定义 Model
  • connect 起来
  • 构建应用
  • 下一步

安装 dva

通过 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 的欢迎界面。

使用 antd

通过 npm 安装 antdbabel-plugin-antdbabel-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 Component

随着应用的发展,你会需要在多个页面分享 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;

定义 Model

完成 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 上的 key
  • state 是初始值,在这里是空数组
  • reducers 等同于 redux 里的 reducer,接收 action,同步更新 state

然后别忘记在 index.js 里载入他:

// 3. Model
+ app.model(require('./models/products'));

connect 起来

到这里,我们已经单独完成了 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/ 目录下找到这些文件。

下一步

我们已经完成了一个简单应用,你可能还有很多疑问,比如:

  • 如何处理异步请求
  • 如何优雅地加载初始数据
  • 如何统一处理出错,以及特定操作的出错
  • 如何动态加载路由和 Model,以加速页面载入速度
  • 如何实现 hmr
  • 如何 mock 数据
  • 等等

你可以:

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 25, 2016

@afc163 项目开发实践放哪里? 以及前面上手文档的改动,需要我发 pr 吗?

@afc163
Copy link
Member

afc163 commented Aug 25, 2016

发 PR 到 ant design master 分支吧。双语哦。

@tianlizhao
Copy link

tianlizhao commented Aug 25, 2016

如何统一处理出错,以及特定操作的出错
@sorrycc 这个我没有在User Dashboard项目里看到怎么处理的,建议在utils/request.js 这里面处理么?谢谢你。

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 25, 2016

@275287902 全局出错处理举例:

import { message } from 'dva';

const app = dva({
  onError(error) {
    message.destroy();
    message.error(error);
  },
});

@tianlizhao
Copy link

@sorrycc 好的 非常感谢!

@xyzget
Copy link

xyzget commented Aug 26, 2016

antd太高产了,大赞!!!
刚看了 @sorrycc 的dva-cli,文档全部看完了,我还好奇dva-cliantd-init 的 redux 脚手架之间是什么关系呢,就看到这个Issues了。
谢谢antd团队的大神们提供了这么高质量的UI库,让很多创业的小团队和个人也能做出很nice的中台界面。

@zenany
Copy link

zenany commented Aug 26, 2016

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,如果你要开发正式项目

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 26, 2016

@zenany 认同,demo 保持最简单吧。其他人有不同想法吗? 没有的话我就按这个改了。

@sorrycc
Copy link
Contributor Author

sorrycc commented Aug 27, 2016

antd-init@2.0.0-beta2

@sorrycc
Copy link
Contributor Author

sorrycc commented Sep 18, 2016

(英文版)

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
  • Create New App
  • Integrate antd
  • Define Router
  • Write UI Components
  • Define Model
  • Connect
  • Build
  • What's Next

Install dva

Install dva with npm.

$ 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.

$ 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.

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

$ 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.

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:

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.

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:

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;

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:

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:

// 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:

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:

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:

$ 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.

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:

@wheatma
Copy link

wheatma commented Sep 19, 2016

exports default Products; => export default Products;

@raisezhang
Copy link

@sorrycc

exports default Products; export 写错
export default Products;

@sorrycc
Copy link
Contributor Author

sorrycc commented Sep 20, 2016

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants