├── .gitignore ├── .idea ├── modules.xml ├── vcs.xml ├── vue-datasheet.iml └── workspace.xml ├── README.md ├── assets └── example1.gif ├── index.js ├── lib ├── ComponentCell.vue ├── DataCell.vue ├── DataSheet.vue ├── constant.js ├── index.js └── react-datasheet.css ├── package.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | *.iml 4 | .*.haste_cache.* 5 | .DS_Store 6 | .idea 7 | npm-debug.log 8 | node_modules 9 | .nyc_output 10 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vue-datasheet.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | before 55 | beforeD 56 | beforeDestroy 57 | removeAllListeners 58 | pageClick 59 | created 60 | defaultState 61 | props 62 | es 63 | handleKey 64 | test 65 | _input 66 | input 67 | forceEdit 68 | forceedit 69 | selected 70 | editing 71 | onSelect 72 | console 73 | data 74 | onDoubleClick 75 | doub 76 | updated 77 | reverting 78 | change 79 | console.log 80 | wa 81 | wat 82 | watch 83 | onChange 84 | 85 | 86 | 87 | 89 | 90 | 106 | 107 | 108 | 109 | 110 | true 111 | 112 | false 113 | true 114 | 115 | 116 | true 117 | DEFINITION_ORDER 118 | 119 | 120 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 148 | 149 | 152 | 153 | 154 | 155 | 158 | 159 | 162 | 163 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 252 | 253 | project 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | project 270 | 271 | 272 | true 273 | 274 | 275 | 276 | DIRECTORY 277 | 278 | false 279 | 280 | 281 | 282 | 283 | 285 | 286 | 287 | 288 | 1513875786860 289 | 303 | 304 | 305 | 306 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 334 | 335 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-datasheet 2 | 3 | 简单易用的在线excel插件 4 | 5 | npm install vue-datasheet --save
6 | 7 | ![image](https://github.com/vyouyou/vue-datasheet/blob/master/assets/example1.gif) 8 | ## 选项 9 | 10 | 选项 | 类型 | 描述 11 | :--- | :---: | :--- 12 | data | Array | 二维数组,每个元素的属性会传递给对应单元格 13 | valueRenderer | func | 渲染单元格的方法: `function(cell, i, j)` 14 | onChange | func | 发生变化的回调函数: `function(cell, i, j, newValue) {}` 15 | onPaste | func | 粘贴的回调函数: `function(array) {}` 16 | onContextMenu | func | 鼠标右键的上下文菜单回调: `function(event, cell, i, j)` 17 | parsePaste | func | `function (string) {}` 粘贴时对内容字符串处理的回调函数 18 | 19 | ## 单元格选项 20 | 21 | Option | Type | Default | Description 22 | :--- | :--- | :--- | :-- 23 | readOnly | Bool | false | 是否只读 24 | key | String | undefined | 默认为行列的number 25 | className | Object | undefined | 单元格的class 26 | component | Function | undefined | component(h)形式的jsx自定义单元格 27 | forceComponent | bool | false | 默认只在edit时显示自定义单元格,为true则一直保持自定义单元格形式 28 | disableEvents | bool | false | cell会不可选取 29 | colSpan | number | 1 | cell的colSpan 30 | rowSpan | number | 1 | cell的rowSpan 31 | style | Object | undefined | cell的style 32 | -------------------------------------------------------------------------------- /assets/example1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vyouyou/vue-datasheet/dbf855bf8c3891e598a710a23e73fae4c04ebd33/assets/example1.gif -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import DataSheet from "./lib/DataSheet.vue"; 2 | 3 | module.exports = DataSheet; 4 | -------------------------------------------------------------------------------- /lib/ComponentCell.vue: -------------------------------------------------------------------------------- 1 | 79 | -------------------------------------------------------------------------------- /lib/DataCell.vue: -------------------------------------------------------------------------------- 1 | 121 | -------------------------------------------------------------------------------- /lib/DataSheet.vue: -------------------------------------------------------------------------------- 1 | 414 | 415 | 418 | 419 | 421 | -------------------------------------------------------------------------------- /lib/constant.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by vyouyou on 17-12-11. 3 | */ 4 | export const TAB_KEY = 9; 5 | export const ENTER_KEY = 13; 6 | export const ESCAPE_KEY = 27; 7 | export const LEFT_KEY = 37; 8 | export const UP_KEY = 38; 9 | export const RIGHT_KEY = 39; 10 | export const DOWN_KEY = 40; 11 | export const DELETE_KEY = 46; 12 | export const BACKSPACE_KEY = 8; 13 | export const isEmpty = (obj) => Object.keys(obj).length === 0; 14 | export const range = (start, end) => { 15 | const array = []; 16 | const inc = (end - start > 0); 17 | for (let i = start; inc ? (i <= end) : (i >= end); inc ? i++ : i--) { 18 | inc ? array.push(i) : array.unshift(i); 19 | } 20 | return array; 21 | }; 22 | 23 | export const nullFtn = (obj) => {}; 24 | 25 | export const defaultParsePaste = (str) => { 26 | return str.split(/\r\n|\n|\r/) 27 | .map((row) => row.split("\t")); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import DataSheet from "./DataSheet.vue"; 2 | 3 | export default DataSheet; 4 | -------------------------------------------------------------------------------- /lib/react-datasheet.css: -------------------------------------------------------------------------------- 1 | 2 | table.data-grid { 3 | table-layout: fixed; 4 | border-collapse: collapse; 5 | 6 | } 7 | 8 | table.data-grid td.cell.updated { 9 | background-color: rgba(0, 145, 253, 0.16); 10 | transition: background-color 0ms ease; 11 | } 12 | 13 | table.data-grid td.cell { 14 | height: 24px; 15 | line-height: 23px; 16 | user-select: none; 17 | -moz-user-select: none; 18 | -webkit-user-select: none; 19 | -ms-user-select: none; 20 | cursor: cell; 21 | background-color: unset; 22 | transition: background-color 500ms ease; 23 | vertical-align: middle; 24 | text-align: right; 25 | border: 1px solid #DDD; 26 | padding: 0px 3px; 27 | } 28 | 29 | table.data-grid td.cell.selected { 30 | border: 1px double #0099CC; 31 | transition: none; 32 | } 33 | 34 | table.data-grid td.cell span { 35 | } 36 | 37 | table.data-grid td.cell div{ 38 | width: 100%; 39 | line-height: 100%; 40 | height: 100%; 41 | } 42 | 43 | table.data-grid td.cell.selected div { 44 | position: absolute; 45 | left: 0px; 46 | top: 0px; 47 | width: 100%; 48 | line-height: 100%; 49 | height: 100%; 50 | box-shadow: 0 0 5px 3px rgba(0, 0, 0, 0.12); 51 | z-index: 2; 52 | } 53 | 54 | table.data-grid td.cell.selected div input { 55 | width: calc(100% - 6px); 56 | height: calc(100% - 6px); 57 | margin: 3px 3px; 58 | } 59 | 60 | /*table.data-grid td.cell.selected {*/ 61 | /*box-shadow: inset 0 -100px 0 rgba(33, 133, 208, 0.15);*/ 62 | /*}*/ 63 | 64 | table.data-grid td.cell.read-only { 65 | background: whitesmoke; 66 | color: #666666; 67 | text-align: center; 68 | padding: 0px 0px; 69 | } 70 | 71 | table.data-grid td.cell > div.text { 72 | padding: 2px 5px; 73 | text-overflow: ellipsis; 74 | overflow: hidden; 75 | } 76 | 77 | table.data-grid td.cell div input { 78 | box-sizing: content-box; 79 | outline: none !important; 80 | border: 0px solid #0099CC; 81 | text-align: right; 82 | width: calc(100% - 1px); 83 | height: 100%; 84 | background: #ffffff; 85 | } 86 | 87 | table.data-grid td.cell { 88 | vertical-align: bottom; 89 | } 90 | 91 | table.data-grid td.cell, 92 | table.data-grid.wrap td.cell, 93 | table.data-grid.wrap td.cell.wrap, 94 | table.data-grid td.cell.wrap, 95 | table.data-grid.nowrap td.cell.wrap, 96 | table.data-grid.clip td.cell.wrap { 97 | white-space: normal; 98 | } 99 | 100 | table.data-grid.nowrap td.cell, 101 | table.data-grid.nowrap td.cell.nowrap, 102 | table.data-grid td.cell.nowrap, 103 | table.data-grid.wrap td.cell.nowrap, 104 | table.data-grid.clip td.cell.nowrap { 105 | white-space: nowrap; 106 | overflow-x: visible; 107 | } 108 | 109 | table.data-grid.clip td.cell, 110 | table.data-grid.clip td.cell.clip, 111 | table.data-grid td.cell.clip, 112 | table.data-grid.wrap td.cell.clip, 113 | table.data-grid.nowrap td.cell.clip { 114 | white-space: nowrap; 115 | overflow-x: hidden; 116 | } 117 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-datasheet", 3 | "version": "1.0.0", 4 | "description": "the best excel component for vue.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "vyouyou", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | vue-datasheet@^1.0.0: 6 | version "1.0.0" 7 | resolved "http://registry.npm.taobao.org/vue-datasheet/download/vue-datasheet-1.0.0.tgz#e718f73166b8b79e836fcdd4d7bf2fc49cf05155" 8 | --------------------------------------------------------------------------------