使用VUE組件創建SpreadJS自定義單元格(一)
作為近五年都衝在熱門框架排行榜首的Vue,大家一定會學到的一部分就是組件的使用。前端開發的模塊化,可以讓代碼邏輯更加簡單清晰,項目的擴展性大大加強。對於Vue而言,模塊化的體現集中在組件之上,以組件為單位實現模塊化。
通常我們使用組件的方式是,在實例化Vue對象之前,通過Vue.component方法來註冊全局的組件。
// 吿訴Vue,現在需要組件 todo-item,配置如下,包含props和template
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
// 實例化一個Vue對象,掛載在#app-7元素下,定它的屬性,數組groceryList
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{ text: 'Vegetables' },
{ text: 'Cheese' },
{ text: 'Whatever else humans are supposed to eat' }
]
}
})
在眾多組件之中,作為辦公必備的電子表格,在前端組件中也佔據了重要地位。除了以表格的形式展示數據,電子表格還有一個非常重要的功能,即支持自定義功能拓展和各種定製化的數據展示效果,比如checkbox,Radio button等;還需要實現當單元格進入編輯狀態時,使用下拉菜單(或其他輸入控件)輸入的效果。我們稱之為"自定義單元格",一種嵌入組件內的組件。SpreadJS目前擁有8種下拉列表,在打開列表之前,我們只需要在單元格樣式中設置選項數據。 你可以參考以下代碼使用列表:
// 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"});
前端電子表格固然好用, 但由於框架生命週期以及自定義單元格渲染邏輯的問題,目前的技術手段無法直接在框架頁面下直接通過template的方式使用框架下的組件。在之前的內容中,我們提到了可以使用Svelte使用Web Conmponents封裝其他組件可以使用的組件。 除了上面提到的方法之外,我們如果想在Vue環境下使用自定義單元格,可以考慮使用持動態渲染的方式來創建和掛載組件,從而將組件注入自定義單元格。
下面為大家演演示如何在VUE項目中,創建一個使用VUE 組件的自定義單元格。
實踐
首先,在項目中開啟運行時加載,在vue.config.js中添加runtimeCompiler: true。
module.exports = {
devServer: {
port: 3000
},
<font color="#ff0000">runtimeCompiler: true</font>
}
引用ElementUI,需要注意要把element 的css引用放在APP import前,這樣修改樣式,才能覆蓋原有項目內容。
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
創建AutoComplateCellType,具體代碼如下,需要注意幾點。 1、自定義的元素,需要添加gcUIElement屬性,如果元素或者其父元素沒有該屬性,點擊創建的組件便會直接退出編輯狀態無法編輯。 對於ElementUI 的autocomplete,默認下拉選項內容是注入到body中的,需要給組件模板中設置:popper-append-to-body="false",讓彈出的下拉選項在gcUIElement的Div中渲染。 如果使用其他組件沒有類似選項,也可以跟進實際情況在彈出時在添加gcUIElement屬性。 2、使用動態掛載組件的 this.vm 設置和獲取單元格的值。 3、在deactivateEditor中銷燬組件。
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作為容器,需要在創建一個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) {
// 動態創建VUE 組件並掛載到editor
const AutoCompleteComponent = {
props: ['text','cellStyle'],
template: `<div>
<el-autocomplete
:style="cellStyle"
popper-class="my-autocomplete"
v-model="text"
:fetch-suggestions="querySearch"
placeholder="請輸入內容"
: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;
// 無法設置動態內容的位置,可以動態添加gcUIElement
// setTimeout(() => {
// let popDiv = document.getElementsByClassName("my-autocomplete")[0];
// if(popDiv){
// popDiv.setAttribute("gcUIElement", "gcEditingInput");
// }
// }, 500);
// 調用 callback 返回建議列表的數據
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) {
// 給定一個最小編輯區域大小
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) {
// 設置組件默認值
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) {
// 銷燬組件
this.vm.$destroy();
this.vm = undefined;
};
export {AutoComplateCellType};
效果如圖:
一個完美的單元格新鮮出爐~
這裏介紹的方式只是諸多實現方案的一種。如果大家有其他更好的想法方法,歡迎一起討論 ~
如果你對其他更多前端電子表格中有趣功能感興趣,可以查看 SpreadJS更多實例演示。
我們也會在之後,持續為大家帶來更多帶來更多嚴肅和有趣的內容 ~
- JSON數據傳輸大法第一式——用OADate處理日期格式
- VS Code閃現,巨頭紛紛入局的Web IDE緣何崛起?
- 數據傳輸POST心法分享,做前端的你還解決不了這個bug?
- 詳解BI系統中的任務調度
- 還在寫SQL做SAP二開?通過RFC調用NetWeaver,讓HANA數據庫操作更可靠
- 還在寫SQL做SAP二開?通過RFC調用NetWeaver,讓HANA數據庫操作更可靠
- 當.Net撞上BI可視化,這3種“套路”你必須知道
- SpreadJS GcExcel 一出,誰與爭鋒!全棧表格技術輕鬆應對複雜公式計算場景(一)
- “四大高手”為你的 Vue 應用程序保駕護航
- 前端生成PDF,讓後端刮目相看
- 前端生成PDF,讓後端刮目相看
- 2021年度總結 | 葡萄城軟件開發技術回顧(下)
- 從服務端生成Excel電子表格(Node.js SpreadJS)
- PWA 技術落地!讓你的站點(Web)秒變APP(應用程序)
- 使用VUE組件創建SpreadJS自定義單元格(一)
- 使用VUE組件創建SpreadJS自定義單元格(一)
- 突破技術限制,實現Web端靜默打印
- 電子表格實戰錦囊:巧用稀疏數組是關鍵!
- 前端er必須掌握的數據可視化技術
- 前端er必須掌握的數據可視化技術