010-68421378
sales@cogitosoft.com
当前您所在的位置:首页>新闻中心>新品发布

从 Handsontable 15.3 迁移到 16.0

发布时间:2025/07/15 浏览量:75
从 Handsontable 15.3 迁移到 Handsontable 16.0,于 09/07/2025 发布。 更多关于此版本的信息,请参阅 16.0.0 版本的博客文章。 1. ...

从 Handsontable 15.3 迁移到 Handsontable 16.0,于 09/07/2025 发布。

 

更多关于此版本的信息,请参阅 16.0.0 版本的博客文章。

 

1. 介绍新的 DOM 结构

在 Handsontable 16.0 中,我们改变了表格在 DOM 中的挂载方式。以前,您提供的容器 <div> 成为表格的根元素。现在,该容器作为一个挂载点,Handsontable 在其中创建并注入自己的根元素。

 

以下是新旧 DOM 结构的并排比较:

 

旧的 DOM 结构:

 

body

├── #example.ht-wrapper.handsontable // Root Container/Element

│ ├── .htFocusCatcher // Focus Catcher (top)

│ ├── Data grid content

│ └── . htFocusCatcher // Focus Catcher (down)

├── .hot-display-license-info // License key notification bar

└── Context menus, dropdowns, pop-ups, sidebars

(absolutely positioned elements)

 

新的 DOM 结构:

 

body

├── #example // Root Wrapper

│ └── .ht-root-wrapper // Root Element

│ ├─ . htFocusCatcher // Focus Catcher (top)

│ ├── .ht-wrapper.handsontable // Root Container

│ │ └── Data grid content

│ ├── . htFocusCatcher // Focus Catcher (down)

│ ├── .hot-display-license-info // License key notification bar

└── .ht-portal // Portal Element

 └── Context menus, dropdowns, pop-ups, sidebars

 (absolutely positioned elements)

 

关键变化:

 

2. 更新了 CSS 变量

在 Handsontable 16.0 中,我们对 CSS 变量系统进行了重大改进,调整了主题颜色、变量顺序,并提供了更好的定制选项。以下是主要的变更:

 

新的 CSS 变量

我们引入了新的变量,让自定义变得更容易:

l--ht-letter-spacing: 控制字母间距,以改善可读性和视觉外观。

l--ht-radio-*: 使单选输入的样式更准确。

l--ht-cell-read-only-background-color: 实现更好的只读单元格背景自定义。

l--ht-checkbox-indeterminate: 允许您对复选框的不定状态进行风格设置。

 

重命名的 CSS 变量

我们已将部分变量重命名为更一致的名称:

旧变量名称

新变量名称

--ht-icon-active-button-border-color

--ht-icon-button-active-border-color

--ht-icon-active-button-background-color

--ht-icon-button-active-background-color

--ht-icon-active-button-icon-color

--ht-icon-button-active-icon-color

--ht-icon-active-button-hover-border-color

--ht-icon-button-active-hover-border-color

--ht-icon-active-button-hover-background-color

--ht-icon-button-active-hover-background-color

--ht-icon-active-button-hover-icon-color

--ht-icon-button-active-hover-icon-color

 

 

迁移说明

如果您在版本 15.3 中使用了自定义 CSS 变量,您需要:

1. 检查您的自定义变量名称是否符合新的命名规范

2. 更新变量引用以使用新的单选按钮输入(仅当复选框变量发生更改时)

3. 利用新变量实现更精细的控制

 

3. 更新自定义边框的位置

在版本 16.0 中,我们更新了自定义边框的定位方式,以提高准确性和一致性。此更改会影响边框的视觉定位,特别是对于具有自定义边框的单元格。

 

发生了什么变化?

边框位置已调整,以防止与相邻单元格和标题重叠。

 

为何这是重大变更?

虽然可能性极低,但若您的应用依赖特定边框位置,或基于边框位置实现了自定义样式,可能需要更新样式。

 

版本 16.0 中边框的视觉外观与版本 15.3 相比将略有不同。

 

迁移说明

无需修改代码——新版本会自动处理这些改进。

 

4. 切换至新的 Angular 包装器(适用于 Angular 16+)

Handsontable 16.0 引入了全新的 Angular 包装器。该包装器旨在与现代 Angular 应用程序实现更佳集成并提升开发体验。若您使用 Angular 16 或更高版本,建议迁移至新包装器。

 

为何切换至新 Angular 包装器?

• 组件化架构:新包装器采用 Angular 的组件化架构,允许您将自定义编辑器和渲染器实现为 Angular 组件。

• 改进的 TypeScript 支持:新包装器提供了更完善的 TypeScript 定义。

• 独立组件支持:新包装器全面支持 Angular 的独立组件,使其在现代 Angular 应用中更易于使用。

• 全局配置:新包装器通过依赖注入提供了更好的全局配置管理。

• 模板语法:简化的模板语法减少了冗余代码,使配置更易于维护。

• 实例访问:现在可以通过 ViewChild 直接访问 Handsontable 实例。

 

步骤 1:更新包依赖项

用新包装器包替换旧的 Angular 包装器包:

 

npm uninstall @handsontable/angular

npm install @handsontable/angular-wrapper

 

步骤 2:更新组件配置

将所有配置选项移动到组件中的 GridSettings 对象中。

 

旧的包装组件:

 

@Component({

  selector: ‘app-root’,

  template: `

    <hot-table

      [data]=“data”

      [colHeaders]=“true”

      [licenseKey]=“‘non-commercial-and-evaluation’”>

      <hot-column data="id" [readOnly]=“true” title="ID"></hot-column>

      <hot-column data="name" title="Full name"></hot-column>

    </hot-table>

  `})export class AppComponent {

  data = //...}

 

新包装组件:

import { GridSettings, HotTableModule } from ‘@handsontable/angular-wrapper’;

@Component({

  standalone: true,

  imports: [HotTableModule],

  template: `<hot-table [data]=“data” [settings]=“gridSettings” />`})export class AppComponent {

  data = //...;

 

  gridSettings: GridSettings = {

    colHeaders: true,

    licenseKey: ‘non-commercial-and-evaluation’,

    columns: [

      { data: ‘id’, readOnly: true, title: ‘ID’ },

      { data: ‘name’, title: ‘Full name’ },

    ]

  };}

 

步骤 3:更新表格实例引用

您引用和与 Handsontable 实例交互的方式已发生变化。

 

旧的包装器实例引用:

 

export class AppComponent {

  private hotRegisterer = new HotTableRegisterer();

  id = ‘hotInstance’;

 

  swapHotData() {

    this.hotRegisterer.getInstance(this.id).loadData([[‘new’, ‘data’]]);

  }}

 

新的包装器实例引用:

 

import { HotTableComponent } from ‘@handsontable/angular-wrapper’;

export class AppComponent {

  @ViewChild(HotTableComponent, { static: false })

  hotTable!: HotTableComponent;

 

  swapHotData() {

    this.hotTable.hotInstance!.loadData([[‘new’, ‘data’]]);

  }}

 

步骤 4:更新全局设定

新的包装器提供更好的全局设定管理。

 

旧包装器的全局配置:

 

// Configuration was typically done per componentexport class AppComponent {

 hotSettings = {

 licenseKey: 'non-commercial-and-evaluation',

 };}

 

使用 ApplicationConfig 的新包装器全局配置:

 

import { ApplicationConfig } from '@angular/core';import { HOT_GLOBAL_CONFIG, HotGlobalConfig, NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

const globalHotConfig: HotGlobalConfig = {

 license: NON_COMMERCIAL_LICENSE,

 language: 'en',

 themeName: 'ht-theme-main',};

export const appConfig: ApplicationConfig = {

 providers: [

 { provide: HOT_GLOBAL_CONFIG, useValue: globalHotConfig },

 ],};

 

使用服务的新包装器全局配置:

 

import { HotGlobalConfigService, NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

export class AppComponent {

 constructor(private hotConfig: HotGlobalConfigService) {

 this.hotConfig.setConfig({

 themeName: 'ht-theme-main',

 });

 }}

 

步骤 5:更新自定义编辑器

新的包装器在传统以类为基础的方式之外,引入了以元件为基础的编辑器。

 

旧包装器自定义编辑器:

 

import { TextEditor } from 'handsontable/editors/textEditor';

export class CustomEditor extends TextEditor {

 override createElements() {

 super.createElements();

 this.TEXTAREA = document.createElement('input');

 this.TEXTAREA. setAttribute('placeholder', 'Custom placeholder');

 this.TEXTAREA.setAttribute('data-hot-input', 'true');

 this.textareaStyle = this.TEXTAREA.style;

 this.TEXTAREA_PARENT.innerText = '';

 this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);

 }}

 

// Usage in settings

hotSettings = {

 columns: [{ editor: CustomEditor }]};

 

新的封装元件式编辑器:

 

import { Component, ViewChild, ElementRef, ChangeDetectionStrategy } from '@angular/core';

import { FormsModule } from '@angular/forms';

import { HotCellEditorComponent } from '@handsontable/angular-wrapper';

 

@Component({

 selector: 'app-custom-editor',

 imports: [FormsModule],

 standalone: true,

 changeDetection: ChangeDetectionStrategy.OnPush,

 template: `

 <div style="width: 100%; overflow: hidden">

 <input

        #inputElement

 type="text"

 [value]="getValue()"

 (keydown)="onKeyDown($event)"

 style="width: 100%; box-sizing: border-box"

 />

 </div>

 `,})export class CustomEditorComponent extends HotCellEditorComponent<string> {

 @ViewChild('inputElement') inputElement! ElementRef;

 

  onKeyDown(event: KeyboardEvent): void {

 const target = event.target as HTMLInputElement;

 this.setValue(target.value);

 }

 

  onFocus(): void {

 this.inputElement.nativeElement.select();

 }}

 

// Usage in settings

gridSettings: GridSettings = {

 columns: [{ editor: CustomEditorComponent }]};

 

步骤 6:更自定义渲染器

新的包装器除了支持基于函数的渲染器外,还支持基于元件的渲染器。

 

旧的包装器自定义渲染器:

 

export class AppComponent {

 hotSettings = {

 columns: [{

 renderer(instance, td, row, col, prop, value, cellProperties) {

 const img = document.createElement('img');

        img.src = value;

        td.innerText = 『』;

        td.appendChild(img);

 return td;

 }

    }]

  };}

 

新的封装元件式渲染器:

import { Component, ChangeDetectionStrategy } from '@angular/core';

import { HotCellRendererComponent } from '@handsontable/angular-wrapper';

 

@Component({

 selector: 'app-custom-renderer',

 template: `

 <div class="container" [style.backgroundColor]="value">

 {{ value }}

    </div>

 `,

 styles: [`

.container {

 height: 100%;

 width: 100%;

 }

:host {

 justify-content: center;

 align-items: center;

 width: 100%;

 height: 100%;

 padding: 0;

 }

  `],

 standalone: true,

 changeDetection: ChangeDetectionStrategy.OnPush})export class CustomRendererComponent extends HotCellRendererComponent<string> {}

 

// Usage in settings

gridSettings: GridSettings = {

 columns: [{ renderer: CustomRendererComponent }]};

 

步骤 7:更新 CSS 导入

确认您导入的主题 CSS 档案是正确的。

 

CSS 导入 (两个包装器相同):

 

@import'handsontable/styles/handsontable.min.css';

@import 'handsontable/styles/ht-theme-main.min.css';

 

或在 angular.json 中:

 

{

 "styles": [

 "src/styles.scss",

 "node_modules/handsontable/styles/handsontable.min.css",

 "node_modules/handsontable/styles/ht-theme-main.min.css"

 ]}

 

常见迁移问题

问题:无法找到模块 ‘@handsontable/angular’

 

解决方案:确保您已将导入更新为使用 @handsontable/angular-wrapper

 

问题:hot-column 未被识别

解决方案:新包装器不再使用 <hot-column>。在设置对象中将列配置移动到列数组中。

 

问题: “未定义HotTableRegisterer ”

解决方案: 使用 @ViewChild(HotTableComponent) 并访问 hotInstance 属性。

 

问题: “自定义渲染器无法正常工作”

解决方案: 将基于函数的渲染器转换为继承自 HotCellRendererComponent 的组件。

 

问题:自定义编辑器无法正常工作

解决方案:将基于类的编辑器转换为继承自 HotCellEditorComponent 的组件。

 

本迁移指南涵盖了旧版和新版 Angular 包装器之间的主要变化。新版包装器提供了与现代 Angular 模式更好的集成、改进的类型安全性和更易于维护的代码库。

 

5. 引入 pnpm 作为仓库包管理器

自2025年7月1日起,我们已切换至pnpm作为仓库的主要包管理器。

 

随着仓库中包数量的增加,依赖项数量也随之增长。这使得管理依赖项并以一致的方式安装它们变得困难。为解决此问题,我们已切换至使用pnpm作为主要包管理器。

 

这会影响我吗?

除非您需要创建Handsontable或任何包装器的自定义构建,否则此更改不会影响您。

 

如果您正在进行此类操作,则需要使用 pnpm 安装主仓库依赖项。

 

注意:示例和文档包仍由 npm 管理,不属于主 pnpm 工作区。

 

如何迁移?

 

1.安装 pnpm,版本需与根目录 package.json 文件中 packageManager 字段定义的版本一致。

2.如果您之前在仓库的克隆版本上进行过开发,需要删除 node_modules 目录、package-lock.json 文件等。

 

您可以通过运行 npm run clean:node_modules -- --keep-lockfiles 来完成此操作。

3.运行 pnpm install 安装依赖项。

4.所有 npm 命令仍然可用,因此您可以像以前一样构建包,例如通过运行 npm run build。

下一篇:官方 Angular 16+ 版本的 Handsontable 包装器
上一篇:Handsontable 16:全新 Angular 包装器与核心优化

                               

 京ICP备09015132号-996网络文化经营许可证京网文[2017]4225-497号 | 违法和不良信息举报电话:4006561155

                                   © Copyright 2000-2023 北京哲想软件有限公司版权所有 | 地址:北京市海淀区西三环北路50号豪柏大厦C2座11层1105室

                         北京哲想软件集团旗下网站:哲想软件 | 哲想动画

                            华滋生物