网页版模仿Excel
網(wǎng)頁版模仿Excel
最近公司閑的dan疼,非要模仿Excel做一個網(wǎng)頁版的Excel,剛開始聽說要做這么一個東西的時候瞬間覺得公司領導高(sang)瞻(xin)遠(bing)矚(kuang),只能頭鐵的接下了,那就開始干。其實主要目的是為了能連上自己的數(shù)據(jù)庫,方便操作表格,后來發(fā)現(xiàn)實現(xiàn)成本太高,做了一個前端DEMO就果斷放棄了,但是這個DEMO還是有點意思,發(fā)開DEMO過程中有些心得與收獲。github地址
https://github.com/zhuqitao/E...
實現(xiàn)功能
- 字體、字號、顏色、背景色、加粗、斜體等字體樣式基本操作功能
- 鼠標拖拽多選單元格
- 左右居中布局
- 合并、拆分單元格
- 插入函數(shù)(沒有計算功能的函數(shù),只是靜態(tài)添加函數(shù)名)
- 本地打開excel(.xls)文件
截圖
先看看目前的效果圖:
滾動問題
領導說先做一個demo看看效果,那就亮出咱家的看家本領吧html+css+js三劍客,不就是表格嗎,html填上table,修修樣式,頁面效果就ok了。
第一個碰到的問題就是滾動問題,看上面的截圖就知道其實這是一種表格表頭固定,表格第一列固定,其他部分滾動的效果,但是其實沒有那么簡單,還有一個問題是垂直滾動的時候第一行(表頭)不動,但是第一列得跟著動啊,水平滾動亦是如此,這可怎么辦啊,這種情況沒遇到過啊,但是得解決啊。
不知道的網(wǎng)友們可以考慮考慮怎么做? 知道怎么處理這種情況的也別噴博主菜。最后的解決方法就是寫了三個table,一個放表頭(第一行),一個放第一列,一個放表格主要內(nèi)容,看下圖:
table1放置表頭(A,B,C),table2放置第一列,table3放置中間操作區(qū)域,把table1、2設置為overflow:hidden,只有table3可以滾動,監(jiān)聽table3的滾動事件,獲取table3的scrollLeft和scrollTop然后分別給table1、table2的scrollLeft和scrollTop賦值。
鼠標按下拖拽多選單元格
這個是本DEMO唯一的亮點了(個人認為)。表格目前定下的是30*30的表格。一開始的想法是監(jiān)聽鼠標按下(mousedown)事件獲取鼠標按下時的位置,然后再監(jiān)聽鼠標移動事件(mousemove),獲取鼠標當前的位置,然后根據(jù)當前位置和按下時位置畫一個矩形,循環(huán)遍歷所有的單元格元素,判斷單元格是否在矩形內(nèi),然后給選中的單元格添加active類。
這樣做的結果是頁面非常卡,因為鼠標移動過程會多次觸發(fā)鼠標移動事件(mousemove),會多次進行單元格元素循環(huán)遍歷。 后來就不在鼠標移動事件里面進行單元格遍歷操作,在鼠標松開事件里面遍歷所有的單元格元素。
這樣確實快了一些,但是還有一個問題上面兩種方法都沒解決的問題,就是如果選擇了很多元素(比如100個),在遍歷單元格元素的時候需要對著100個元素操作添加active類,其實js操作操作DOM是比較耗時的,這里也沒有想到什么好的DOM操作緩存的方法。
就在一籌莫展的時候想到了目前流行的虛擬dom框架(react、vue等),果斷使用了vue。在vue實例里創(chuàng)建兩個對象數(shù)組,分別作為行數(shù)據(jù)和列數(shù)據(jù),頁面上分別對<tr>和<td>標簽使用v-for循環(huán)渲染,這樣就能生成一張表格。每個單元格都給加上行數(shù)和列樹標志。
在鼠標按下獲取鼠標按下時所在單元格的行數(shù)和列數(shù),鼠標松開時獲取松開時所在單元格的行數(shù)和列數(shù),然后先循環(huán)行數(shù)據(jù)的數(shù)組,所有在選中的行數(shù)的數(shù)據(jù)對象添加選中標志,然后再循環(huán)列數(shù)據(jù)的數(shù)組,所有在選中的列數(shù)的數(shù)據(jù)對象添加選中標志,在頁面對<tr>和<td>標簽使用v-for循環(huán)渲染時動態(tài)綁定class類,只有行和列同時被選中,單元格才設置為選中狀態(tài),這樣其實只循環(huán)了30+30=60次,瞬間把復雜度有原來的O(n^2)降低到O(2n)。
其實背后是通過vue的diff算法快速的計算出需要改變的dom元素,然后利用虛擬dom快速渲染到頁面上,速度大大提升。這也讓我真實的感受到這些框架的威力(怪不得這么火)。
我的語言表達能力不是很強,上面說的大家不知道有沒有聽明白,沒明白的可以看看源代碼(^︹^)。?
意外收獲
- 打開本地xls文件
有一款jquery插件js-xlsx可以幫助在線打開本地xls文件,并把xls文件轉(zhuǎn)成json。
- 本地保存xls文件
利用xml的createElementNS創(chuàng)建帶有指定命名空間的元素節(jié)點,再利用js自帶Blob數(shù)據(jù)類型保存xls文件:
var urlObject = window.URL || window.webkitURL || window;var export_blob = new Blob(['test']);var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")var ev = document.createEvent("MouseEvents");ev.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);save_link.href = urlObject.createObjectURL(export_blob);save_link.download = 'test.xls';save_link.dispatchEvent(ev);- execCommand
當一個HTML文檔切換到設計模式 designMode時,文檔對象暴露 execCommand 方法,該方法允許運行命令來操縱可編輯區(qū)域的內(nèi)容。詳情查看MDN地址:https://developer.mozilla.org...
AbsolutePosition 設定元素的 position 屬性為“absolute”(絕對)。 BackColor 設置或獲取當前選中區(qū)的背景顏色。 BlockDirLTR 目前尚未支持。 BlockDirRTL 目前尚未支持。 Bold 切換當前選中區(qū)的粗體顯示與否。 BrowseMode 目前尚未支持。 Copy 將當前選中區(qū)復制到剪貼板。 Paste 用剪貼板內(nèi)容覆蓋當前選中區(qū)(目前尚未支持)。 ...// 例子 document.execCommand("copy") document.execCommand("cut") document.execCommand('paste')- window.getSelection()
獲取鼠標選中的文本
- clipboarddata.setData()
手動設置剪切板,一般用于用戶復制內(nèi)容時添加版權信息。
總結
以上是生活随笔為你收集整理的网页版模仿Excel的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity 之 如何删除Unity项目里
- 下一篇: angularjs控制器之间的数据共享与