今日又係要講返 ExtJS 既野,話說 Webpack 已經流行左一大段時間,好多野都變得容易管理左好多。但係如果要將一個 Framework 搬去 Webpack 度用就實在係有啲困難,因為 Framework 通常都會用到好多好底層的功能。而呢啲功能本身既前題係運行個 Scope 有自己本身固定既 Context,運單啲講 Webpack 當 Bundle 完個 package 之後,入面所運行既 JS 係有自己個 Context,係同 Browser 入面 html embed 的 Javascript Context 唔一樣,會有可能引起 Webpack 打包後的 JS 運行唔到。

### 自訂 ExtJS Component

如果你要自訂一個 Component,最起碼都要設定佢最基本既行為,例如當個 Component 建立時需要係 runtime 拎一啲 condition 來決定佢畫出來個樣。或者在建立後修改一下 child component 的數值等等。呢個時候如果睇官方個 Guide 係會教你可以用 `initComponent()` 去改寫 Component 生成時的行為,當中有一個 statement 係 `this.callParent()`。佢係類似 Java 入面 `super()` 的 method,用來叫返 override 左既 super class 個 method。正常用係無問題既,但係如果當你係魔改配合 Webpack 使用的話,就會出 Error。

睇下呢段 Code:

```js
// 定義一個 component
Ext.define('MyApp.view.YourComponent', {
	
	// extend 'Ext.window.Window' 呢個 component
	extend: 'Ext.window.Window',
	
	// 原本個 title
	title: 'foo',
	
	// 自動顯示
	autoShow: true,
	
	// 用 initComponent 來改寫
	initComponent: function(...args) {
		
		// 生成 component
		this.callParent(...args);
		
		// 改下個 title
		this.setTitle('bar');
	},
});

// 生成 class
Ext.create('MyApp.view.YourComponent');
```

之後就會出 Error :

```js
Uncaught TypeError: Cannot read properties of null (reading '$owner') at constructor.callParent
```

### 用 beforerender event 

上網找左好耐好耐都找唔到有效既方法,後來用左 beforerender event 暫時頂住先,後來又改用 added event 來頂住,但係都只係治標不治本既方法。

使用 beforerender 來 workaround:

```js
// 定義一個 component
Ext.define('MyApp.view.YourComponent', {
	
	// extend 'Ext.window.Window' 呢個 component
	extend: 'Ext.window.Window',
	
	// 原本個 title
	title: 'foo',
	
	// 自動顯示
	autoShow: true,
	
	// 設定 listeners
	listeners: {
		
		// beforerender 係生命週期比較早的 event
		beforerender: view => {
			
			// 改下個 title
			view.setTitle('bar')
		},
	},
});

// 生成 class
Ext.create('MyApp.view.YourComponent');
```

### Strict Mode 問題

其實 this.callParent() 係會用到 arguments.callee 同埋 arguments.caller 來配合達成到 call 返 override 的 method。

所以在 Strict Mode 底下會有機會用唔到 this.callParent()...

### Workaround 方法

之後睇到有一篇大神講 ExtJS + Webpack 的使用方法,入面提到如果要用 this.callParent() 的話需要使用到 class prototype 去完成,我再測試一下法現成功了!

實現方法如下:

```js
// 定義一個 component
Ext.define('MyApp.view.YourComponent', {
	
	// extend 'Ext.window.Window' 呢個 component
	extend: 'Ext.window.Window',
	
	// 原本個 title
	title: 'foo',
	
	// 自動顯示
	autoShow: true,
	
	// 用 initComponent 來改寫
	initComponent: function(...args) {

		// 生成 component
		// this.callParent(...args); // 會出 Error

		// workaround 方法, 主要係 call 返 extend component prototype 個 method, 再放返現在 context 個 this 入去
		Ext.window.Window.prototype.initComponent.call(this, ...args);
		
		// 改下個 title
		this.setTitle('bar');
	},
});

// 生成 class
Ext.create('MyApp.view.YourComponent');
```

咁就可以成功啦 !
過去文章
2025 (9)
4 (5)
3 (1)
2 (3)
2024 (25)
11 (3)
10 (3)
9 (1)
3 (18)
2022 (6)
10 (1)
6 (2)
5 (1)
3 (1)
1 (1)
2021 (21)
11 (7)
7 (1)
6 (2)
5 (2)
4 (6)
3 (2)
2 (1)
2020 (92)
12 (1)
11 (2)
10 (4)
9 (10)
8 (5)
7 (1)
6 (3)
5 (1)
4 (4)
3 (25)
2 (7)
1 (29)
2019 (57)
12 (25)
11 (7)
9 (25)