├── .gitignore
├── README.md
├── react16.2
├── example.gif
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
│ ├── createServiceWorker.js
│ ├── data.js
│ ├── index.js
│ ├── index.scss
│ └── package.json
└── react16.3
├── example.gif
├── package.json
├── public
├── favicon.ico
├── index.html
└── manifest.json
└── src
├── createServiceWorker.js
├── data.js
├── index.js
├── index.scss
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # antd-editTable
2 | 使用antd实现表格增、删、编辑,分别基于react16.2和react16.3实现两种方式
3 |
4 | ## 背景
5 | React在版本16.3-alpha里引入了新的Context API,antd3.10.0基于react16.3-alpha,利用React.createContext()特性实现表格编辑。
6 |
7 | ## 方式一:基于react16.2, antd8.4实现表格增、删、编辑,未实现校验功能
8 | ### 示例
9 | 
10 |
11 | ### Demo
12 | [https://codesandbox.io/s/v85jlv541y](https://codesandbox.io/s/v85jlv541y)
13 |
14 |
15 | ## 方式二:基于react16.3, antd3.10实现表格增、删、编辑,已实现校验功能
16 | ### 示例
17 | 
18 |
19 | ### Demo
20 | [https://codesandbox.io/s/73zvp3vljx](https://codesandbox.io/s/73zvp3vljx)
21 |
--------------------------------------------------------------------------------
/react16.2/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Youzi-wr/antd-editTable/b0db17313f451d1920a37f7c9234c58e077c9759/react16.2/example.gif
--------------------------------------------------------------------------------
/react16.2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "react-dom": "latest",
4 | "react": "latest",
5 | "antd": "latest"
6 | },
7 | "name": "v85jlv541y",
8 | "description": null,
9 | "version": "0.0.0",
10 | "devDependencies": {
11 | "react-scripts": "1.0.0"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test --env=jsdom",
17 | "eject": "react-scripts eject"
18 | }
19 | }
--------------------------------------------------------------------------------
/react16.2/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Youzi-wr/antd-editTable/b0db17313f451d1920a37f7c9234c58e077c9759/react16.2/public/favicon.ico
--------------------------------------------------------------------------------
/react16.2/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 |
27 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/react16.2/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react16.2/src/createServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | export default function register() {
12 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
13 | window.addEventListener('load', () => {
14 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
15 | navigator.serviceWorker
16 | .register(swUrl)
17 | .then(registration => {
18 | // eslint-disable-next-line no-param-reassign
19 | registration.onupdatefound = () => {
20 | const installingWorker = registration.installing;
21 | installingWorker.onstatechange = () => {
22 | if (installingWorker.state === 'installed') {
23 | if (navigator.serviceWorker.controller) {
24 | // At this point, the old content will have been purged and
25 | // the fresh content will have been added to the cache.
26 | // It's the perfect time to display a "New content is
27 | // available; please refresh." message in your web app.
28 | console.log('New content is available; please refresh.'); // eslint-disable-line no-console
29 | } else {
30 | // At this point, everything has been precached.
31 | // It's the perfect time to display a
32 | // "Content is cached for offline use." message.
33 | console.log('Content is cached for offline use.'); // eslint-disable-line no-console
34 | }
35 | }
36 | };
37 | };
38 | })
39 | .catch(error => {
40 | console.error('Error during service worker registration:', error);
41 | });
42 | });
43 | }
44 | }
45 |
46 | export function unregister() {
47 | if ('serviceWorker' in navigator) {
48 | navigator.serviceWorker.ready.then(registration => {
49 | registration.unregister();
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/react16.2/src/data.js:
--------------------------------------------------------------------------------
1 | export default {
2 | getList: [
3 | {
4 | name: "大庆水果城",
5 | price: "20",
6 | fruitTypes: ["apple"],
7 | tenantCode: "001",
8 | evaluate: false,
9 | id: 2905258602579968
10 | },
11 | {
12 | name: "同顺水果铺",
13 | price: "40",
14 | fruitTypes: ["apple", "orange"],
15 | tenantCode: "001",
16 | evaluate: false,
17 | id: 2904806276614144
18 | }
19 | ]
20 | };
21 |
--------------------------------------------------------------------------------
/react16.2/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import style from "./index.scss";
4 | import "antd/dist/antd.css";
5 | import data from "./data.js";
6 | import {
7 | Table,
8 | Checkbox,
9 | Input,
10 | Divider,
11 | Select,
12 | Button,
13 | notification,
14 | Form
15 | } from "antd";
16 |
17 | const sty = style;
18 | const Option = Select.Option;
19 | const CheckboxGroup = Checkbox.Group;
20 | const fruitList = [
21 | {
22 | value: "apple",
23 | label: "苹果"
24 | },
25 | {
26 | value: "banana",
27 | label: "香蕉"
28 | },
29 | {
30 | value: "orange",
31 | label: "橘子"
32 | }
33 | ];
34 |
35 | class Client extends React.Component {
36 | constructor(props) {
37 | super(props);
38 |
39 | this.state = {
40 | isRowOpen: false, //当前是否处于编辑状态(有且只有一行可编辑)
41 | locale: {
42 | emptyText: "暂无数据"
43 | },
44 | data: [],
45 | //正在编辑数据的缓存以便取消动作
46 | editCacheData: []
47 | };
48 |
49 | this.columns = [
50 | {
51 | title: "名称",
52 | key: "name", // todo 校验
53 | dataIndex: "name",
54 | render: (name, record) => {
55 | return record.type !== "view" ? (
56 | this.nameChange(e, record)}
59 | />
60 | ) : (
61 | name
62 | );
63 | }
64 | },
65 | {
66 | title: "评价一下",
67 | width: 120,
68 | key: "evaluate",
69 | dataIndex: "evaluate",
70 | render: (evaluate, record) => {
71 | return record.type !== "view" ? (
72 |
80 | ) : evaluate ? (
81 | "不好吃"
82 | ) : (
83 | "好吃"
84 | );
85 | }
86 | },
87 | {
88 | title: "水果",
89 | width: "25%",
90 | key: "fruitTypes",
91 | dataIndex: "fruitTypes",
92 | render: (fruitTypes, record) => {
93 | return (
94 | this.fruitTypesChange(e, record)}
96 | disabled={record.type !== "view" ? false : true}
97 | options={fruitList}
98 | defaultValue={fruitTypes}
99 | />
100 | );
101 | }
102 | },
103 | {
104 | title: "价格",
105 | width: "38%",
106 | key: "price", // todo 校验
107 | render: record => {
108 | return record.type !== "view" ? (
109 | this.priceChange(e, record)}
112 | />
113 | ) : (
114 | record.price
115 | );
116 | }
117 | },
118 | {
119 | title: "操作",
120 | render: record => (
121 |
122 | {record.type === "new" && (
123 |
124 | this.addSubmit(record)}>
125 | 完成
126 |
127 |
128 | this.removeAdd(record)}>
129 | 取消
130 |
131 |
132 | )}
133 | {record.type === "edit" && (
134 |
135 | this.editSubmit(record)}>
136 | 完成
137 |
138 |
139 | this.giveUpUpdata(record)}>
140 | 取消
141 |
142 |
143 | this.delete(record)}>
144 | 删除
145 |
146 |
147 | )}
148 | {record.type === "view" && (
149 |
150 | this.edit(record)}>
151 | 编辑
152 |
153 |
154 | this.delete(record)}>
155 | 删除
156 |
157 |
158 | )}
159 |
160 | ),
161 | width: 150
162 | }
163 | ];
164 | }
165 | componentDidMount() {
166 | this.initRowType(data.getList);
167 | }
168 | initRowType(data) {
169 | for (let item of data) {
170 | item["type"] = "view";
171 | }
172 | this.updateDataSource(data);
173 | }
174 | // ---------------------- cell change start------------------
175 | nameChange(e, record) {
176 | this.updateEditCacheData(record, { name: e.target.value });
177 | }
178 | evaluateChange(e, record) {
179 | this.updateEditCacheData(record, { evaluate: e == "1" ? true : false });
180 | }
181 | fruitTypesChange(e, record) {
182 | this.updateEditCacheData(record, { fruitTypes: e });
183 | }
184 | priceChange(e, record) {
185 | this.updateEditCacheData(record, { price: e.target.value });
186 | }
187 | // ---------------------- cell change end------------------
188 | updateEditCacheData(record, obj) {
189 | let { editCacheData } = this.state;
190 | let cacheData =
191 | record.id === editCacheData.id
192 | ? { ...editCacheData, ...obj }
193 | : { ...record, ...obj };
194 | this.setState({ editCacheData: cacheData });
195 | }
196 | updateDataSource(newData, isAddDisabled) {
197 | let isRowOpen =
198 | typeof isAddDisabled == "boolean"
199 | ? isAddDisabled
200 | : newData.some(item => item.type === "new" || item.type === "edit");
201 | this.setState({
202 | isRowOpen,
203 | data: newData
204 | });
205 | }
206 | addRow = () => {
207 | let { data } = this.state;
208 | let newRecord = {
209 | fruitTypes: ["apple", "banana", "orange"],
210 | name: "",
211 | evaluate: true,
212 | price: "",
213 | type: "new",
214 | id: ""
215 | };
216 |
217 | data.push(newRecord);
218 | this.updateDataSource(data);
219 | };
220 | addSubmit(record) {
221 | let { data, editCacheData } = this.state;
222 | // console.log(editCacheData);
223 | setTimeout(res => {
224 | editCacheData.type = "view";
225 | data.pop();
226 | data.push(editCacheData);
227 | this.updateDataSource(data);
228 | notification["success"]({ message: "添加成功!" });
229 | }, 500);
230 | }
231 | removeAdd(record) {
232 | let { data } = this.state;
233 | data.pop();
234 | this.updateDataSource(data);
235 | }
236 | editSubmit(record) {
237 | let { data, editCacheData } = this.state;
238 |
239 | setTimeout(res => {
240 | //将cacheData更新到dataSource
241 | let newData = data.map(item => {
242 | if (item.id === editCacheData.id) {
243 | item = Object.assign({}, editCacheData);
244 | item.type = "view";
245 | }
246 | return item;
247 | });
248 | this.updateDataSource(newData);
249 | notification["success"]({ message: "修改成功!" });
250 | }, 500);
251 | }
252 | giveUpUpdata(record) {
253 | let { data } = this.state;
254 | let editRow = data.find(item => item.id === record.id);
255 | editRow.type = "view";
256 | this.updateDataSource(data);
257 | }
258 | delete(record) {
259 | let { data } = this.state;
260 | console.log(record);
261 | setTimeout(res => {
262 | let index = data.findIndex(item => item.id === record.id);
263 | data.splice(index, 1);
264 | this.updateDataSource(data);
265 | notification["success"]({ message: "删除成功!" });
266 | });
267 | }
268 | edit(record) {
269 | let { data } = this.state;
270 | let newData = data.filter(item => {
271 | if (item.id === record.id) {
272 | item.type = "edit";
273 | return item;
274 | } else if (item.type !== "new") {
275 | item.type = "view";
276 | return item;
277 | }
278 | });
279 | this.updateDataSource(newData, true);
280 | }
281 | render() {
282 | const { data, locale, isRowOpen } = this.state;
283 |
284 | return (
285 |
286 |
287 |
294 |
record.id}
298 | size={"middle"}
299 | columns={this.columns}
300 | dataSource={data}
301 | pagination={false}
302 | />
303 |
304 |
305 | );
306 | }
307 | }
308 |
309 | ReactDOM.render(, document.getElementById("container"));
310 |
--------------------------------------------------------------------------------
/react16.2/src/index.scss:
--------------------------------------------------------------------------------
1 | .client {
2 | padding: 16px;
3 | .client-wrap {
4 | padding: 20px;
5 | background-color: #fff;
6 | }
7 | .colmns-ip {
8 | display: flex;
9 | justify-content: space-between;
10 | align-items: center;
11 | }
12 | :global {
13 | .ant-table-thead > tr > th,
14 | .ant-table-tbody > tr > td {
15 | padding: 15px 9px;
16 | }
17 | .editable-row .ant-form-explain {
18 | position: absolute;
19 | font-size: 12px;
20 | margin-top: -4px;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/react16.2/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "react-dom": "latest",
4 | "react": "latest",
5 | "antd": "latest"
6 | }
7 | }
--------------------------------------------------------------------------------
/react16.3/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Youzi-wr/antd-editTable/b0db17313f451d1920a37f7c9234c58e077c9759/react16.3/example.gif
--------------------------------------------------------------------------------
/react16.3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "react-dom": "^16.3.2",
4 | "react": "^16.3.2",
5 | "antd": "^3.10.0"
6 | },
7 | "name": "73zvp3vljx",
8 | "description": null,
9 | "version": "0.0.17",
10 | "devDependencies": {
11 | "react-scripts": "1.0.0"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test --env=jsdom",
17 | "eject": "react-scripts eject"
18 | }
19 | }
--------------------------------------------------------------------------------
/react16.3/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Youzi-wr/antd-editTable/b0db17313f451d1920a37f7c9234c58e077c9759/react16.3/public/favicon.ico
--------------------------------------------------------------------------------
/react16.3/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 |
27 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/react16.3/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react16.3/src/createServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | export default function register() {
12 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
13 | window.addEventListener('load', () => {
14 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
15 | navigator.serviceWorker
16 | .register(swUrl)
17 | .then(registration => {
18 | // eslint-disable-next-line no-param-reassign
19 | registration.onupdatefound = () => {
20 | const installingWorker = registration.installing;
21 | installingWorker.onstatechange = () => {
22 | if (installingWorker.state === 'installed') {
23 | if (navigator.serviceWorker.controller) {
24 | // At this point, the old content will have been purged and
25 | // the fresh content will have been added to the cache.
26 | // It's the perfect time to display a "New content is
27 | // available; please refresh." message in your web app.
28 | console.log('New content is available; please refresh.'); // eslint-disable-line no-console
29 | } else {
30 | // At this point, everything has been precached.
31 | // It's the perfect time to display a
32 | // "Content is cached for offline use." message.
33 | console.log('Content is cached for offline use.'); // eslint-disable-line no-console
34 | }
35 | }
36 | };
37 | };
38 | })
39 | .catch(error => {
40 | console.error('Error during service worker registration:', error);
41 | });
42 | });
43 | }
44 | }
45 |
46 | export function unregister() {
47 | if ('serviceWorker' in navigator) {
48 | navigator.serviceWorker.ready.then(registration => {
49 | registration.unregister();
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/react16.3/src/data.js:
--------------------------------------------------------------------------------
1 | export default {
2 | getList: [
3 | {
4 | name: "大庆水果城",
5 | price: "20",
6 | fruitTypes: ["apple"],
7 | tenantCode: "001",
8 | evaluate: false,
9 | id: 2905258602579968
10 | },
11 | {
12 | name: "同顺水果铺",
13 | price: "40",
14 | fruitTypes: ["apple", "orange"],
15 | tenantCode: "001",
16 | evaluate: false,
17 | id: 2904806276614144
18 | }
19 | ]
20 | };
21 |
--------------------------------------------------------------------------------
/react16.3/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import style from "./index.scss";
4 | import "antd/dist/antd.css";
5 | import data from "./data.js";
6 | import {
7 | Table,
8 | Checkbox,
9 | Input,
10 | Divider,
11 | Select,
12 | Button,
13 | notification,
14 | Form
15 | } from "antd";
16 |
17 | const sty = style;
18 | const CheckboxGroup = Checkbox.Group;
19 | const FormItem = Form.Item;
20 | const EditableContext = React.createContext();
21 | const fruitList = [
22 | {
23 | value: "apple",
24 | label: "苹果"
25 | },
26 | {
27 | value: "banana",
28 | label: "香蕉"
29 | },
30 | {
31 | value: "orange",
32 | label: "橘子"
33 | }
34 | ];
35 |
36 | const EditableRow = ({ form, index, ...props }) => (
37 |
38 |
39 |
40 | );
41 |
42 | const EditableFormRow = Form.create()(EditableRow);
43 |
44 | class EditableCell extends React.Component {
45 | constructor(props) {
46 | super(props);
47 | }
48 | render() {
49 | const { renderDom, record, ...restProps } = this.props;
50 |
51 | return (
52 | (this.cell = node)} {...restProps}>
53 |
54 | {form => {
55 | this.form = form;
56 | return renderDom(form, record);
57 | }}
58 |
59 | |
60 | );
61 | }
62 | }
63 |
64 | class Client extends React.Component {
65 | constructor(props) {
66 | super(props);
67 |
68 | this.state = {
69 | isRowOpen: false, //当前是否处于编辑状态(有且只有一行可编辑)
70 | locale: {
71 | emptyText: "暂无数据"
72 | },
73 | data: []
74 | };
75 |
76 | this.columns = [
77 | {
78 | title: "名称",
79 | key: "name",
80 | renderDom: (form, record) => {
81 | return record.type !== "view" ? (
82 |
83 | {form.getFieldDecorator("name", {
84 | rules: [
85 | {
86 | required: true,
87 | message: "名称不能为空!"
88 | }
89 | ],
90 | initialValue: record.name
91 | })()}
92 |
93 | ) : (
94 | record.name
95 | );
96 | }
97 | },
98 | {
99 | title: "评价一下",
100 | width: 120,
101 | key: "evaluate",
102 | renderDom: (form, record) => {
103 | return record.type !== "view" ? (
104 |
105 | {form.getFieldDecorator("evaluate", {
106 | rules: [],
107 | initialValue: record.evaluate ? "1" : "0"
108 | })(
109 |
113 | )}
114 |
115 | ) : record.evaluate ? (
116 | "不好吃"
117 | ) : (
118 | "好吃"
119 | );
120 | }
121 | },
122 | {
123 | title: "水果",
124 | width: "25%",
125 | key: "fruitTypes",
126 | renderDom: (form, record) => {
127 | return (
128 |
129 | {form.getFieldDecorator("fruitTypes", {
130 | rules: [],
131 | initialValue: record.fruitTypes
132 | })(
133 |
137 | )}
138 |
139 | );
140 | }
141 | },
142 | {
143 | title: "价格",
144 | width: "38%",
145 | key: "price",
146 | renderDom: (form, record) => {
147 | return record.type !== "view" ? (
148 |
149 | {form.getFieldDecorator("price", {
150 | rules: [
151 | {
152 | required: true,
153 | message: "价格不能为空!"
154 | }
155 | ],
156 | initialValue: record.price
157 | })()}
158 |
159 | ) : (
160 | record.price
161 | );
162 | }
163 | },
164 | {
165 | title: "操作",
166 | renderDom: (form, record) => (
167 |
168 | {record.type === "new" && (
169 |
170 | this.addSubmit(form, record)}
173 | >
174 | 完成
175 |
176 |
177 | this.removeAdd(record)}>
178 | 取消
179 |
180 |
181 | )}
182 | {record.type === "edit" && (
183 |
184 | this.editSubmit(form, record)}
187 | >
188 | 完成
189 |
190 |
191 | this.giveUpUpdata(record)}>
192 | 取消
193 |
194 |
195 | this.delete(record)}>
196 | 删除
197 |
198 |
199 | )}
200 | {record.type === "view" && (
201 |
202 | this.edit(record)}>
203 | 编辑
204 |
205 |
206 | this.delete(record)}>
207 | 删除
208 |
209 |
210 | )}
211 |
212 | ),
213 | width: 150
214 | }
215 | ];
216 | }
217 | componentDidMount() {
218 | this.initRowType(data.getList);
219 | }
220 | initRowType(data) {
221 | for (let item of data) {
222 | item["type"] = "view";
223 | }
224 | this.updateDataSource(data);
225 | }
226 | updateDataSource(newData, isAddDisabled) {
227 | let isRowOpen =
228 | typeof isAddDisabled == "boolean"
229 | ? isAddDisabled
230 | : newData.some(item => item.type === "new" || item.type === "edit");
231 | this.setState({
232 | isRowOpen,
233 | data: newData
234 | });
235 | }
236 | addRow = () => {
237 | let { data } = this.state;
238 | let newRecord = {
239 | fruitTypes: ["apple", "banana", "orange"],
240 | name: "",
241 | evaluate: true,
242 | price: "",
243 | type: "new",
244 | id: ""
245 | };
246 |
247 | data.push(newRecord);
248 | this.updateDataSource(data);
249 | };
250 | addSubmit(form, record) {
251 | let { data } = this.state;
252 |
253 | form.validateFields((error, values) => {
254 | if (error) {
255 | return;
256 | }
257 | values.evaluate = values.evaluate == "1" ? true : false;
258 | let updateData = { ...record, ...values };
259 |
260 | setTimeout(res => {
261 | updateData.type = "view";
262 | data.pop();
263 | data.push(updateData);
264 | this.updateDataSource(data);
265 | notification["success"]({ message: "添加成功!" });
266 | }, 500);
267 | });
268 | }
269 | editSubmit(form, record) {
270 | let { data } = this.state;
271 |
272 | form.validateFields((error, values) => {
273 | if (error) {
274 | return;
275 | }
276 | values.evaluate = values.evaluate == "1" ? true : false;
277 | let updateData = { ...record, ...values };
278 |
279 | // console.log(updateData);
280 | setTimeout(res => {
281 | //将updateData更新到dataSource
282 | let newData = data.map(item => {
283 | if (item.id === updateData.id) {
284 | item = Object.assign({}, updateData);
285 | item.type = "view";
286 | }
287 | return item;
288 | });
289 | this.updateDataSource(newData);
290 | notification["success"]({ message: "修改成功!" });
291 | });
292 | });
293 | }
294 | removeAdd(record) {
295 | let { data } = this.state;
296 | data.pop();
297 | this.updateDataSource(data);
298 | }
299 | giveUpUpdata(record) {
300 | let { data } = this.state;
301 | let editRow = data.find(item => item.id === record.id);
302 | editRow.type = "view";
303 | this.updateDataSource(data);
304 | }
305 | delete(record) {
306 | let { data } = this.state;
307 | // console.log(record);
308 | setTimeout(res => {
309 | let index = data.findIndex(item => item.id === record.id);
310 | data.splice(index, 1);
311 | this.updateDataSource(data);
312 | notification["success"]({ message: "删除成功!" });
313 | });
314 | }
315 | edit(record) {
316 | let { data } = this.state;
317 | let newData = data.filter(item => {
318 | if (item.id === record.id) {
319 | item.type = "edit";
320 | return item;
321 | } else if (item.type !== "new") {
322 | item.type = "view";
323 | return item;
324 | }
325 | });
326 | this.updateDataSource(newData, true);
327 | }
328 | render() {
329 | const { data, locale, isRowOpen } = this.state;
330 | const components = {
331 | body: {
332 | row: EditableFormRow,
333 | cell: EditableCell
334 | }
335 | };
336 | const columns = this.columns.map(col => {
337 | return {
338 | ...col,
339 | onCell: record => ({
340 | ...col,
341 | record
342 | })
343 | };
344 | });
345 |
346 | return (
347 |
348 |
349 |
356 |
record.id}
361 | columns={columns}
362 | dataSource={data}
363 | pagination={false}
364 | rowClassName="editable-row"
365 | />
366 |
367 |
368 | );
369 | }
370 | }
371 |
372 | ReactDOM.render(, document.getElementById("container"));
373 |
--------------------------------------------------------------------------------
/react16.3/src/index.scss:
--------------------------------------------------------------------------------
1 | .client {
2 | padding: 16px;
3 | .client-wrap {
4 | padding: 20px;
5 | background-color: #fff;
6 | }
7 | .colmns-ip {
8 | display: flex;
9 | justify-content: space-between;
10 | align-items: center;
11 | }
12 | .ant-table-thead > tr > th,
13 | .ant-table-tbody > tr > td {
14 | padding: 15px 9px;
15 | }
16 | .editable-row .ant-form-explain {
17 | position: absolute;
18 | font-size: 12px;
19 | margin-top: -4px;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/react16.3/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "react-dom": "^16.3.2",
4 | "react": "^16.3.2",
5 | "antd": "^3.10.0"
6 | }
7 | }
--------------------------------------------------------------------------------