教你如何使用VUE組件創(chuàng)建SpreadJS自定義單元格
SpreadJS純前端表格控件是基于HTML5的Java電子表格和網(wǎng)格功能控件,適用于.NET、Java和移動(dòng)端等各平臺(tái)在線編輯類(lèi)Excel功能的表格程序開(kāi)發(fā)。
本文介紹了如何使用VUE組件創(chuàng)建SpreadJS自定義單元格功能。
作為近五年都沖在熱門(mén)框架排行榜首的Vue,大家一定會(huì)學(xué)到的一部分就是組件的使用。前端開(kāi)發(fā)的模塊化,可以讓代碼邏輯更加簡(jiǎn)單清晰,項(xiàng)目的擴(kuò)展性大大加強(qiáng)。對(duì)于Vue而言,模塊化的體現(xiàn)集中在組件之上,以組件為單位實(shí)現(xiàn)模塊化。
通常我們使用組件的方式是,在實(shí)例化Vue對(duì)象之前,通過(guò)Vue.component方法來(lái)注冊(cè)全局的組件。
// 告訴Vue,現(xiàn)在需要組件 todo-item,配置如下,包含props和template Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) // 實(shí)例化一個(gè)Vue對(duì)象,掛載在#app-7元素下,定它的屬性,數(shù)組groceryList var app7 = new Vue({ el: '#app-7', data: { groceryList: [ { text: 'Vegetables' }, { text: 'Cheese' }, { text: 'Whatever else humans are supposed to eat' } ] } })
在眾多組件之中,作為辦公必備的電子表格,在前端組件中也占據(jù)了重要地位。除了以表格的形式展示數(shù)據(jù),電子表格還有一個(gè)非常重要的功能,即支持自定義功能拓展和各種定制化的數(shù)據(jù)展示效果,比如checkbox,Radio button等;還需要實(shí)現(xiàn)當(dāng)單元格進(jìn)入編輯狀態(tài)時(shí),使用下拉菜單(或其他輸入控件)輸入的效果。我們稱(chēng)之為"自定義單元格",一種嵌入組件內(nèi)的組件。SpreadJS目前擁有8種下拉列表,在打開(kāi)列表之前,我們只需要在單元格樣式中設(shè)置選項(xiàng)數(shù)據(jù)。 你可以參考以下代碼使用列表:
// The way of click the dropdown icon to open list. var style = new GC.Spread.Sheets.Style(); style.cellButtons = [ { imageType: GC.Spread.Sheets.ButtonImageType.dropdown, command: "openList", useButtonStyle: true, } ]; style.dropDowns = [ { type: GC.Spread.Sheets.DropDownType.list, option: { items: [ { text: 'item1', value: 'item1' }, { text: 'item2', value: 'item2' }, { text: 'item3', value: 'item3' }, { text: 'item4', value: 'item4' } ], } } ]; sheet.setText(2, 1, "Vertical text list"); sheet.setStyle(3, 1, style); // The way open list with command rather then clicking the dropdown button. spread.commandManager().execute({cmd:"openList",row:3,col:1,sheetName:"Sheet1"});
前端電子表格固然好用, 但由于框架生命周期以及自定義單元格渲染邏輯的問(wèn)題,目前的技術(shù)手段無(wú)法直接在框架頁(yè)面下直接通過(guò)template的方式使用框架下的組件。在之前的內(nèi)容中,我們提到了可以使用Svelte使用Web Conmponents封裝其他組件可以使用的組件。
除了上面提到的方法之外,我們?nèi)绻朐赩ue環(huán)境下使用自定義單元格,可以考慮使用持動(dòng)態(tài)渲染的方式來(lái)創(chuàng)建和掛載組件,從而將組件注入自定義單元格。
下面為大家演演示如何在VUE項(xiàng)目中,創(chuàng)建一個(gè)使用VUE 組件的自定義單元格。
實(shí)踐
首先,在項(xiàng)目中開(kāi)啟運(yùn)行時(shí)加載,在vue.config.js中添加runtimeCompiler: true。
module.exports = { devServer: { port: 3000 }, <font color="#ff0000">runtimeCompiler: true</font> }
引用ElementUI,需要注意要把element 的css引用放在APP import前,這樣修改樣式,才能覆蓋原有項(xiàng)目?jī)?nèi)容。
import Vue from 'vue' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue' import router from './router' Vue.use(ElementUI); new Vue({ el: '#app', router, render: h => h(App) }) Vue.config.productionTip = false
創(chuàng)建AutoComplateCellType,具體代碼如下,需要注意幾點(diǎn)。
1、自定義的元素,需要添加gcUIElement屬性,如果元素或者其父元素沒(méi)有該屬性,點(diǎn)擊創(chuàng)建的組件便會(huì)直接退出編輯狀態(tài)無(wú)法編輯。
對(duì)于ElementUI 的autocomplete,默認(rèn)下拉選項(xiàng)內(nèi)容是注入到body中的,需要給組件模板中設(shè)置:popper-append-to-body="false",讓彈出的下拉選項(xiàng)在gcUIElement的Div中渲染。
如果使用其他組件沒(méi)有類(lèi)似選項(xiàng),也可以跟進(jìn)實(shí)際情況在彈出時(shí)在添加gcUIElement屬性。
2、使用動(dòng)態(tài)掛載組件的 this.vm 設(shè)置和獲取單元格的值。
3、在deactivateEditor中銷(xiāo)毀組件。
import Vue from 'vue' import * as GC from "@grapecity/spread-sheets" import DataService from './dataService' function AutoComplateCellType() { } AutoComplateCellType.prototype = new GC.Spread.Sheets.CellTypes.Base(); AutoComplateCellType.prototype.createEditorElement = function (context, cellWrapperElement) { cellWrapperElement.style.overflow = 'visible' let editorContext = document.createElement("div") editorContext.setAttribute("gcUIElement", "gcEditingInput"); let editor = document.createElement("div"); // 自定義單元格中editorContext作為容器,需要在創(chuàng)建一個(gè)child用于掛載,不能直接掛載到editorContext上 editorContext.appendChild(editor); return editorContext; } AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) { let width = cellRect.width > 180 ? cellRect.width : 180; if (editorContext) { // 動(dòng)態(tài)創(chuàng)建VUE 組件并掛載到editor const AutoCompleteComponent = { props: ['text','cellStyle'], template: `<div> <el-autocomplete :style="cellStyle" popper-class="my-autocomplete" v-model="text" :fetch-suggestions="querySearch" placeholder="請(qǐng)輸入內(nèi)容" :popper-append-to-body="false" value-key="name" @select="handleSelect"> <i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClick"> </i> <template slot-scope="{ item }"> <div class="name">{{ item.name }}</div> <span class="addr">{{ item.phone }}</span> </template> </el-autocomplete> </div>`, mounted() { this.items = DataService.getEmployeesData(); }, methods: { querySearch(queryString, cb) { var items = this.items; var results = queryString ? items.filter(this.createFilter(queryString)) : items; // 無(wú)法設(shè)置動(dòng)態(tài)內(nèi)容的位置,可以動(dòng)態(tài)添加gcUIElement // setTimeout(() => { // let popDiv = document.getElementsByClassName("my-autocomplete")[0]; // if(popDiv){ // popDiv.setAttribute("gcUIElement", "gcEditingInput"); // } // }, 500); // 調(diào)用 callback 返回建議列表的數(shù)據(jù) cb(results); }, createFilter(queryString) { return (restaurant) => { return (restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0); }; }, handleSelect(item) { console.log(item); }, handleIconClick(ev) { console.log(ev); } } }; // create component constructor const AutoCompleteCtor = Vue.extend(AutoCompleteComponent); this.vm = new AutoCompleteCtor({ propsData: { cellStyle: {width: width+"px"} } }).$mount(editorContext.firstChild); } return editorContext; }; AutoComplateCellType.prototype.updateEditor = function(editorContext, cellStyle, cellRect) { // 給定一個(gè)最小編輯區(qū)域大小 let width = cellRect.width > 180 ? cellRect.width : 180; let height = cellRect.height > 40 ? cellRect.height : 40; return {width: width, height: height}; }; AutoComplateCellType.prototype.getEditorValue = function (editorContext) { // 設(shè)置組件默認(rèn)值 if (this.vm) { return this.vm.text; } }; AutoComplateCellType.prototype.setEditorValue = function (editorContext, value) { // 獲取組件編輯后的值 if (editorContext) { this.vm.text = value; } }; AutoComplateCellType.prototype.deactivateEditor = function (editorContext, context) { // 銷(xiāo)毀組件 this.vm.$destroy(); this.vm = undefined; }; export {AutoComplateCellType};
效果如圖:
一個(gè)完美的單元格新鮮出爐~
這里介紹的方式只是諸多實(shí)現(xiàn)方案的一種。如果大家有其他更好的想法方法,歡迎一起討論 ~
如果你對(duì)其他更多前端電子表格中有趣功能感興趣,可以查看 SpreadJS更多實(shí)例演示。
到此這篇關(guān)于教你如何使用VUE組件創(chuàng)建SpreadJS自定義單元格的文章就介紹到這了,更多相關(guān)vue SpreadJS自定義單元格內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談vue-cli加載不到dev-server.js的解決辦法
本篇文章主要介紹了淺談vue-cli加載不到dev-server.js的解決辦法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11Vue.js項(xiàng)目部署到服務(wù)器的詳細(xì)步驟
這篇文章給大家介紹了Vue.js項(xiàng)目部署到服務(wù)器的詳細(xì)步驟,既然是部署到服務(wù)器,肯定是需要一個(gè)云的。具體思路步驟大家可以參考下本文2017-07-07vue通過(guò)cookie獲取用戶(hù)登錄信息的思路詳解
這篇文章主要介紹了vue通過(guò)cookie獲取用戶(hù)登錄信息的思路詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-10-10vue3組合式api創(chuàng)建單文件組件的寫(xiě)法
Vue3?中的?Composition?API?是一種新的編寫(xiě)組件邏輯的方式,它提供了更好的代碼組織、類(lèi)型推導(dǎo)、測(cè)試支持和復(fù)用性,本文為大家介紹了vue3利用組合式api創(chuàng)建單文件組件的方法,感興趣的可以了解下2023-08-08vue.js動(dòng)態(tài)設(shè)置VueComponent高度遇到的問(wèn)題及解決
這篇文章主要介紹了vue.js動(dòng)態(tài)設(shè)置VueComponent高度遇到的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08詳解.vue文件中監(jiān)聽(tīng)input輸入事件(oninput)
本篇文章主要介紹了詳解.vue文件中監(jiān)聽(tīng)input輸入事件(oninput),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09axios發(fā)送post請(qǐng)求springMVC接收不到參數(shù)的解決方法
下面小編就為大家分享一篇axios發(fā)送post請(qǐng)求springMVC接收不到參數(shù)的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03vue spa應(yīng)用中的路由緩存問(wèn)題與解決方案
這篇文章主要介紹了vue spa應(yīng)用中的路由緩存問(wèn)題與解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05