正在顯示「 2024 年 10 月 」的所有結果


今日又係要講返 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');
```

咁就可以成功啦 !
10月 06, 2024 Docker


Docker 點用就唔係度講了,可以去睇其他文章都得。

今日主要講下點可以係 docker compose 入面淨係 rebuild 一個 container,話說今日要 update docker compose 入面其中一個 image 既 version。雖然 rebuild 晒成個 docker compose 都其實係安全,但係為左安全起見,最好都係可以動最少既野係最安全,所以就好快咁找左一陣 solution。

可以睇下下面呢條:

https://stackoverflow.com/questions/31466428/how-to-restart-a-single-container-with-docker-compose

其實就係用

```sh
$ docker compose up -d --build workername
```

就咁可以解決到了,但係要注意如果有 dependance 的話,佢既 dependance worker 都可能會 rebuild 埋。


其實間唔中中下雷都唔係新鮮事,今次想搞既係 custom component 可以連得返去 parent component 個 viewmodel binding,講多無謂睇 code 最實制。

```js

{ // 整左一個 textfield 叫做 username, bind 左去 viewmodel 個 username 度
	bind: {
		value: '{username}',
	},
	xtype: 'textfield',
	fieldLabel: 'username',
	value: '',
}

```

上面係好正常可以運作,對於個 `textfield` 來講,`value` 係佢呀 `config`。當 viewmodel 個 username 變動時,就會叫埋佢個 `setValue()` 去 update 返 `textfield` 個 `value`。

但係如果你自己整左個 component 出來,咁要做先可以連到呢? 一齊睇下下面呢個。

```js
// 整左個自訂 component 出來
Ext.define('App.MyComponent', {
	extend: 'Ext.panel.Panel',
	alias: 'widget.app-mycomponent',
	config: {
		value: '',
	},
	viewModel: {
		data: {
			value: '',
		},
	},
	layout:{
		type: 'vbox',
	},
	items:[{
		bind: {
			value: '{value}',
		},
		xtype: 'textfield',
		fieldLabel: 'username',
		value: '',
	}]
});

// 然後再 create 一個 panel
Ext.create('Ext.panel.Panel', {
	itemId: 'panel1',
	viewModel: {
		data: {
			value: '',
		},
	},
	layout:{
		type: 'vbox',
	},
	items:[{
		itemId: 'panel2',
		bind: {
			value: '{value}',
		},
		xtype: 'app-mycomponent',
	}]
});
```

現在當 `#panel1` 的 viewModel value 變動時,就會連動埋 bind 左個 component (app-mycomponent) 入面個 value 都會更新。

但係如果我現係係 `#panel2` 度 call 個 `setValue()`,你估會唔會可以反向更新返 `#panel1` 個 viewModel 呢???

答案係唔會 !!!!

除非要加一個 `config` 入去 `#panel2` 個 define 入面,就係 `publishes` 睇下下面:

```js
// 下面係改動左
Ext.define('App.MyComponent', {
	extend: 'Ext.panel.Panel',
	alias: 'widget.app-mycomponent',
	config: {
		value: '',
	},
	publishes: {
		value: true, // 呢度個 value 係指 config 個 value, 咁當呢個 instance call .setValue() 時,如果出面有 viewModel bind 到呢個 value 就會一齊更新
	},
	viewModel: {
		data: {
			value: '',
		},
	},
	layout:{
		type: 'vbox',
	},
	items:[{
		bind: {
			value: '{value}',
		},
		xtype: 'textfield',
		fieldLabel: 'username',
		value: '',
	}]
});
```

呢啲野都係 document 上面寫到唔清唔楚又無好好介紹點用... 搵左勁耐先搵到。

但係仲有樣野解決唔到,就係點樣可以 listen 個 config change? 因為 config 轉左其實我係唔知道佢轉左,所以 update 唔到相應既 component。

雖然可以通過 override setValue() 呢個方法去做,但係唔知點解 ExtJS 7.0.0 個 community edition 係有 bug...

係用唔到 this.callParent(arguments) ...

變左係無得用 override 去解法... 唉... 唔知會唔會整返好...


過去文章
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)