使用VUE组件创建SpreadJS自定义单元格
Posted 葡萄城技术团队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用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更多实例演示。
我们也会在之后,持续为大家带来更多带来更多严肃和有趣的内容 ~
以上是关于使用VUE组件创建SpreadJS自定义单元格的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 2 个或更多自定义单元格创建自定义 UICollectionView?