從 Handsontable 15.3 遷移到 Handsontable 16.0,于 09/07/2025 發(fā)布。
更多關于此版本的信息,請參閱 16.0.0 版本的博客文章。
1. 介紹新的 DOM 結(jié)構(gòu)
在 Handsontable 16.0 中,我們改變了表格在 DOM 中的掛載方式。以前,您提供的容器 <div> 成為表格的根元素?,F(xiàn)在,該容器作為一個掛載點,Handsontable 在其中創(chuàng)建并注入自己的根元素。
以下是新舊 DOM 結(jié)構(gòu)的并排比較:
舊的 DOM 結(jié)構(gòu):
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 結(jié)構(gòu):
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 變量系統(tǒng)進行了重大改進,調(diào)整了主題顏色、變量順序,并提供了更好的定制選項。以下是主要的變更:
新的 CSS 變量
我們引入了新的變量,讓自定義變得更容易:
l--ht-letter-spacing: 控制字母間距,以改善可讀性和視覺外觀。
l--ht-radio-*: 使單選輸入的樣式更準確。
l--ht-cell-read-only-background-color: 實現(xiàn)更好的只讀單元格背景自定義。
l--ht-checkbox-indeterminate: 允許您對復選框的不定狀態(tài)進行風格設置。
重命名的 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. 檢查您的自定義變量名稱是否符合新的命名規(guī)范
2. 更新變量引用以使用新的單選按鈕輸入(僅當復選框變量發(fā)生更改時)
3. 利用新變量實現(xiàn)更精細的控制
3. 更新自定義邊框的位置
在版本 16.0 中,我們更新了自定義邊框的定位方式,以提高準確性和一致性。此更改會影響邊框的視覺定位,特別是對于具有自定義邊框的單元格。
發(fā)生了什么變化?
邊框位置已調(diào)整,以防止與相鄰單元格和標題重疊。
為何這是重大變更?
雖然可能性極低,但若您的應用依賴特定邊框位置,或基于邊框位置實現(xiàn)了自定義樣式,可能需要更新樣式。
版本 16.0 中邊框的視覺外觀與版本 15.3 相比將略有不同。
遷移說明
無需修改代碼——新版本會自動處理這些改進。
4. 切換至新的 Angular 包裝器(適用于 Angular 16+)
Handsontable 16.0 引入了全新的 Angular 包裝器。該包裝器旨在與現(xiàn)代 Angular 應用程序?qū)崿F(xiàn)更佳集成并提升開發(fā)體驗。若您使用 Angular 16 或更高版本,建議遷移至新包裝器。
為何要切換至新 Angular 包裝器?
• 組件化架構(gòu):新包裝器采用 Angular 的組件化架構(gòu),允許您將自定義編輯器和渲染器實現(xiàn)為 Angular 組件。
• 改進的 TypeScript 支持:新包裝器提供了更完善的 TypeScript 定義。
• 獨立組件支持:新包裝器全面支持 Angular 的獨立組件,使其在現(xiàn)代 Angular 應用中更易于使用。
• 全局配置:新包裝器通過依賴注入提供了更好的全局配置管理。
• 模板語法:簡化的模板語法減少了冗余代碼,使配置更易于維護。
• 實例訪問:現(xiàn)在可以通過 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 實例交互的方式已發(fā)生變化。
舊的包裝器實例引用:
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:更新自定義編輯器
新的包裝器在傳統(tǒng)以類為基礎的方式之外,引入了以元件為基礎的編輯器。
舊包裝器自定義編輯器:
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:更新自定義渲染器
新的包裝器除了支持基于函數(shù)的渲染器外,還支持基于元件的渲染器。
舊的包裝器自定義渲染器:
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>。在設置對象中將列配置移動到列數(shù)組中。
問題: “未定義HotTableRegisterer ”
解決方案: 使用 @ViewChild(HotTableComponent) 并訪問 hotInstance 屬性。
問題: “自定義渲染器無法正常工作”
解決方案: 將基于函數(shù)的渲染器轉(zhuǎn)換為繼承自 HotCellRendererComponent 的組件。
問題:自定義編輯器無法正常工作
解決方案:將基于類的編輯器轉(zhuǎn)換為繼承自 HotCellEditorComponent 的組件。
本遷移指南涵蓋了舊版和新版 Angular 包裝器之間的主要變化。新版包裝器提供了與現(xiàn)代 Angular 模式更好的集成、改進的類型安全性和更易于維護的代碼庫。
5. 引入 pnpm 作為倉庫包管理器
自2025年7月1日起,我們已切換至pnpm作為倉庫的主要包管理器。
隨著倉庫中包數(shù)量的增加,依賴項數(shù)量也隨之增長。這使得管理依賴項并以一致的方式安裝它們變得困難。為解決此問題,我們已切換至使用pnpm作為主要包管理器。
這會影響我嗎?
除非您需要創(chuàng)建Handsontable或任何包裝器的自定義構(gòu)建,否則此更改不會影響您。
如果您正在進行此類操作,則需要使用 pnpm 安裝主倉庫依賴項。
注意:示例和文檔包仍由 npm 管理,不屬于主 pnpm 工作區(qū)。
如何遷移?
1.安裝 pnpm,版本需與根目錄 package.json 文件中 packageManager 字段定義的版本一致。
2.如果您之前在倉庫的克隆版本上進行過開發(fā),需要刪除 node_modules 目錄、package-lock.json 文件等。
您可以通過運行 npm run clean:node_modules -- --keep-lockfiles 來完成此操作。
3.運行 pnpm install 安裝依賴項。
4.所有 npm 命令仍然可用,因此您可以像以前一樣構(gòu)建包,例如通過運行 npm run build。
京ICP備09015132號-996 | 違法和不良信息舉報電話:4006561155
© Copyright 2000-2026 北京哲想軟件有限公司版權(quán)所有 | 地址:北京市海淀區(qū)西三環(huán)北路50號豪柏大廈C2座11層1105室
北京哲想軟件集團旗下網(wǎng)站:哲想軟件 | 哲想動畫