{"id":14976330,"url":"https://github.com/xiubug/react-antd","last_synced_at":"2025-07-26T00:35:39.011Z","repository":{"id":54982589,"uuid":"82528598","full_name":"xiubug/react-antd","owner":"xiubug","description":"基于react + redux + immutable + less + ES6/7 + webpack2.0 + fetch + react-router + antd实现的SPA后台管理系统模板","archived":false,"fork":false,"pushed_at":"2021-01-18T02:56:23.000Z","size":805,"stargazers_count":318,"open_issues_count":0,"forks_count":73,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-03-31T07:08:58.391Z","etag":null,"topics":["admin","ant-design","es6","es7","immutable","less","react","react-redux","react-router","redux","webpack2"],"latest_commit_sha":null,"homepage":"http://antd.sosout.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xiubug.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-20T07:21:08.000Z","updated_at":"2025-01-16T11:34:22.000Z","dependencies_parsed_at":"2022-08-14T08:10:18.072Z","dependency_job_id":null,"html_url":"https://github.com/xiubug/react-antd","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiubug%2Freact-antd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiubug%2Freact-antd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiubug%2Freact-antd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiubug%2Freact-antd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xiubug","download_url":"https://codeload.github.com/xiubug/react-antd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247622983,"owners_count":20968575,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["admin","ant-design","es6","es7","immutable","less","react","react-redux","react-router","redux","webpack2"],"created_at":"2024-09-24T13:53:43.882Z","updated_at":"2025-04-07T09:20:14.702Z","avatar_url":"https://github.com/xiubug.png","language":"JavaScript","funding_links":[],"categories":["Admin Template"],"sub_categories":["React"],"readme":"# react-antd(新版后台很快就与大家见面了)\n[![React Native](https://img.shields.io/badge/react-^15.3.2-brightgreen.svg?style=flat-square)](https://github.com/facebook/react)\n[![Redux](https://img.shields.io/badge/redux-^4.4.5-yellowgreen.svg?style=flat-square)](https://github.com/reactjs/redux)\n[![Redux Immutablejs](https://img.shields.io/badge/immutablejs-^0.0.8-orange.svg?style=flat-square)](https://github.com/indexiatech/redux-immutablejs)\n[![Ant Design](https://img.shields.io/badge/ant--design-^2.7.2-yellowgreen.svg?style=flat-square)](https://github.com/ant-design/ant-design)\n\n[![MIT](https://img.shields.io/dub/l/vibe-d.svg?style=flat-square)](http://opensource.org/licenses/MIT)\n\n## 相关推荐\n[基于vue + vuex + less + ES6/7 + webpack + fetch + vue-router + store + element-ui实现的SPA后台管理系统模板](https://github.com/sosout/vue2-element)\n\n[Redux源码解析-Redux的架构](https://github.com/sosout/redux-source-analyse)\n\n[Immutable源码解析-Immutable的架构](https://github.com/sosout/immutable-source-analyse)\n\n\n## 最新更新\n\u003e  webpack版本升级2，同时引入Yarn缓存下载的每个包以及happypack利用了多进程，同时还利用缓存来使得rebuild 更快等\n\n\u003e  Redux使用调整\n\n\u003e 路由模式更改为浏览器模式\n\n## 前言\n\u003e  本工程主要基于react + redux + immutable + less + ES6/7 + webpack2.0 + fetch + react-router + antd(1.x)实现的SPA后台管理系统模板。\n\n\u003e  如果觉得不错的话，请star一下吧 😊\n\n\u003e  编码时间：8:00——9:30, 下班时间——24:00，其他时间要工作。代码未优化，处女座代码必须要优化。由于代码延后，先向大家说声抱歉。您有什么问题可以私信我segmentfault。\n\n[线上demo](http://antd.sosout.com/)\n\n## 关于我自己\n\n\u003e  使用技术： react + redux + immutable + less + ES6/7 + webpack2.0 + fetch + react-router + antd(1.x)\n\n\u003e  项目说明： 此项目是本人空余时间搭建的。希望大家提供宝贵的意见和建议，谢谢。\n\n\u003e  JS/React/Vue/Angular前端群： 599399742\n\n\u003e  邮\u0026emsp;\u0026emsp;\u0026ensp;箱： sosout@139.com\n\n\u003e  个人网站： http://www.sosout.com/\n\n\u003e  个人博客： http://blog.sosout.com/\n\n\u003e  个人简书： http://www.jianshu.com/users/23b9a23b8849/latest_articles\n\n\u003e  segmentfault：https://segmentfault.com/u/sosout\n\n### 下载\n\n```\n# git clone\n\ngit clone https://github.com/sosout/react-antd.git\n\ncd react-antd\n```\n\n### 安装\n```bush\n\n// 安装前请先确保已安装node和npm\n\n// 安装成功后,再安装依赖，如果之前有用npm安装过，请先删掉node_modules\nyarn install\n```\n### 运行\n```bush\nyarn run dev （开发版本，用于开发使用，热加载）\n  \nyarn run dist （发布生产版本，对代码进行混淆压缩，提取公共代码，分离css文件）\n```\n\n### 访问\n在浏览器地址栏输入[http://127.0.0.1:8888](http://127.0.0.1:8888)\n\n### 目标功能\n- [x] 登录页面\n- [x] 全站布局\n- [x] 全站路由\n- [ ] 对接接口，优化代码(冗余代码，不规则写法，界面样式)\n- [ ] 后台系统常用场景会逐个完善\n\n### 历史更新\n  *2017.02.20*\n\n  \t1. 初始化项目目录;\n\n  \t2. webpack版本升级(webpack2.0)，并加上yarn，happypack等(最新迭代)；\n\n  \t3. 登录退出;\n\n  \t4. 整体布局;\n\n  \t5. 菜单映射路由(路由模式更改为浏览器模式);\n    \n# 性能优化\n\n## 如何正确地在React中处理事件\n\n[参考官网](https://facebook.github.io/react/docs/handling-events.html)\n\n#### 1、构造器内绑定this\n```javascript\nclass MyComponent extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            count: 0\n        };\n        this.handleClick = this.handleClick.bind(this);\n    }\n\n    handleClick() {\n        this.setState({\n            count: ++this.state.count\n        });\n    }\n\n    render() {\n        return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{this.state.count}\u003c/div\u003e\n            \u003cbutton onClick={this.handleClick}\u003eClick\u003c/button\u003e\n        \u003c/div\u003e\n        );\n    }\n}\n```\n这种方式的好处是每次render，不会重新创建一个回调函数，没有额外的性能损失。需要注意的是，使用这种方式要在构造函数中为事件回调函数绑定this:  this.handleClick = this.handleClick.bind(this)，否则handleClick中的this是undefined。这是因为ES6 语法的缘故，ES6 的 Class 构造出来的对象上的方法默认不绑定到 this 上，需要我们手动绑定。\n\n#### 2、属性初始化\n使用ES7的 property initializers，代码可以这样写：\n```javascript\nclass MyComponent extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            count: 0\n        };\n    }\n\n    handleClick = () =\u003e {\n        this.setState({\n            count: ++this.state.count\n        });\n    }\n\n    render() {\n        return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{this.state.count}\u003c/div\u003e\n            \u003cbutton onClick={this.handleClick}\u003eClick\u003c/button\u003e\n        \u003c/div\u003e\n        );\n    }\n}\n```\n这种方式就不需要手动绑定this了。但是你需要知道，这个特性还处于试验阶段，默认是不支持的。如果你是使用官方脚手架Create React App 创建的应用，那么这个特性是默认支持的。你也可以自行在项目中引入babel的transform-class-properties插件获取这个特性支持。\n\n#### 3、箭头函数\n```javascript\nclass MyComponent extends React.Component {\n    render() {\n        return (\n        \u003cbutton onClick={()=\u003e{console.log('button clicked');}}\u003e\n            Click\n        \u003c/button\u003e\n        );\n    }\n}\n```\n当事件响应逻辑比较复杂时，如果再把所有的逻辑直接写在onClick的大括号内，就会导致render函数变得臃肿，不容易直观地看出组件render出的元素结构。这时，可以把逻辑封装成组件的一个方法，然后在箭头函数中调用这个方法。如下所示：\n```javascript\nclass MyComponent extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            count: 0\n        };\n    }\n    handleClick() {\n        this.setState({\n            count: ++this.state.count\n        });\n    }\n    render() {\n        return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{this.state.number}\u003c/div\u003e\n            \u003cbutton onClick={()=\u003e{this.handleClick();}}\u003eClick\u003c/button\u003e\n        \u003c/div\u003e\n        );\n    }\n}\n```\n这种方式最大的问题是，每次render调用时，都会重新创建一个事件的回调函数，带来额外的性能开销，当组件的层级越低时，这种开销就越大，因为任何一个上层组件的变化都可能会触发这个组件的render方法。当然，在大多数情况下，这点性能损失是可以不必在意的。这种方式也有一个好处，就是不需要考虑this的指向问题，因为这种写法保证箭头函数中的this指向的总是当前组件。\n\n#### 4、函数传递参数\n事件的回调函数默认是会被传入一个事件对象Event作为参数的。如果我想传入其他参数给回调函数应该怎么办呢？\n\n使用第一种方式（构造器内绑定this）的话，可以把绑定this的操作延迟到render中，在绑定this的同时，绑定额外的参数：\n```javascript\n// 代码6\nclass MyComponent extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n        list: [1,2,3,4],\n        current: 1\n        };\n    }\n\n    handleClick(item) {\n        this.setState({\n            current: item\n        });\n    }\n\n    render() {\n        return (\n        \u003cul\u003e\n            {this.state.list.map(\n                (item)=\u003e(\n                \u003cli className={this.state.current === item ? 'current':''} \n                onClick={this.handleClick.bind(this, item)}\u003e{item}\n                \u003c/li\u003e\n                )\n            )}\n        \u003c/ul\u003e\n        );\n    }\n}\n```\n使用第二种方式（属性初始化），解决方案和第一种基本一致：\n```javascript\n// 代码7\nclass MyComponent extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            list: [1,2,3,4],\n            current: 1\n        };\n    }\n\n    handleClick = (item) =\u003e  {\n        this.setState({\n            current: item\n        });\n    }\n\n    render() {\n        return (\n        \u003cul\u003e\n            {this.state.list.map(\n                (item)=\u003e(\n                \u003cli className={this.state.current === item ? 'current':''} \n                onClick={this.handleClick.bind(undefined, item)}\u003e{item}\n                \u003c/li\u003e\n                )\n            )}\n        \u003c/ul\u003e\n        );\n    }\n}\n```\n不过这种方式就有点鸡肋了，因为虽然你不需要通过bind函数绑定this，但仍然要使用bind函数来绑定其他参数。\n\n使用第三种方式（函数传递参数）的话很简单，直接传就可以了：\n```javascript\nclass MyComponent extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            list: [1,2,3,4],\n            current: 1\n        };\n    }\n\n    handleClick(item,event) {\n        this.setState({\n            current: item\n        });\n    }\n\n    render() {\n        return (\n        \u003cul\u003e\n            {this.state.list.map(\n                (item)=\u003e(\n                \u003cli className={this.state.current === item ? 'current':''} \n                onClick={(event) =\u003e this.handleClick(item, event)}\u003e{item}\n                \u003c/li\u003e\n                )\n            )}\n        \u003c/ul\u003e\n        );\n    }\n}\n```\n\n关于事件响应的回调函数，还有一个地方需要注意。不管你在回调函数中有没有显式的声明事件参数Event，React都会把事件Event作为参数传递给回调函数，且参数Event的位置总是在其他自定义参数的后面。例如，在代码6和代码7中，handleClick的参数中虽然没有声明Event参数，但你依然可以通过arguments[1]获取到事件Event对象。\n\n总结一下，三种绑定事件回调的方式，第一种有额外的性能损失；第二种需要手动绑定this，代码量增多；第三种用到了ES7的特性，目前并非默认支持，需要Babel插件的支持，但是写法最为简洁，也不需要手动绑定this。推荐使用第二种和第三种方式。\n\n## Immutable 详解及 React 中实践 (https://github.com/camsong/blog/issues/3)\n\n## react 实现pure render的时候，bind(this)隐患\n```javascript\nexport default class Parent extends Component {\n...\n  render() {\n    const {name,age} =this.state;\n    return (\n      \u003cdiv\u003e\n        \u003cChild name={name} age={age} onClick={this._handleClick.bind(this)}\u003e\u003c/Child\u003e//bug 所在\n      \u003c/div\u003e\n    )\n  }\n...\n}\n```\n发现一个问题，对于Child这个子组件来说，在父组件re－render的时候，即使Child得前后两个props都没改变，它依旧会re－render。。即使用immutable.js也不好使。。。原来啊，父组件每次render，_handleClick都会执行bind(this) 这样_handleClick的引用每次都会改。。所以Child前后两次props其实是不一样的。。\n那怎么办？把bind（this）去掉？不行 还必须得用。真正的答案是 让父组件每次render 不执行bind（this），直接提前在constructor执行好，修改之后\n```javascript\nexport default class Parent extends Component {\n  constructor(props){\n    super(props)\n    this._handleClick=this._handleClick.bind(this)//改成这样\n  }\n  render() {\n    const {name,age} =this.state;\n    return (\n      \u003cdiv\u003e\n        \u003cChild name={name} age={age} onClick={this._handleClick}\u003e\u003c/Child\u003e\n      \u003c/div\u003e\n    )\n  }\n...\n}\n```\n## 子组件跟随父组件re－render\n想象一下这种场景，一个父组件下面一大堆子组件。然后呢，这个父组件re－render。是不是下面的子组件都得跟着re－render。可是很多子组件里面是冤枉的啊！！很多子组件的props 和 state 然而并没有改变啊！！虽然virtual dom 的diff 算法很快。。但是性能也不是这么浪费的啊！！\n```javascript\nclass Child  extends Component {\n  render() {\n    console.log(\"我re-render了\");\n    const {name,age} = this.props;\n\n      return (\n        \u003cdiv\u003e\n          \u003cspan\u003e姓名:\u003c/span\u003e\n          \u003cspan\u003e{name}\u003c/span\u003e\n          \u003cspan\u003e age:\u003c/span\u003e\n          \u003cspan\u003e{age}\u003c/span\u003e\n        \u003c/div\u003e\n      )\n  }\n}\nconst Person = pureRender(Child);\n```\npureRender其实就是一个函数，接受一个Component。把这个Component搞一搞，返回一个Component看他pureRender的源代码就一目了然\n```javascript\nfunction shouldComponentUpdate(nextProps, nextState) {\n  return shallowCompare(this, nextProps, nextState);\n}\n\nfunction pureRende(component) {\n  component.prototype.shouldComponentUpdate = shouldComponentUpdate;\n}\nmodule.exports = pureRender;\n```\npureRender很简单，就是把传进来的component的shouldComponentUpdate给重写掉了，原来的shouldComponentUpdate，无论怎样都是return ture，现在不了，我要用shallowCompare比一比，shallowCompare代码及其简单，如下\n```javascript\nfunction shallowCompare(instance, nextProps, nextState) {\n  return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState);\n}  \n```\n一目了然。分别拿现在props\u0026state和要传进来的props\u0026state，用shallowEqual比一比，要是props\u0026state都一样的话，就return false\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiubug%2Freact-antd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxiubug%2Freact-antd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiubug%2Freact-antd/lists"}