├── .all-contributorsrc
├── .babelrc.js
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .github
└── badge.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .stylelintrc
├── .travis.yml
├── LICENSE
├── README-zh.md
├── README.md
├── assets
├── image-20181106222453747.png
├── image-20181106224258372.png
├── image-20181106224933515.png
├── image-20181106225421654.png
├── image-20181106230058138.png
└── image-20181106231010055.png
├── build.sh
├── build
└── rollup.config.js
├── docs
├── axios-config.md
├── basic.md
├── before-confirm.md
├── before-search.md
├── can-search-collapse.md
├── clear-selection.md
├── custom-text.md
├── expand.md
├── extra-body.md
├── extra-buttons.md
├── extra-query.sync.md
├── faq.md
├── first-page.md
├── formatter.md
├── guide-contributing-correctly.md
├── has-pagination=false.md
├── header-buttons.md
├── id.md
├── is-tree.md
├── multi-level-header.md
├── on-default-delete.md
├── on-new-edit-delete.md
├── on-response.md
├── on-success.md
├── persist-selection.md
├── save-query.md
├── search-immediately.md
├── search-item-collapsible.md
├── slot-form.md
├── slot-header.md
├── slot-no-data.md
├── slot-operation.md
├── slot-search.md
└── table-props-events.md
├── netlify.sh
├── notify.sh
├── package.json
├── src
├── components
│ ├── el-data-table-column.js
│ ├── self-loading-button.vue
│ ├── text-button.vue
│ └── the-dialog.vue
├── el-data-table.d.ts
├── el-data-table.md
├── el-data-table.vue
├── index.js
└── utils
│ ├── extract-keys.js
│ ├── query.js
│ ├── search-immediately-item.js
│ ├── select-strategy.js
│ └── utils.js
├── styleguide.config.js
├── styleguide
├── axios.js
├── el-form-renderer.js
└── element.js
├── test
├── extract-keys.test.js
├── query.test.js
├── select-strategy.test.js
└── utils.test.js
└── yarn.lock
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "el-data-table",
3 | "projectOwner": "FEMessage",
4 | "repoType": "github",
5 | "repoHost": "https://github.com",
6 | "files": [
7 | "README.md"
8 | ],
9 | "imageSize": 100,
10 | "commit": false,
11 | "commitConvention": "angular",
12 | "contributors": [
13 | {
14 | "login": "levy9527",
15 | "name": "levy",
16 | "avatar_url": "https://avatars3.githubusercontent.com/u/9384365?v=4",
17 | "profile": "http://levy.work",
18 | "contributions": [
19 | "code",
20 | "review",
21 | "doc",
22 | "infra",
23 | "ideas"
24 | ]
25 | },
26 | {
27 | "login": "donaldshen",
28 | "name": "Donald Shen",
29 | "avatar_url": "https://avatars3.githubusercontent.com/u/19591950?v=4",
30 | "profile": "https://donaldshen.github.io/portfolio",
31 | "contributions": [
32 | "code",
33 | "test",
34 | "doc"
35 | ]
36 | },
37 | {
38 | "login": "MiffyCooper",
39 | "name": "MiffyCooper",
40 | "avatar_url": "https://avatars1.githubusercontent.com/u/20179564?v=4",
41 | "profile": "https://github.com/MiffyCooper",
42 | "contributions": [
43 | "code",
44 | "doc"
45 | ]
46 | },
47 | {
48 | "login": "prisbre",
49 | "name": "Huanfeng Chen",
50 | "avatar_url": "https://avatars1.githubusercontent.com/u/13557397?v=4",
51 | "profile": "https://github.com/prisbre",
52 | "contributions": [
53 | "code"
54 | ]
55 | },
56 | {
57 | "login": "evillt",
58 | "name": "EVILLT",
59 | "avatar_url": "https://avatars3.githubusercontent.com/u/19513289?v=4",
60 | "profile": "https://evila.me",
61 | "contributions": [
62 | "code",
63 | "bug"
64 | ]
65 | },
66 | {
67 | "login": "Alvin-Liu",
68 | "name": "Alvin",
69 | "avatar_url": "https://avatars0.githubusercontent.com/u/11909145?v=4",
70 | "profile": "https://github.com/Alvin-Liu",
71 | "contributions": [
72 | "code",
73 | "bug"
74 | ]
75 | },
76 | {
77 | "login": "lianghx-319",
78 | "name": "Han",
79 | "avatar_url": "https://avatars2.githubusercontent.com/u/27187946?v=4",
80 | "profile": "https://github.com/lianghx-319",
81 | "contributions": [
82 | "code",
83 | "bug",
84 | "doc"
85 | ]
86 | },
87 | {
88 | "login": "kunzhijia",
89 | "name": "kunzhijia",
90 | "avatar_url": "https://avatars2.githubusercontent.com/u/4848041?v=4",
91 | "profile": "https://github.com/kunzhijia",
92 | "contributions": [
93 | "code",
94 | "tool",
95 | "example"
96 | ]
97 | },
98 | {
99 | "login": "chenEdgar",
100 | "name": "Edgar",
101 | "avatar_url": "https://avatars3.githubusercontent.com/u/12596622?v=4",
102 | "profile": "https://github.com/chenEdgar",
103 | "contributions": [
104 | "code",
105 | "bug"
106 | ]
107 | },
108 | {
109 | "login": "Barretem",
110 | "name": "Barretem",
111 | "avatar_url": "https://avatars2.githubusercontent.com/u/47966933?v=4",
112 | "profile": "https://github.com/Barretem",
113 | "contributions": [
114 | "code"
115 | ]
116 | },
117 | {
118 | "login": "GaryHjy",
119 | "name": "阿禹。",
120 | "avatar_url": "https://avatars1.githubusercontent.com/u/32995274?v=4",
121 | "profile": "https://github.com/GaryHjy",
122 | "contributions": [
123 | "doc"
124 | ]
125 | },
126 | {
127 | "login": "lujunwei",
128 | "name": "lujunwei",
129 | "avatar_url": "https://avatars0.githubusercontent.com/u/7427200?v=4",
130 | "profile": "https://github.com/lujunwei",
131 | "contributions": [
132 | "code"
133 | ]
134 | },
135 | {
136 | "login": "cjfff",
137 | "name": "cjf",
138 | "avatar_url": "https://avatars1.githubusercontent.com/u/20502762?v=4",
139 | "profile": "http://www.ccc1996.cn",
140 | "contributions": [
141 | "bug",
142 | "code"
143 | ]
144 | },
145 | {
146 | "login": "Jack-rainbow",
147 | "name": "Jack-rainbow",
148 | "avatar_url": "https://avatars1.githubusercontent.com/u/20368037?v=4",
149 | "profile": "https://github.com/Jack-rainbow",
150 | "contributions": [
151 | "bug"
152 | ]
153 | },
154 | {
155 | "login": "colmugx",
156 | "name": "ColMugX",
157 | "avatar_url": "https://avatars1.githubusercontent.com/u/21327913?v=4",
158 | "profile": "https://colmugx.github.io",
159 | "contributions": [
160 | "code"
161 | ]
162 | },
163 | {
164 | "login": "snowlocked",
165 | "name": "snowlocked",
166 | "avatar_url": "https://avatars0.githubusercontent.com/u/19562649?v=4",
167 | "profile": "https://github.com/snowlocked",
168 | "contributions": [
169 | "code",
170 | "doc"
171 | ]
172 | },
173 | {
174 | "login": "zcqno1",
175 | "name": "Sponge",
176 | "avatar_url": "https://avatars0.githubusercontent.com/u/11766057?v=4",
177 | "profile": "https://github.com/zcqno1",
178 | "contributions": [
179 | "bug",
180 | "code"
181 | ]
182 | },
183 | {
184 | "login": "gd4Ark",
185 | "name": "4Ark",
186 | "avatar_url": "https://avatars0.githubusercontent.com/u/27952659?v=4",
187 | "profile": "https://4ark.me",
188 | "contributions": [
189 | "code",
190 | "doc"
191 | ]
192 | },
193 | {
194 | "login": "Htongbing",
195 | "name": "Htongbing",
196 | "avatar_url": "https://avatars2.githubusercontent.com/u/36433396?v=4",
197 | "profile": "https://github.com/Htongbing",
198 | "contributions": [
199 | "code"
200 | ]
201 | },
202 | {
203 | "login": "PPPenny",
204 | "name": "PPPenny",
205 | "avatar_url": "https://avatars3.githubusercontent.com/u/20984729?v=4",
206 | "profile": "https://github.com/PPPenny",
207 | "contributions": [
208 | "code"
209 | ]
210 | },
211 | {
212 | "login": "zenghao1203",
213 | "name": "PopupDialog",
214 | "avatar_url": "https://avatars0.githubusercontent.com/u/22702128?v=4",
215 | "profile": "https://github.com/zenghao1203",
216 | "contributions": [
217 | "bug"
218 | ]
219 | },
220 | {
221 | "login": "Jogiter",
222 | "name": "Jogiter",
223 | "avatar_url": "https://avatars0.githubusercontent.com/u/9711036?v=4",
224 | "profile": "https://www.jogiter.cn/",
225 | "contributions": [
226 | "code"
227 | ]
228 | },
229 | {
230 | "login": "yolofit",
231 | "name": "yolofit",
232 | "avatar_url": "https://avatars.githubusercontent.com/u/20294811?v=4",
233 | "profile": "https://github.com/yolofit",
234 | "contributions": [
235 | "bug"
236 | ]
237 | },
238 | {
239 | "login": "huazaili",
240 | "name": "huazaili",
241 | "avatar_url": "https://avatars.githubusercontent.com/u/13534495?v=4",
242 | "profile": "https://github.com/huazaili",
243 | "contributions": [
244 | "bug"
245 | ]
246 | }
247 | ],
248 | "contributorsPerLine": 7,
249 | "skipCi": true
250 | }
251 |
--------------------------------------------------------------------------------
/.babelrc.js:
--------------------------------------------------------------------------------
1 | module.exports = api => {
2 | return {
3 | presets: [['@babel/env', {modules: api.env('test') ? 'commonjs' : false}]],
4 | plugins: [['@babel/transform-runtime']]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_style = space
8 | indent_size = 2
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | insert_final_newline = false
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/
2 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | browser: true,
5 | node: true
6 | },
7 | parserOptions: {
8 | parser: 'babel-eslint'
9 | },
10 | extends: [
11 | 'eslint:recommended',
12 | 'plugin:jest/recommended',
13 | 'plugin:vue/recommended',
14 | 'plugin:prettier/recommended',
15 | 'prettier/vue'
16 | ],
17 | plugins: ['vue', 'prettier'],
18 | rules: {
19 | 'no-console': [
20 | 'error',
21 | {
22 | allow: ['warn', 'error']
23 | }
24 | ],
25 | 'no-debugger': 'error',
26 | 'prettier/prettier': 'error'
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.github/badge.yml:
--------------------------------------------------------------------------------
1 | types:
2 | feat: 'enhancement'
3 | fix:
4 | hack: 'hack'
5 | default: 'bug'
6 | hack: 'hack'
7 | docs: 'documentation'
8 | refactor: 'refactor'
9 | style: 'style'
10 | test: 'test'
11 | perf: 'performance'
12 | chore:
13 | deps: 'dependencies'
14 | default: 'chore'
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | npm-debug.log*
4 | yarn-debug.log*
5 | yarn-error.log*
6 | dist
7 | docs/build
8 | docs/index.html
9 | docs/*.woff
10 | docs/*.ttf
11 |
12 | # Editor directories and files
13 | .idea
14 | .vscode
15 | *.suo
16 | *.ntvs*
17 | *.njsproj
18 | *.sln
19 | .env
20 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | docs
2 | dist
3 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | semi: false
2 | singleQuote: true
3 | bracketSpacing: false
4 |
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-standard",
3 | "rules": {
4 | "no-empty-source": null
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | branches:
2 | only:
3 | - master
4 | language: node_js
5 | node_js:
6 | - lts/*
7 | git:
8 | depth: 30
9 | install:
10 | - yarn --frozen-lockfile
11 | - yarn test
12 | script:
13 | - ./build.sh
14 | after_script:
15 | - ./notify.sh
16 | cache: yarn
17 | deploy:
18 | - provider: pages
19 | local-dir: docs
20 | github-token: $GITHUB_TOKEN
21 | skip-cleanup: true
22 | keep-history: true
23 | - provider: npm
24 | email: levy9527@qq.com
25 | api_key: $NPM_TOKEN
26 | skip-cleanup: true
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 FEMessage
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README-zh.md:
--------------------------------------------------------------------------------
1 | # el-data-table
2 |
3 | [](https://travis-ci.com/FEMessage/el-data-table)
4 | [](https://www.npmjs.com/package/@femessage/el-data-table)
5 | [](https://www.npmjs.com/package/@femessage/el-data-table)
6 | [](https://github.com/FEMessage/el-data-table/blob/master/LICENSE)
7 | [](https://github.com/FEMessage/el-data-table/pulls)
8 | [](https://github-tools.github.io/github-release-notes/)
9 |
10 | 使用`axios`自动发送请求,支持树形结构,支持分页,支持自定义查询, 自定义操作列, 让 RESTful 风格的 CRUD 更简单 👏
11 |
12 | 内置[@femessage/el-form-renderer](https://github.com/FEMessage/el-form-renderer)用于渲染表单
13 |
14 | 
15 |
16 | ## Table of Contents
17 |
18 | - [Introduction](#introduction)
19 | - [CRUD](#crud)
20 | - [数据驱动](#数据驱动)
21 | - [Why](#why)
22 | - [Feature](#feature)
23 | - [Links](#links)
24 | - [Install](#install)
25 | - [Quick Start](#quick-start)
26 | - [Global Register Component](#global-register-component)
27 | - [Template](#template)
28 | - [Reference](#reference)
29 | - [Contributing](#contributing)
30 | - [Contributors](#contributors)
31 | - [License](#license)
32 |
33 | ## Introduction
34 |
35 | ### CRUD
36 |
37 | el-data-table 就是为了解决业务问题而生的,故而封装了 CRUD 的逻辑在里面。
38 |
39 | 以用户接口示例,设其相对路径为:
40 |
41 | ```sh
42 | /api/v1/users
43 | ```
44 |
45 | 则其 restful CRUD 接口如下:
46 |
47 | - 查询
48 |
49 | ```sh
50 | GET /api/v1/users?page=1&size=10
51 | ```
52 |
53 | 默认数据结构
54 |
55 | ```js
56 | {
57 | "code":0,
58 | "msg":"ok",
59 | "payload":{
60 | "content":[], // dataPath
61 | "totalElements":2, // totalPath
62 | }
63 | }
64 | ```
65 |
66 | 可根据实际情况设置 dataPath/totalPath 两个字段的路径
67 | 如果接口不分页, 则传 hasPagination=false, 此时默认 dataPath 为 payload, 当然此时仍可以自定义
68 |
69 | - 新增
70 |
71 | ```sh
72 | POST /api/v1/users
73 | ```
74 |
75 | - 修改(编辑)
76 |
77 | ```sh
78 | PUT /api/v1/users/:id
79 | ```
80 |
81 | - 删除
82 |
83 | ```sh
84 | DELETE /api/v1/users/:id
85 | ```
86 |
87 | 则只需要使用以下代码,即可完成 CRUD 功能
88 |
89 | ```vue
90 |
91 |
92 |
93 | ```
94 |
95 | ```js
96 |
140 | ```
141 |
142 | 效果如下:
143 |
144 | - 查询
145 |
146 | 
147 |
148 | 
149 |
150 | - 新增
151 |
152 | 
153 |
154 | - 修改
155 |
156 | 
157 |
158 | - 删除
159 |
160 | 
161 |
162 | [⬆ Back to Top](#table-of-contents)
163 |
164 | ### 数据驱动
165 |
166 | 把 template 的内容移动到 script 中, 意味着 template 可以精简,js 可以抽取出来,方便复用;同时,js 里的数据其实就是一段 json,这也让代码生成工具有了用武之地。
167 |
168 | [⬆ Back to Top](#table-of-contents)
169 |
170 | ### Why
171 |
172 | 为什么要在 element-ui 的 el-table 的基础上封装一个 el-data-table?
173 |
174 | 我常听到有以下几种声音:
175 |
176 | 1. el-table 已可以覆盖大部分场景,暂无扩展需求
177 | 2. 封装了这么多东西,耦合太严重了
178 | 3. 涉及过多的业务逻辑,有点僵化,业务操作还是交给开发者去处理
179 |
180 | 首先 el-table 的确很灵活,只不过,在实现分页请求的时候,仅有 el-table 还不够,还需要组合 el-pagination 组件来实现。而分页处理的内容大多都是重复的,如果不封装,只会产生冗余的代码。
181 |
182 | 而中后台太多都是 CRUD 的操作,结合 restful API,使用得只传一个 url 让组件做 CRUD 成为了可能。
183 |
184 | 其次,很多有经验的“老手”觉得组件越灵活越好。
185 |
186 | 但对于经验尚浅的“新手”,他们并不熟悉常见的业务场景,对一些基本操作,如果表单校验,空格过滤,添加 loading,异常处理,他们只会漏掉,而这正是产生 bug 的源头。
187 |
188 | 对于一线的业务开发人员而言,面对做不完的业务,其实他们并不想去处理重复的业务逻辑,他们只想解放双手,早点下班。
189 |
190 | 正是在这样的背景下,产生了 el-data-table。
191 |
192 | [⬆ Back to Top](#table-of-contents)
193 |
194 | ## Feature
195 |
196 | - 只需进行 json 配置,即可实现 restful 风格的 CRUD 四个接口的对接
197 | - 支持表格内展示树形结构数据(该功能 element-ui 官方是不支持的)
198 | - 自带分页逻辑
199 | - 可扩展自定义列按钮,以及自定义操作函数
200 | - 支持分页查询后,点击详情再返回,恢复上一次的查询状态
201 |
202 | [⬆ Back to Top](#table-of-contents)
203 |
204 | ## Links
205 |
206 | - [docs](https://FEMessage.github.io/el-data-table/)
207 | - [fem-vscode-helper](https://marketplace.visualstudio.com/items?itemName=FEMessage.fem-vscode-helper)
208 |
209 | [⬆ Back to Top](#table-of-contents)
210 |
211 | ## Install
212 |
213 | encourage using [yarn](https://yarnpkg.com/en/docs/install#mac-stable) to install
214 |
215 | ```sh
216 | yarn add @femessage/el-data-table
217 | ```
218 |
219 | [⬆ Back to Top](#table-of-contents)
220 |
221 | ## Quick Start
222 |
223 | ### Global Register Component
224 |
225 | this is for minification reason: in this way building your app,
226 |
227 | webpack or other bundler just bundle the dependencies into one vendor for all pages which using this component,
228 |
229 | instead of one vendor for one page
230 |
231 | ```js
232 | import Vue from 'vue'
233 |
234 | // register component and loading directive
235 | import ElDataTable from '@femessage/el-data-table'
236 | import ElFormRenderer from '@femessage/el-form-renderer'
237 | import {
238 | Button,
239 | Dialog,
240 | Form,
241 | FormItem,
242 | Loading,
243 | Pagination,
244 | Table,
245 | TableColumn,
246 | Message,
247 | MessageBox
248 | } from 'element-ui'
249 |
250 | Vue.use(Button)
251 | Vue.use(Dialog)
252 | Vue.use(Form)
253 | Vue.use(FormItem)
254 | Vue.use(Loading.directive)
255 | Vue.use(Pagination)
256 | Vue.use(Table)
257 | Vue.use(TableColumn)
258 | Vue.component('el-form-renderer', ElFormRenderer)
259 | Vue.component('el-data-table', ElDataTable)
260 |
261 | // to show confirm before delete
262 | Vue.prototype.$confirm = MessageBox.confirm
263 |
264 | // show tips
265 | Vue.prototype.$message = Message
266 |
267 | // if the table component cannot access `this.$axios`, it cannot send request
268 | import axios from 'axios'
269 | Vue.prototype.$axios = axios
270 | ```
271 |
272 | ### Template
273 |
274 | ```vue
275 |
276 |
277 |
278 | ```
279 |
280 | [⬆ Back to Top](#table-of-contents)
281 |
282 | ## Reference
283 |
284 | - [form rules detail see async-validator](https://github.com/yiminghe/async-validator)
285 | - [el-input enter to submit](https://github.com/ElemeFE/element/pull/5920)
286 | - [html spec form submission](https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2)
287 | - [What_is_a_URL](https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/What_is_a_URL)
288 | - [History_API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)
289 | - [encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
290 | - [RegExp](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp)
291 | - [从 vue-router 看前端路由的两种实现](https://zhuanlan.zhihu.com/p/27588422)
292 | - [peer-dependencies](https://nodejs.org/en/blog/npm/peer-dependencies/)
293 |
294 | [⬆ Back to Top](#table-of-contents)
295 |
296 | ## Contributing
297 |
298 | For those who are interested in contributing to this project, such as:
299 |
300 | - report a bug
301 | - request new feature
302 | - fix a bug
303 | - implement a new feature
304 |
305 | Please refer to our [contributing guide](https://github.com/FEMessage/.github/blob/master/CONTRIBUTING.md).
306 |
307 | [⬆ Back to Top](#table-of-contents)
308 |
309 | ## Contributors
310 |
311 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
320 |
321 | ## License
322 |
323 | [MIT](./LICENSE)
324 |
325 | [⬆ Back to Top](#table-of-contents)
326 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # el-data-table
2 |
3 | [](https://travis-ci.com/FEMessage/el-data-table)
4 | [](https://www.npmjs.com/package/@femessage/el-data-table)
5 | [](https://www.npmjs.com/package/@femessage/el-data-table)
6 | [](https://github.com/FEMessage/el-data-table/blob/master/LICENSE)
7 | [](https://github.com/FEMessage/el-data-table/pulls)
8 | [](https://github-tools.github.io/github-release-notes/)
9 |
10 | Auto requesting by `axios`, supports pagination, tree data structure, custom search, custom operation column, which makes rest api easily👏
11 |
12 | The table uses [@femessage/el-form-renderer](https://github.com/FEMessage/el-form-renderer) to render form.
13 |
14 | 
15 |
16 | [中文文档](./README-zh.md)
17 |
18 | ## Table of Contents
19 |
20 | - [Introduction](#introduction)
21 | - [CRUD](#crud)
22 | - [Data Driven](#data-driven)
23 | - [Why](#why)
24 | - [Feature](#feature)
25 | - [Links](#links)
26 | - [Install](#install)
27 | - [Quick Start](#quick-start)
28 | - [Global Register Component](#global-register-component)
29 | - [Template](#template)
30 | - [Reference](#reference)
31 | - [Contributing](#contributing)
32 | - [Contributors](#contributors)
33 | - [License](#license)
34 |
35 | ## Introduction
36 |
37 | ### CRUD
38 |
39 | el-data-table is created to solve business problems, so CRUD logic is set inside.
For example, to develop `user` api, suppose its relative path like this:
40 |
41 | ```javascript
42 | /api/v1/users
43 | ```
44 |
45 | The restful CRUD api should be:
46 |
47 | - Retrieve
48 |
49 | ```javascript
50 | GET /api/v1/users?page=1&size=10
51 | ```
52 |
53 | default data structure
54 |
55 | ```js
56 | {
57 | "code":0,
58 | "msg":"ok",
59 | "payload":{
60 | "content":[], // dataPath
61 | "totalElements":2, // totalPath
62 | }
63 | }
64 | ```
65 |
66 | You can customize dataPath/totalPath.
67 |
68 | If `hasPagination=false`, default dataPath is `payload`
69 |
70 | - Create
71 |
72 | ```javascript
73 | POST / api / v1 / users
74 | ```
75 |
76 | - Update
77 |
78 | ```javascript
79 | PUT /api/v1/users/:id
80 | ```
81 |
82 | - Delete
83 |
84 | ```javascript
85 | DELETE /api/v1/users/:id
86 | ```
87 |
88 | Then only need to use the following code to complete CRUD functions
89 |
90 | ```html
91 |
92 |
93 |
94 | ```
95 |
96 | ```javascript
97 |
141 | ```
142 |
143 | The results are as follows:
144 |
145 | - Retrieve
146 | 

147 |
148 | - Create
149 | 
150 |
151 | - Update
152 | 
153 |
154 | - Delete
155 | 
156 |
157 | [⬆Back to Top](#table-of-contents)
158 |
159 | ### Data Driven
160 |
161 | Moving the content of the template to the script means that the template can be reduced and js can be extracted to another file to reuse.
162 | At the same time, the data in js is actually a piece of json, this means code generation tool can help.
163 |
164 | 


165 |
166 | [⬆Back to Top](#table-of-contents)
167 |
168 | ### Why
169 |
170 | Why do you create el-data-table based on el-table of element-ui?
171 |
172 | I often hear the following sounds:
173 |
174 | 1. el-table can cover most scenarios without extended requirements
175 | 2. wrap up so many things, it's heavy and high coupling
176 | 3. bound with too many business logic, it's not flexible; business logic should handle by developers
177 |
178 | First of all, I have to say, el-table is really flexible, but when implementing paging requests, only el-table is not enough, and the el-pagination component needs to be combined. Most of the content of paging processing is repeated. Without a high level business component, we get duplicate code everywhere.
179 |
180 | In fact, in the admin or dashboard web app, there are many CRUD operations, using restful API. It is possible to use only one url to make a component to complete CRUD functions.
181 |
182 | Secondly, many experienced developers think that components are the more flexible the better.
183 |
184 | However, for the "newbees" who lack of experience, they are not familiar with common business scenarios. Some basic operations, like form validation, space filtering, adding loading, exception handling, they may forget, which result in bugs.
185 |
186 | For front-line business developers, in the face of endless developing task, in fact, they don't want to deal with repeated business logic. they just want to free their hands and get off work early.
187 |
188 | In such situation, el-data-table was born.
189 |
190 | [⬆Back to Top](#table-of-contents)
191 |
192 | ## Feature
193 |
194 | - Use configuration to call restful api to complete CRUD functions
195 | - Support table display tree structure data
196 | - Bound with pagination logic
197 | - Support custom column buttons, and custom operation functions
198 | - Support saving query on url, which can resotre search status after history.go(-1) or location.reload()
199 |
200 | [⬆Back to Top](#table-of-contents)
201 |
202 | ## Links
203 |
204 | - [docs](https://FEMessage.github.io/el-data-table/)
205 | - [fem-vscode-helper](https://marketplace.visualstudio.com/items?itemName=FEMessage.fem-vscode-helper)
206 |
207 | [⬆ Back to Top](#table-of-contents)
208 |
209 | ## Install
210 |
211 | Encourage using [Yarn](https://yarnpkg.com/en/docs/install#mac-stable) to install
212 |
213 | ```sh
214 | yarn add @femessage/el-data-table
215 | ```
216 |
217 | [⬆Back to Top](#table-of-contents)
218 |
219 | ## Quick Start
220 |
221 | ### Global Register Component
222 |
223 | This is for minification reason: in this way building your app, webpack or other bundler just bundle the dependencies into one vendor for all pages which using this component, instead of one vendor for one page
224 |
225 | ```javascript
226 | import Vue from 'vue'
227 | // register component and loading directive
228 | import ElDataTable from '@femessage/el-data-table'
229 | import ElFormRenderer from '@femessage/el-form-renderer'
230 | import {
231 | Button,
232 | Dialog,
233 | Form,
234 | FormItem,
235 | Loading,
236 | Pagination,
237 | Table,
238 | TableColumn,
239 | Message,
240 | MessageBox
241 | } from 'element-ui'
242 | Vue.use(Button)
243 | Vue.use(Dialog)
244 | Vue.use(Form)
245 | Vue.use(FormItem)
246 | Vue.use(Loading.directive)
247 | Vue.use(Pagination)
248 | Vue.use(Table)
249 | Vue.use(TableColumn)
250 | Vue.component('el-form-renderer', ElFormRenderer)
251 | Vue.component('el-data-table', ElDataTable)
252 | // to show confirm before delete
253 | Vue.prototype.$confirm = MessageBox.confirm
254 | // show tips
255 | Vue.prototype.$message = Message
256 | // if the table component cannot access `this.$axios`, it cannot send request
257 | import axios from 'axios'
258 | Vue.prototype.$axios = axios
259 | ```
260 |
261 | ### Template
262 |
263 | ```vue
264 |
265 |
266 |
267 | ```
268 |
269 | [⬆Back to Top](#table-of-contents)
270 |
271 | ## Reference
272 |
273 | - [form rules detail see asynchronc-veriator](https://github.com/yiminghe/async-validator)
274 | - [ll-input enter to submit](https://github.com/ElemeFE/element/pull/5920)
275 | - [html spec form submission](https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2)
276 | - [what_is_a_URL](https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/What_is_a_URL)
277 | - [history_API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)
278 | - [encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
279 | - [regExp](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp)
280 | - [routing implementations details in vue-router](https://zhuanlan.zhihu.com/p/27588422)
281 | - [peer-dependencies](https://nodejs.org/en/blog/npm/peer-dependencies/)
282 |
283 | [⬆Back to Top](#table-of-contents)
284 |
285 | ## Contributing
286 |
287 | For those who are interested in contributing to this project, such as:
288 |
289 | - report a bug
290 | - request new feature
291 | - fix a bug
292 | - implement a new feature
293 |
294 | Please refer to our [contributing guide](https://github.com/FEMessage/.github/blob/master/CONTRIBUTING.md).
295 |
296 | [⬆ Back to Top](#table-of-contents)
297 |
298 | ## Contributors
299 |
300 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
301 |
302 |
303 |
304 |
305 |
339 |
340 |
341 |
342 |
343 |
344 |
345 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
346 |
347 | ## License
348 |
349 | [MIT](https://www.yuque.com/deepexi-serverless/onx52o/LICENSE)
350 |
351 | [⬆Back to Top](#table-of-contents)
352 |
--------------------------------------------------------------------------------
/assets/image-20181106222453747.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FEMessage/el-data-table/899acd50f84a9878c539298a0f34fe617afd4973/assets/image-20181106222453747.png
--------------------------------------------------------------------------------
/assets/image-20181106224258372.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FEMessage/el-data-table/899acd50f84a9878c539298a0f34fe617afd4973/assets/image-20181106224258372.png
--------------------------------------------------------------------------------
/assets/image-20181106224933515.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FEMessage/el-data-table/899acd50f84a9878c539298a0f34fe617afd4973/assets/image-20181106224933515.png
--------------------------------------------------------------------------------
/assets/image-20181106225421654.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FEMessage/el-data-table/899acd50f84a9878c539298a0f34fe617afd4973/assets/image-20181106225421654.png
--------------------------------------------------------------------------------
/assets/image-20181106230058138.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FEMessage/el-data-table/899acd50f84a9878c539298a0f34fe617afd4973/assets/image-20181106230058138.png
--------------------------------------------------------------------------------
/assets/image-20181106231010055.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FEMessage/el-data-table/899acd50f84a9878c539298a0f34fe617afd4973/assets/image-20181106231010055.png
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | yarn stdver
3 |
4 | yarn build
5 |
--------------------------------------------------------------------------------
/build/rollup.config.js:
--------------------------------------------------------------------------------
1 | // rollup.config.js
2 | import vue from 'rollup-plugin-vue'
3 | import babel from 'rollup-plugin-babel'
4 | import commonjs from 'rollup-plugin-commonjs'
5 | import {terser} from 'rollup-plugin-terser'
6 | import minimist from 'minimist'
7 |
8 | const argv = minimist(process.argv.slice(2))
9 |
10 | const config = {
11 | input: 'src/index.js',
12 | output: {
13 | name: 'ElDataTable',
14 | exports: 'named'
15 | },
16 | plugins: [
17 | commonjs(),
18 | vue({
19 | css: true,
20 | compileTemplate: true
21 | }),
22 | babel({
23 | runtimeHelpers: true,
24 | exclude: 'node_modules/**'
25 | })
26 | ]
27 | }
28 |
29 | // Only minify browser (iife) version
30 | if (argv.format === 'iife') {
31 | config.plugins.push(terser())
32 | }
33 |
34 | export default config
35 |
--------------------------------------------------------------------------------
/docs/axios-config.md:
--------------------------------------------------------------------------------
1 | axiosConfig 示例代码,打开控制台,可以看到请求中带上了自定义的头
2 |
3 | ```vue
4 |
5 |
6 |
7 |
53 | ```
54 |
--------------------------------------------------------------------------------
/docs/basic.md:
--------------------------------------------------------------------------------
1 | 基本用法,包含crud
2 |
3 | ```vue
4 |
5 |
6 |
7 |
70 | ```
71 |
--------------------------------------------------------------------------------
/docs/before-confirm.md:
--------------------------------------------------------------------------------
1 | 自定义新增、修改请求前的操作
2 |
3 | ```vue
4 |
5 |
6 |
7 |
8 |
61 | ```
62 |
--------------------------------------------------------------------------------
/docs/before-search.md:
--------------------------------------------------------------------------------
1 | 搜索前的操作
2 |
3 | ```vue
4 |
5 |
6 |
7 |
34 | ```
35 |
--------------------------------------------------------------------------------
/docs/can-search-collapse.md:
--------------------------------------------------------------------------------
1 | search表单可以折叠、展开
2 |
3 | ```vue
4 |
5 |
6 | slot header button
7 |
8 |
9 |
32 | ```
33 |
--------------------------------------------------------------------------------
/docs/clear-selection.md:
--------------------------------------------------------------------------------
1 | 使用clearSelection清空多选项;使用toggleRowSelection切换、设置行是否选中
2 |
3 | ```vue
4 |
5 |
6 |
7 |
selected: {{selected}}
8 |
选择
9 |
取消选择
10 |
11 |
12 |
43 | ```
44 |
--------------------------------------------------------------------------------
/docs/custom-text.md:
--------------------------------------------------------------------------------
1 | 自定义新增、修改、删除按钮以及删除提示框的文案
2 |
3 | ```vue
4 |
5 |
6 |
7 |
48 | ```
49 |
--------------------------------------------------------------------------------
/docs/expand.md:
--------------------------------------------------------------------------------
1 | 展开表格列
2 |
3 | ```vue
4 |
5 |
8 |
9 |
10 |
11 |
12 | {{ row.date }}
13 |
14 |
15 | {{ row.name }}
16 |
17 |
18 | {{ row.address }}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
42 | ```
43 |
--------------------------------------------------------------------------------
/docs/extra-body.md:
--------------------------------------------------------------------------------
1 | 新增、修改请求附带额外参数
2 |
3 | ```vue
4 |
5 |
6 |
7 |
38 | ```
39 |
--------------------------------------------------------------------------------
/docs/extra-buttons.md:
--------------------------------------------------------------------------------
1 | 自定义操作列按钮
2 |
3 | ```vue
4 |
5 |
6 |
7 |
31 | ```
32 |
--------------------------------------------------------------------------------
/docs/extra-query.sync.md:
--------------------------------------------------------------------------------
1 | extraQuery用sync修饰时,点击重置按钮也会重置extraQuery
2 |
3 | ```vue
4 |
5 |
16 |
17 | slot=search
18 |
19 |
20 |
21 |
22 |
53 | ```
54 |
--------------------------------------------------------------------------------
/docs/faq.md:
--------------------------------------------------------------------------------
1 | ## 获取组件内的el-table实例
2 |
3 | ```html
4 |
5 |
6 |
7 |
14 | ```
15 |
16 | ## 手动刷新el-data-table
17 |
18 | ```javascript
19 | this.$refs.dataTable.getList()
20 | ```
21 |
22 | ## 自己实现 delete 操作,同时实现删除最后一页时,返回正确的最后一页
23 |
24 | ### 场景
25 | 1. 因为业务需求,data-table 默认的删除确认框不满足需求
26 | 2. 自己在外部使用 extra-buttons 实现 delete 操作
27 | 3. 遇到了[最后一页删到空,页码出现错误](https://github.com/FEMessage/el-data-table/issues/223)的问题
28 |
29 | ### 解决方案
30 | 1. 自己实现删除操作
31 | 2. 调用 correctPage 判断是否返回正确的最后一页
32 | 3. 调用 getList 刷新列表
33 | ```html
34 |
35 |
36 |
37 |
38 |
63 | ```
64 |
65 | ## 查询后刷新
66 |
67 | ### 场景
68 | 

69 |
70 |
71 | ### 解决方案
72 | 把select option的value变成字符串类型
73 |
74 | ### 原有代码
75 |
76 | ```javascript
77 | searchForm: [
78 | {
79 | el: {placeholder: '请选择'},
80 | label: '状态',
81 | id: 'status',
82 | type: 'select',
83 | options: [
84 | {
85 | value: 1,
86 | label: '待处理'
87 | },
88 | ]
89 | }
90 | ],
91 | ```
92 |
93 | ### 改动后代码
94 |
95 | ```javascript
96 | searchForm: [
97 | {
98 | el: {placeholder: '请选择'},
99 | label: '状态',
100 | id: 'status',
101 | type: 'select',
102 | options: [
103 | {
104 | value: '1', // 修改了这一行
105 | label: '待处理'
106 | },
107 | ]
108 | }
109 | ],
110 | ```
111 |
112 | ## 弹窗关闭时清空选中状态
113 |
114 | ### 场景
115 | el-data-table 在 el-dialog 中展示,在 el-dialog 关闭后,清空 el-data-table 的选中状态。
116 |
117 | ### 解决方案
118 | 
119 |
120 | ```javascript
121 | cancelRelation() {
122 | this.showRelationDialog = false
123 | this.$refs.outsideModuleTable.clearSelection()
124 | }
125 | ```
126 |
127 | ## searchForm 部分内容重置失效
128 | ### 场景
129 | 两个 data-table 在同一个页面使用时,搜索栏的重置按钮不起作用
130 | ```html
131 |
132 |
133 | ```
134 | ### 解决方案
135 | 在el-data-table上使用key属性规避此问题。
136 | ```html
137 |
138 |
139 | ```
140 | ### 原始issue
141 | [https://github.com/FEMessage/el-data-table/issues/119](https://github.com/FEMessage/el-data-table/issues/119)
142 |
143 | ## 点击 el-form 内部按钮触发页面刷新
144 |
145 | ### 场景
146 |
147 | el-form 包裹 el-data-table 时,点击 el-data-table 的操作列按钮会触发 form submit 的默认行为,导致页面刷新一次。
148 |
149 | ```html
150 |
151 |
152 |
153 | ```
154 |
155 | ### 解决方案
156 |
157 | 在 el-form 上增加一个禁用 submit 默认行为的事件。
158 |
159 | ```html
160 |
163 |
164 |
165 | ```
166 |
167 | ### 参考链接
168 | [W3C Form Submission](https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2)
169 |
170 | [element-ui el-form 文档](https://element.eleme.cn/#/zh-CN/component/form)
171 |
172 | [issue #224](https://github.com/FEMessage/el-data-table/issues/224)
173 |
174 | ## 在 TypeScript 中指定组件的类型
175 |
176 | ```html
177 |
186 | ```
187 | > 关于更多可用类型请参考:[el-data-table.d.ts](https://github.com/FEMessage/el-data-table/blob/dev/src/el-data-table.d.ts)
188 |
--------------------------------------------------------------------------------
/docs/first-page.md:
--------------------------------------------------------------------------------
1 | 接口第一页页数为0
2 |
3 | ```vue
4 |
5 |
6 |
7 |
38 | ```
39 |
--------------------------------------------------------------------------------
/docs/formatter.md:
--------------------------------------------------------------------------------
1 | formatter 可以返回 jsx 渲染功能更丰富的单元格
2 |
3 | ```vue
4 |
5 |
15 |
16 |
17 |
53 | ```
54 |
--------------------------------------------------------------------------------
/docs/guide-contributing-correctly.md:
--------------------------------------------------------------------------------
1 | # 正确地为组件贡献
2 |
3 | ## 关于按钮大小
4 |
5 | 我们使用 `prop.buttonSize` 统一控制按钮大小.
6 |
7 | 因此, 在开发或贡献的时候有需要添加新的按钮的情况, 需要使用 `buttonSize` 来控制, 使得风格统一.
8 |
9 | 例如这样写:
10 |
11 | ```html
12 | 新增的按钮
13 | ```
--------------------------------------------------------------------------------
/docs/has-pagination=false.md:
--------------------------------------------------------------------------------
1 | 不分页,设置has-pagination="false"即可,此时接口传参page=-1
2 |
3 | ```vue
4 |
5 |
6 |
7 |
38 | ```
39 |
--------------------------------------------------------------------------------
/docs/header-buttons.md:
--------------------------------------------------------------------------------
1 | 自定义头部按钮
2 |
3 | ```vue
4 |
5 |
6 |
7 |
8 |
56 |
57 | ```
58 |
--------------------------------------------------------------------------------
/docs/id.md:
--------------------------------------------------------------------------------
1 | 自定义主键,点击删除按钮,查看网络请求
2 |
3 | ```vue
4 |
5 |
8 |
9 |
10 |
42 | ```
43 |
--------------------------------------------------------------------------------
/docs/is-tree.md:
--------------------------------------------------------------------------------
1 | 树形结构
2 |
3 | ```vue
4 |
5 |
6 |
7 |
50 | ```
51 |
--------------------------------------------------------------------------------
/docs/multi-level-header.md:
--------------------------------------------------------------------------------
1 | 只需要在columns子项里嵌套columns数组,就可以实现多级表头
2 |
3 | **二级**
4 | ```vue
5 |
6 |
7 |
8 |
52 | ```
53 |
54 | **更多级**
55 | ```vue
56 |
57 |
58 |
59 |
109 | ```
110 |
--------------------------------------------------------------------------------
/docs/on-default-delete.md:
--------------------------------------------------------------------------------
1 | 有时候,el-data-table 内置删除按钮的形式、数量不满足用户需求。那么用户可以在合适的时机自行调用内部方法来删除。
2 | 下面的例子就是在多选的情况补回行删除按钮
3 |
4 | ```vue
5 |
6 |
7 |
8 |
33 | ```
34 |
--------------------------------------------------------------------------------
/docs/on-new-edit-delete.md:
--------------------------------------------------------------------------------
1 | 新增、编辑、删除钩子
2 |
3 | ```vue
4 |
5 |
6 |
默认情况下:
7 |
8 | - 新增是 POST url body 的格式
9 | - 修改是 PUT url/id body 的格式
10 | - 删除多个的请求地址是 DELETE url/id,id,id 的形式
11 |
12 |
当不满足需求时, 可通过 onNew、onEdit、onDelete 方法定制
13 |
19 |
20 |
21 |
22 |
80 | ```
81 |
--------------------------------------------------------------------------------
/docs/on-response.md:
--------------------------------------------------------------------------------
1 | 处理请求返回的数据,需要返回 total 与 data, 如果有此函数,则会忽略 totalPath/dataPath
2 |
3 | ```vue
4 |
5 |
6 |
7 |
28 | ```
29 |
--------------------------------------------------------------------------------
/docs/on-success.md:
--------------------------------------------------------------------------------
1 | 自定义操作成功后的逻辑
2 |
3 | ```vue
4 |
5 |
6 |
7 |
45 | ```
46 |
--------------------------------------------------------------------------------
/docs/persist-selection.md:
--------------------------------------------------------------------------------
1 | 选中效果在翻页后仍维持
2 |
3 | ```vue
4 |
5 |
6 |
7 |
25 | ```
26 |
--------------------------------------------------------------------------------
/docs/save-query.md:
--------------------------------------------------------------------------------
1 | 通过saveQuery控制页面中只有一个table使用url来保存query参数。saveQuery默认为true。
2 | 以下示例中,第一个table会saveQuery为true, 第二个saveQuery为false
3 |
4 | ```vue
5 |
6 |
7 |
8 |
9 |
10 |
11 |
49 | ```
50 |
--------------------------------------------------------------------------------
/docs/search-immediately.md:
--------------------------------------------------------------------------------
1 | 表单项变更时, 立即获取新的表格数据
2 |
3 | ```vue
4 |
5 |
6 |
7 |
36 | ```
37 |
--------------------------------------------------------------------------------
/docs/search-item-collapsible.md:
--------------------------------------------------------------------------------
1 | search表单折叠并且设置部分总是可见
2 |
3 | ```vue
4 |
5 |
6 |
7 |
76 | ```
77 |
--------------------------------------------------------------------------------
/docs/slot-form.md:
--------------------------------------------------------------------------------
1 | form插槽用法
2 |
3 | ```vue
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
42 | ```
43 |
--------------------------------------------------------------------------------
/docs/slot-header.md:
--------------------------------------------------------------------------------
1 | header插槽,作用域传入selected数组
2 |
3 | ```vue
4 |
5 |
8 |
9 | slot=header{{selected.length}}
10 |
11 |
12 | 更多菜单
13 |
14 |
15 | 黄金糕
16 | 狮子头
17 | 螺蛳粉
18 | 双皮奶
19 | 蚵仔煎
20 |
21 |
22 |
23 |
24 |
25 |
39 | ```
40 |
--------------------------------------------------------------------------------
/docs/slot-no-data.md:
--------------------------------------------------------------------------------
1 | slot=no-data, 只在第一次请求获取数据为空时显示
2 |
3 | ```vue
4 |
5 |
6 |
7 | 没有数据,请去添加数据
8 |
9 |
10 |
11 |
25 |
35 | ```
36 |
--------------------------------------------------------------------------------
/docs/slot-operation.md:
--------------------------------------------------------------------------------
1 | operation插槽,作用域传入当前行 row
2 |
3 | ```vue
4 |
5 |
8 |
9 | 点击查看控制台
10 |
11 |
12 | 更多菜单
13 |
14 |
15 | 黄金糕
16 | 狮子头
17 | 螺蛳粉
18 | 双皮奶
19 | 蚵仔煎
20 |
21 |
22 |
23 |
24 |
25 |
55 | ```
56 |
--------------------------------------------------------------------------------
/docs/slot-search.md:
--------------------------------------------------------------------------------
1 | search插槽
2 |
3 | ```vue
4 |
5 |
6 |
7 | slot=search
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
50 | ```
51 |
--------------------------------------------------------------------------------
/docs/table-props-events.md:
--------------------------------------------------------------------------------
1 | 通过 tableAttrs & tableEventHandlers 属性,可以直接传 prop 和 eventHandler 到 el-table 本体上
2 |
3 | ```vue
4 |
5 |
6 |
7 |
33 | ```
34 |
--------------------------------------------------------------------------------
/netlify.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "is netlify: $NETLIFY"
3 | echo "in branch: $BRANCH"
4 | echo "head: $HEAD"
5 |
6 | if [ "$NETLIFY" != "true" ]
7 | then
8 | echo "this script only runs in netlify, bye"
9 | exit 1
10 | fi
11 |
12 | if [ "$BRANCH" != "dev" ] && [ "$HEAD" != "dev" ]
13 | then
14 | yarn doc
15 | else
16 | echo "this script only runs in targeting dev's PR deploy preview, bye"
17 | fi
18 |
--------------------------------------------------------------------------------
/notify.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | if [ "$TRAVIS_TEST_RESULT" != "0" ]
3 | then
4 | echo "build not success, bye"
5 | exit 1
6 | fi
7 |
8 | ORG_NAME=$(echo "$TRAVIS_REPO_SLUG" | cut -d '/' -f 1)
9 | REPO_NAME=$(echo "$TRAVIS_REPO_SLUG" | cut -d '/' -f 2)
10 |
11 | git remote add github https://$GITHUB_TOKEN@github.com/$TRAVIS_REPO_SLUG.git > /dev/null 2>&1
12 | git push github HEAD:master --follow-tags
13 |
14 | GREN_GITHUB_TOKEN=$GITHUB_TOKEN yarn release
15 |
16 | url=https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/latest
17 | resp_tmp_file=resp.tmp
18 |
19 | curl -H "Authorization: token $GITHUB_TOKEN" $url > $resp_tmp_file
20 |
21 | html_url=$(sed -n 5p $resp_tmp_file | sed 's/\"html_url\"://g' | awk -F '"' '{print $2}')
22 | body=$(grep body < $resp_tmp_file | sed 's/\"body\"://g;s/\"//g')
23 | version=$(echo $html_url | awk -F '/' '{print $NF}')
24 |
25 | msg='{"msgtype": "markdown", "markdown": {"title": "'$REPO_NAME'更新", "text": "@所有人\n# ['$REPO_NAME'('$version')]('$html_url')\n'$body'"}}'
26 |
27 | curl -X POST https://oapi.dingtalk.com/robot/send\?access_token\=$DINGTALK_ROBOT_TOKEN -H 'Content-Type: application/json' -d "$msg"
28 |
29 | rm $resp_tmp_file
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@femessage/el-data-table",
3 | "version": "1.2.1",
4 | "description": "base on element-ui, makes crud easily",
5 | "author": "https://github.com/FEMessage",
6 | "license": "MIT",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/FEMessage/el-data-table.git"
10 | },
11 | "keywords": [
12 | "vue",
13 | "element-ui",
14 | "table",
15 | "data-table",
16 | "element table"
17 | ],
18 | "files": [
19 | "src",
20 | "dist"
21 | ],
22 | "main": "dist/el-data-table.umd.js",
23 | "module": "dist/el-data-table.esm.js",
24 | "unpkg": "dist/el-data-table.min.js",
25 | "browser": {
26 | "./sfc": "src/el-data-table.vue"
27 | },
28 | "types": "src/el-data-table.d.ts",
29 | "scripts": {
30 | "test": "jest --verbose",
31 | "dev": "vue-styleguidist server",
32 | "doc": "vue-styleguidist build",
33 | "build": "npm run build:unpkg & npm run build:es & npm run build:umd & npm run doc",
34 | "build:umd": "rollup --config build/rollup.config.js --format umd --file dist/el-data-table.umd.js",
35 | "build:es": "rollup --config build/rollup.config.js --format es --file dist/el-data-table.esm.js",
36 | "build:unpkg": "rollup --config build/rollup.config.js --format iife --file dist/el-data-table.min.js",
37 | "stdver": "standard-version -m '[skip ci] chore(release): v%s'",
38 | "lint": "eslint \"**/*.@(js|vue)\" --fix",
39 | "release": "gren release --override"
40 | },
41 | "dependencies": {
42 | "lodash.get": "^4.4.2",
43 | "lodash.isempty": "^4.4.0",
44 | "lodash.kebabcase": "^4.1.1",
45 | "lodash.values": "^4.3.0"
46 | },
47 | "devDependencies": {
48 | "@babel/core": "^7.4.3",
49 | "@babel/plugin-transform-runtime": "^7.4.3",
50 | "@babel/preset-env": "^7.4.3",
51 | "@femessage/el-form-renderer": "^1.6.0",
52 | "@femessage/github-release-notes": "^0.19.0",
53 | "@femessage/types": "^1.0.3",
54 | "axios": "^0.19.0",
55 | "babel-eslint": "^10.0.3",
56 | "babel-loader": "^8.0.5",
57 | "element-ui": "2.4.11",
58 | "eslint": "^6.6.0",
59 | "eslint-config-prettier": "^6.5.0",
60 | "eslint-plugin-jest": "^23.0.2",
61 | "eslint-plugin-prettier": "^3.1.1",
62 | "eslint-plugin-vue": "^6.0.0",
63 | "file-loader": "^3.0.1",
64 | "glob": "^7.1.3",
65 | "husky": "1.3.1",
66 | "jest": "^24.8.0",
67 | "less": "^3.9.0",
68 | "less-loader": "^5.0.0",
69 | "lint-staged": "^8.1.0",
70 | "minimist": "^1.2.0",
71 | "prettier": "1.18.2",
72 | "rollup": "^1.9.0",
73 | "rollup-plugin-babel": "^4.3.2",
74 | "rollup-plugin-commonjs": "^9.3.4",
75 | "rollup-plugin-terser": "^4.0.4",
76 | "rollup-plugin-vue": "^4.7.2",
77 | "standard-version": "^6.0.1",
78 | "stylelint": "^9.10.0",
79 | "stylelint-config-standard": "^18.2.0",
80 | "vue": "^2.6.10",
81 | "vue-loader": "^15.7.1",
82 | "vue-styleguidist": "^3.16.3",
83 | "vue-template-compiler": "^2.5.16",
84 | "webpack": "^4.29.6"
85 | },
86 | "publishConfig": {
87 | "access": "public"
88 | },
89 | "vue-sfc-cli": "1.11.4",
90 | "engines": {
91 | "node": ">= 8.3.0",
92 | "npm": ">= 3.0.0"
93 | },
94 | "husky": {
95 | "hooks": {
96 | "pre-commit": "lint-staged",
97 | "post-commit": "git update-index --again",
98 | "pre-push": "yarn test"
99 | }
100 | },
101 | "lint-staged": {
102 | "*.@(md|json)": [
103 | "prettier --write",
104 | "git add"
105 | ],
106 | "*.js": [
107 | "eslint --fix",
108 | "prettier --write",
109 | "git add"
110 | ],
111 | "*.vue": [
112 | "eslint --fix",
113 | "prettier --write",
114 | "stylelint --fix",
115 | "git add"
116 | ]
117 | },
118 | "gren": "@femessage/grenrc"
119 | }
120 |
--------------------------------------------------------------------------------
/src/components/el-data-table-column.js:
--------------------------------------------------------------------------------
1 | export default {
2 | name: 'el-data-table-column',
3 | functional: true,
4 | render(h, {data, props}) {
5 | let children = []
6 | const align = props.align
7 | if (props.columns) {
8 | children = props.columns.map(column =>
9 | h('el-data-table-column', {
10 | props: Object.assign({}, {align}, column)
11 | })
12 | )
13 | }
14 | data.props = {
15 | ...data.props
16 | }
17 | return h('el-table-column', data, children)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/self-loading-button.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
74 |
--------------------------------------------------------------------------------
/src/components/text-button.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
44 |
--------------------------------------------------------------------------------
/src/components/the-dialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 | 取 消
22 | 确 定
29 |
30 |
31 |
32 |
33 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/src/el-data-table.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, {VueConstructor, VNode} from 'vue'
2 |
3 | import {AxiosRequestConfig} from 'axios'
4 |
5 | import {Table,Form, Dialog} from '@femessage/types/element-ui'
6 | import {TableColumn} from '@femessage/types/element-ui/table-column'
7 |
8 | declare module '@femessage/el-data-table' {
9 | class FemessageComponent extends Vue {
10 | static install(vue: typeof Vue): void
11 | }
12 |
13 | type CombinedVueInstance<
14 | Instance extends Vue,
15 | Data,
16 | Methods,
17 | Computed,
18 | Props
19 | > = Data & Methods & Computed & Props & Instance
20 |
21 | type ExtendedVue<
22 | Instance extends Vue,
23 | Data,
24 | Methods,
25 | Computed,
26 | Props
27 | > = VueConstructor<
28 | CombinedVueInstance & Vue
29 | >
30 |
31 | type Combined = Data &
32 | Methods &
33 | Computed &
34 | Props
35 |
36 | type ElDataTableData = {
37 | data: any[]
38 | size: number
39 | page: number
40 | total: null | number
41 | loading: boolean
42 | selected: any[]
43 | row: any
44 | initExtraQuery: any
45 | isSearchCollapse: boolean
46 | showNoData: boolean
47 | }
48 |
49 | type ElDataTableMethods = {
50 | getList: ({loading}?: {loading?: boolean}) => void
51 |
52 | resetSearch: () => void
53 |
54 | toggleRowSelection: (row: any, isSelected?: boolean) => any
55 |
56 | clearSelection: () => void
57 |
58 | onDefaultDelete: (data: any) => void
59 |
60 | correctPage: () => void
61 | }
62 |
63 | type ElDataTableComputed = {
64 | tableEventHandlersInner: any
65 | hasSelect: boolean
66 | selectable: () => boolean
67 | columnsAlign: string
68 | routerMode: string
69 | hasSearchForm: boolean
70 | hasHeader: boolean
71 | _extraBody: object
72 | _extraQuery: object
73 | selectStrategy: any
74 | searchLocatedSlotKeys: any
75 | collapseForm: any
76 | _searchForm: any
77 | }
78 |
79 | export interface FormContentItem {
80 | id: string
81 | label?: string | VNode
82 | [key: string]: any
83 | }
84 |
85 | export type FormContent = Array
86 |
87 | export interface DataTableColumn {
88 | label: string
89 | prop: string
90 | formatter?: (row: any, column: TableColumn) => any
91 | [key: string]: any
92 | }
93 |
94 | export type DataTableColumns = Array
95 |
96 | export type OperationButton = {
97 | type?: string
98 | text: string
99 | atClick: (row: any) => Promise
100 | show?: (row: any) => boolean
101 | disabled?: (row: any) => boolean
102 | }
103 |
104 | export type OperationButtons = OperationButton[]
105 |
106 | // props 都有默认值,都是可选的
107 | export type ElDataTableProps = Partial<{
108 | url: string
109 | id: string
110 | firstPage: number
111 | dataPath: string
112 | totalPath: string
113 | pageKey: string
114 | pageSizeKey: string
115 | columns: DataTableColumns
116 | searchForm: FormContent
117 | canSearchCollapse: boolean
118 | beforeSearch: (formValue: any) => any
119 | single: boolean
120 | persistSelection: boolean
121 | hasOperation: boolean
122 | extraButtons: OperationButtons
123 | headerButtons: OperationButtons
124 | hasNew: boolean
125 | hasEdit: boolean
126 | hasView: boolean
127 | hasDelete: boolean
128 | newText: string
129 | editText: string
130 | viewText: string
131 | deleteText: string
132 | deleteMessage: (data: any) => string
133 | canDelete: (row: any) => boolean
134 | onNew: (data: any, row?: any) => Promise
135 | onEdit: (data: any, row: any) => Promise
136 | onDelete: (data: any) => Promise
137 | onSuccess: (type: 'new' | 'edit' | 'delete', data: any) => Promise
138 | hasPagination: boolean
139 | paginationLayout: string
140 | paginationSizes: number[]
141 | paginationSize: number
142 | noPaginationSize: number
143 | isTree: boolean
144 | treeChildKey: string
145 | treeParentKey: string
146 | treeParentValue: string
147 | expandAll: boolean
148 | tableAttrs: Partial
149 | tableEventHandlers: object
150 | operationAttrs: object
151 | dialogNewTitle: string
152 | dialogEditTitle: string
153 | dialogViewTitle: string
154 | form: FormContent
155 | formAttrs: Partial