Skip to content

Commit

Permalink
增加更多事件派发,代码优化增加注释等
Browse files Browse the repository at this point in the history
  • Loading branch information
luanhualiang committed Aug 14, 2020
1 parent 91bc70e commit 0f812e7
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 133 deletions.
12 changes: 10 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
:data="gridData"
:fixed-left="2"
:fixed-right="1"
@on-update="onUpdate"
@after-edit-cell="afterEditCell"
@after-autofill="afterAutofill"
@after-paste="afterPaste"
></DataGrid>
</div>
</template>
Expand Down Expand Up @@ -88,7 +90,13 @@ export default {
]
this.$refs.datagrid.updateData(data);
},
onUpdate(data) {
afterEditCell(data) {
console.log(data)
},
afterAutofill(data) {
console.log(data)
},
afterPaste(data) {
console.log(data)
},
getCheckedRows() {
Expand Down
57 changes: 37 additions & 20 deletions src/components/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
contenteditable="true"
v-show="isSimple"
@input="inputHandler"
@keydown.tab.prevent @keydown.enter.prevent @keydown.esc.prevent
@keydown.tab.prevent
@keydown.enter.prevent
@keydown.esc.prevent
></div>
<el-date-picker
ref="month"
Expand Down Expand Up @@ -83,25 +85,25 @@
></el-option>
</el-select>
<!-- <el-cascader
ref="cascader"
v-else-if="dataType==='cascader'"
:class="`${CSS_PREFIX}-popup`"
:style="popupSty"
v-model="cascader_value"
size="medium"
:options="selectOptions"
@change="selectChange">
</el-cascader> -->
ref="cascader"
v-else-if="dataType==='cascader'"
:class="`${CSS_PREFIX}-popup`"
:style="popupSty"
v-model="cascader_value"
size="medium"
:options="selectOptions"
@change="selectChange">
</el-cascader> -->
</div>
</div>
</div>
</div>
</template>
<script>
import { CSS_PREFIX, HEADER_HEIGHT } from "../core/constants.js";
import { getMaxRow } from '../core/util.js'
import DataGrid from "../core/DataGrid.js";
import Clickoutside from './clickoutside.js'
import { getMaxRow } from '../core/util.js'
const SIMPLE_DATE_TYPES = ["text", "number", "phone", "email"];
const COMPLEX_DATE_TYPES = ["month", "date", "datetime", "select"];
Expand Down Expand Up @@ -219,9 +221,6 @@ export default {
setFullScreen() {
this.grid.resize();
},
doPaste() {
this.isPaste = true
},
editCell() {
const {
dataType,
Expand Down Expand Up @@ -310,7 +309,16 @@ export default {
}
}
},
doPaste() {
// 粘贴事件标识
this.isPaste = true
},
inputHandler(e) {
/**
* 复制粘贴的基本原理:直接监听可编辑元素(这里是contenteditable=true的div)的
* input事件,按下CTRL+V会先触发paste事件,接着会触发input事件,在paste事件中
* 定义一个标识,这样在input事件就可以区分内容是通过粘贴来的还是手动输入的
*/
const val = e.target.innerText;
if (!this.isPaste) {
this.showEditor()
Expand All @@ -327,6 +335,7 @@ export default {
textArr = arr.map(item => item.split("\t"));
}
// 通过table的格式进行粘贴解析
// const objE = document.createElement('div')
// objE.innerHTML = e.target.innerHTML
// const dom = objE.childNodes
Expand Down Expand Up @@ -365,7 +374,6 @@ export default {
selectChange(val) {
this.grid.setTempData(val)
},
handlePaste(e) {},
handleclickoutside() {
this.grid.doneEdit()
}
Expand All @@ -384,14 +392,23 @@ export default {
fixedRight: this.fixedRight,
columns: this.columns,
data: this.data,
onEditCell: () => {
beforeSelectCell: () => {},
afterSelectCell: (cell) => {
self.selectCell(cell)
},
beforeMultiSelectCell: () => {},
afterMultiSelectCell: () => {},
beforeEditCell: () => {
self.editCell();
},
onSelectCell: (cell) => {
self.selectCell(cell)
afterEditCell: (data) => {
self.$emit('after-edit-cell', data)
},
afterAutofill: (data) => {
self.$emit('after-autofill', data)
},
onUpdateData: (rowData) => {
self.$emit('on-update', rowData)
afterPaste: (data) => {
self.$emit('after-paste', data)
}
});
});
Expand Down
41 changes: 37 additions & 4 deletions src/core/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,39 @@ class Body {
return sum + item.height;
}, this.grid.tableHeaderHeight);
}
/**
* CTRL+V 粘贴
* @param {Array} data 粘贴板中的数据
*/
pasteData(data) {
const { editor } = this.grid;
const { xIndex, yIndex } = this.grid.editor;
for (let ri = 0; ri <= data.length - 1; ri++) {
const len = data[ri].length;
for (let ci = 0; ci <= len - 1; ci++) {
const cells = this.rows[ri + editor.yIndex].allCells;
const cell = cells[ci + editor.xIndex];
const cells = this.rows[ri + yIndex].allCells;
const cell = cells[ci + xIndex];
cell.setData(data[ri][ci]);
}
}
// 粘贴后事件派发
const startY = yIndex
const endY = startY + data.length - 1
let rowDatas = []
for (let i = startY; i <= endY; i++) {
rowDatas.push(this.getRowData(i))
}
this.grid.afterPaste(rowDatas)
}
/**
* autofull自动填充
*/
autofillData() {
const { value } = this.getSelectedData();
const xStep = value[0].length;
const yStep = value.length;
const { xArr, yArr } = this.grid.autofill;

const { yArr: syArr } = this.grid.selector

if (yArr[1] < 0 || xArr[1] < 0) return;

for (let ri = 0; ri <= yArr[1] - yArr[0]; ri++) {
Expand All @@ -53,6 +69,22 @@ class Body {
cell.setData(val);
}
}

// 自动填充后事件派发
let startY = syArr[0]
let endY = syArr[1]
let rowDatas = []
if (yArr[0] !== syArr[0]) { // 纵方向向上
startY = yArr[0]
} else {
startY = syArr[1] + 1
endY = yArr[1]
}
for (let i = startY; i <= endY; i++) {
rowDatas.push(this.getRowData(i))
}
this.grid.afterAutofill(rowDatas)

this.grid.clearAuaofill();
}
resizeColumn(colIndex, width) {
Expand Down Expand Up @@ -345,6 +377,7 @@ class Body {
value: cell.value
}
}
// 批量更新表格数据
updateData(data) {
if (data && Array.isArray(data)) {
data.forEach(item => {
Expand Down
11 changes: 9 additions & 2 deletions src/core/Cell.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Context from "./Context.js";
import Validator from "./Validator.js";
import {
SELECT_BORDER_COLOR,
SELECT_AREA_COLOR,
Expand All @@ -6,8 +8,6 @@ import {
READONLY_TEXT_COLOR,
ERROR_TIP_COLOR
} from "./constants.js";
import Context from "./Context.js";
import Validator from "./Validator.js";

class Cell extends Context {
constructor(
Expand Down Expand Up @@ -52,6 +52,7 @@ class Cell extends Context {
if (column.rule && column.rule.immediate === false) return; // 编辑器初始化不需要校验
this.validate();
}
// 鼠标横坐标是否位于【焦点单元格】所在的autofill触点范围内
isInHorizontalAutofill(mouseX, mouseY) {
return (
mouseX > this.x + this.grid.scrollX + this.width - 3 &&
Expand All @@ -60,6 +61,7 @@ class Cell extends Context {
mouseX < this.grid.width - this.grid.fixedRightWidth
);
}
// 鼠标横坐标是否位于处于【冻结列中焦点单元格】所在的autofill触点范围内
isInsideFixedHorizontalAutofill(mouseX, mouseY) {
const x =
this.grid.width -
Expand All @@ -84,6 +86,10 @@ class Cell extends Context {
this.valid = flag;
this.message = message;
}
/**
* @param {String|Number} val 需要设置的值
* @param {Boolean} ignore 是否忽略readonly属性可以修改
*/
setData(val, ignore) {
if (!ignore && this.readonly) return;

Expand Down Expand Up @@ -115,6 +121,7 @@ class Cell extends Context {
}
this.label = label;
}
// 对于下拉类型的数据,对外展示的是label,实际存的是value,所以在更新这类数据的时候需要做一个转换
getMapValue(label) { // label => value
let value = label;
if (this.dataType === "select" && Array.isArray(this.options)) {
Expand Down
32 changes: 16 additions & 16 deletions src/core/Clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ class Clipboard {
paste() {
this.isPaste = true
}
paste2(e) {
const { editor, selector, autofill, body } = this.grid;
let textArr;
let rawText = e.clipboardData.getData("text/plain");
// let arr = isMac ? rawText.split('\r').map(item => item.split('\t')) : rawText.split('\r').map(item => item.split('\t')).slice(0, -1) // windows系统截取掉最后一个空白字符
let arr = rawText.split("\r");
if (arr.length === 1) {
let _arr = arr[0].split("\n");
textArr = _arr.map(item => item.split("\t"));
} else {
textArr = arr.map(item => item.split("\t"));
}
if (textArr.length) {
body.pasteData(textArr);
}
}
// paste2(e) {
// const { editor, selector, autofill, body } = this.grid;
// let textArr;
// let rawText = e.clipboardData.getData("text/plain");
// // let arr = isMac ? rawText.split('\r').map(item => item.split('\t')) : rawText.split('\r').map(item => item.split('\t')).slice(0, -1) // windows系统截取掉最后一个空白字符
// let arr = rawText.split("\r");
// if (arr.length === 1) {
// let _arr = arr[0].split("\n");
// textArr = _arr.map(item => item.split("\t"));
// } else {
// textArr = arr.map(item => item.split("\t"));
// }
// if (textArr.length) {
// body.pasteData(textArr);
// }
// }
select(textArr) {
this.isPaste = false
// 复制完把被填充的区域选中,并把激活单元格定位到填充区域的第一个
Expand Down
4 changes: 3 additions & 1 deletion src/core/ColumnHeader.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Context from "./Context.js";
import {
SELECT_BORDER_COLOR,
SELECT_BG_COLOR
} from "./constants.js";
import Context from "./Context.js";

class ColumnHeader extends Context {
constructor(grid, index, x, y, width, height, column, options) {
Expand Down Expand Up @@ -68,6 +68,8 @@ class ColumnHeader extends Context {
borderWidth: 2
});
}

// 弥补相邻单元格线条覆盖的问题
// if (this.index - 1 === maxX) {
// const points = [
// [x - 1, this.y + this.height],
Expand Down
1 change: 1 addition & 0 deletions src/core/Context.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class Context {
mouseY > this.grid.tableHeaderHeight
);
}
// 鼠标坐标是否在表头范围内
isInsideHeader(mouseX, mouseY) {
return mouseY > this.y && mouseY < this.y + this.grid.tableHeaderHeight;
}
Expand Down
Loading

0 comments on commit 0f812e7

Please sign in to comment.