日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

新版Excel(完结版)

發布時間:2024/1/1 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 新版Excel(完结版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上篇博客講述了此mvc版本的Excel的model層實現,這里我繼續上篇博客的內容,把剩下的內容敘述完。最終效果:新版Excel
首先,我先描述下次版本的Excel在功能上與上個版本的相同點與不同點:

  • 在表的結構上,此次表為動態固定表,也是Excel表格的模式,即行列大小是固定的,所謂的增刪行列就是增加并刪除或者刪除并增加,具體效果可以自行嘗試。
  • 此次的選擇效果除了上次的cell的多選效果外,還新增了行列的多選效果。
  • 在編輯效果上除了上次支持的enter鍵以及鼠標焦點切換來確定輸入內容外,此次新增了tab鍵確定輸入內容的效果。
  • 此次在resize功能上除了本身支持的resize效果外還擴展了反向壓縮resize的效果。
  • 最重要的一個新增功能,上述的行列增刪功能以及resize功能都支持多選操作的效果!

主要功能就這些,還有一些邊界的細節功能我在這就不敘述了,大家有興趣可以自己玩玩。
下面是此版項目的目錄結構:

除了上述模塊外,還有一個單元測試模塊未顯示,由于此版項目代碼量很多,所以在這里我不再給出全部的源碼,大家可以通過此github鏈接下載完整的源代碼:新版Excel源碼
我先講解此mvc項目的運轉流程:
首先最外層的函數接口是main.js文件,此文件調用controller層的initController.js文件的initsheet函數,此函數只做了兩件事,調用model層的表格數據初始化函數,然后調用將model層數據傳給view層來初始化UI頁面。

/* eslint-disable max-len */ import sheet from './sheet.js'; import initTable from '../views/initView.js'; import constants from '../utils/constant.js';export default function initSheet() {sheet.init(constants.rowLength, constants.colLength);initTable(sheet.corner, sheet.rowHeaders, sheet.colHeaders, sheet.selectRange.selectType,sheet.activeCellCoordinate, sheet.selectRange.selectUpperLeftCoordinate, sheet.selectRange.selectBottomRightCoordinate); }

然后,在view層的初始化函數里綁定此次項目所做功能所需的一些事件,而事件的具體實現都交給controller層來管理。

/* eslint-disable max-len */ import portray from './portray.js';import RowHeaderController from '../controllers/rowHeaderController.js'; import ColHeaderController from '../controllers/colHeaderController.js'; import cornerClickHandler from '../controllers/cornerController.js'; import Cell from '../controllers/cellController.js'; import Resize from '../controllers/resizeController.js'; /* eslint-disable max-len */ // time out event resize const colHeaderController = new ColHeaderController(); const rowHeaderController = new RowHeaderController(); const cell = new Cell(); const resize = new Resize(); function createCorner(corner) {const thCorner = document.createElement('th');thCorner.innerText = corner.text;thCorner.classList.add('corner');thCorner.addEventListener('click', (e) => {cornerClickHandler(e);}, false);return thCorner; }function createColHeader(colHeader) {const thColHeader = document.createElement('th');const resizeE = document.createElement('div');const span = document.createElement('span');thColHeader.classList.add('colHeader');resizeE.classList.add('resizeE');thColHeader.appendChild(span);thColHeader.appendChild(resizeE);thColHeader.children[0].innerText = colHeader.text;resizeE.addEventListener('mousedown', resize.resizeColHeaderDownHandler, false);thColHeader.style.width = `${colHeader.width}px`;thColHeader.addEventListener('click', (e) => {ColHeaderController.colHeaderClickHandler(e);}, false);thColHeader.addEventListener('mousedown', (e) => {colHeaderController.colHeaderDownHandler(e);}, false);thColHeader.addEventListener('mouseup', (e) => {colHeaderController.colHeaderUpHandler(e);}, false);thColHeader.addEventListener('mousemove', (e) => {colHeaderController.colHeaderMoveHandler(e);}, false);thColHeader.addEventListener('contextmenu', (e) => {ColHeaderController.colHeaderMenuHandler(e);}, false);return thColHeader; }function createRowHeader(rowHeader) {const tdRowHeader = document.createElement('td');const resizeS = document.createElement('div');const span = document.createElement('span');tdRowHeader.classList.add('rowHeader');resizeS.classList.add('resizeS');tdRowHeader.appendChild(span);tdRowHeader.appendChild(resizeS);tdRowHeader.children[0].innerText = rowHeader.text;tdRowHeader.style.height = `${rowHeader.height}px`;resizeS.addEventListener('mousedown', resize.resizeRowHeaderDownHandler, false);tdRowHeader.addEventListener('click', (e) => {RowHeaderController.rowHeaderClickHandler(e);}, false);tdRowHeader.addEventListener('mousedown', (e) => {rowHeaderController.rowHeaderDownHandler(e);}, false);tdRowHeader.addEventListener('mouseup', (e) => {rowHeaderController.rowHeaderUpHandler(e);}, false);tdRowHeader.addEventListener('mousemove', (e) => {rowHeaderController.rowHeaderMoveHandler(e);}, false);tdRowHeader.addEventListener('contextmenu', (e) => {RowHeaderController.rowHeaderMenuHandler(e);}, false);return tdRowHeader; }function createCell(dataIndex, colWidth) {const tdCell = document.createElement('td');tdCell.style.maxWidth = `${colWidth}px`;tdCell.classList.add('cell');tdCell.setAttribute('data-index', dataIndex);tdCell.addEventListener('click', (e) => {Cell.cellClickHandler(e);}, false);tdCell.addEventListener('dblclick', (e) => {cell.cellDbClickHandler(e);}, false);tdCell.addEventListener('mousedown', (e) => {cell.cellDownHandler(e);}, false);tdCell.addEventListener('mousemove', (e) => {cell.cellMoveHandler(e);}, false);return tdCell; } function BindButtonEvent() {const addButton = document.getElementsByClassName('add')[0];const removeButton = document.getElementsByClassName('remove')[0];addButton.addEventListener('click', () => {colHeaderController.addColHeaderHandler();}, false);removeButton.addEventListener('click', () => {colHeaderController.removeColHeaderHandler();}, false);addButton.addEventListener('click', () => {rowHeaderController.addRowHeaderHandler();}, false);removeButton.addEventListener('click', () => {rowHeaderController.removeRowHeaderHandler();}, false); } export default function initTable(corner, rowHeaders, colHeaders,selectType, activeCellCoordinate, selectUpperLeftCoordinate, selectBottomRightCoordinate) {const body = document.getElementsByTagName('body')[0];const table = document.createElement('table');table.classList.add('table');body.appendChild(table);const trFirst = document.createElement('tr');trFirst.appendChild(createCorner(corner));colHeaders.forEach((colHeader) => trFirst.appendChild(createColHeader(colHeader)));table.appendChild(trFirst);for (let i = 0; i < rowHeaders.length; i++) {const trOther = document.createElement('tr');trOther.appendChild(createRowHeader(rowHeaders[i]));for (let j = 0; j < colHeaders.length; j++) {trOther.appendChild(createCell(colHeaders[j].text, colHeaders[j].width));}table.appendChild(trOther);}document.addEventListener('mouseup', (e) => {cell.cellUpHandler(e);}, false);const bigFrame = document.createElement('div');bigFrame.classList.add('bigFrame');const smallFrame = document.createElement('div');smallFrame.classList.add('smallFrame');table.appendChild(bigFrame);table.appendChild(smallFrame);portray(selectType, selectUpperLeftCoordinate, selectBottomRightCoordinate, activeCellCoordinate);BindButtonEvent(); }

每次我們在前端ui頁面觸發事件后,controller層來執行具體的事件邏輯,然后更改model層的數據,最后傳遞給view層來更新頁面。這不就是最簡單的mvc的核心流程思想嗎
至于每個模塊里的每個文件是干什么的,從文件名應該就能理解,這里我就不多講解。
最后,我講解一下反向壓縮resize的算法思想:
首先,我們明白最基本的resize功能的實現邏輯,無非就三步:在down事件里記錄下初識位置,在move的時候根據初始值來確定該變量并及時更新,最后再up里重置數據。
由于反向壓縮resize操作會改變其它元素的數據,所以下move時候的及時更新就很有可能會出現重復計算的問題,所以我在這里采取的解決方案是通過每次在down的時候深拷貝一份model層的原始數據,在move層里使用深拷貝的那份數據進行邏輯操作,如此一來實時更新model層數據也便無后顧之憂。不得不說,此方案雖然不高效但是的確能解決問題。
到此,此項目的講解就結束了,如果有看源碼不明白的地方或者對源碼有更好的簡潔,歡迎評論區留言,我會及時回復。

總結

以上是生活随笔為你收集整理的新版Excel(完结版)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。