今日又係要講返 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'); ``` 咁就可以成功啦 !
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 去解法... 唉... 唔知會唔會整返好...