
ã¿ãªããããã«ã¡ã¯ã Ext JS 5ã®ãªãªãŒã¹ããå€ãã®æéãçµéããMVVMãã¿ãŒã³ã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãéçºããå¯èœæ§ã瀺ãããŸããã ãã®éãç§ã¯è©±ããããããã€ãã®å°é£ã«ééããŸããã
ãããããExt JS 4ïŒããã³ä»¥åã¯Sencha TouchïŒã§ã³ã³ããŒãã³ããäœæãããšãããã®æ§æããããã£ã¯
configãªããžã§ã¯ãã§å®£èšãããããããã«å¯ŸããŠã²ãã¿ãŒãšã»ãã¿ãŒãèªåçã«äœæãããŸããã ãã¹ãŠã®ãã³ãã©ãæåã§èšè¿°ããã®ã¯å€å°é¢åã§ãããããã¯æšæºçãªã¢ãããŒãã§ããã
MVVMã䜿çšããExt JSã®5çªç®ã®ããŒãžã§ã³ã§ã¯ãã«ãŒãã³ã®å€§éšåãç°¡åã«åãé€ãããšãã§ããŸããæ§æããããã£ãšãã®ãã³ãã©ãŒãåé€ãã代ããã«ç®çã®ããããã£ãŸãã¯åŒViewModelã«ãã€ã³ãããŸãã ã³ãŒããã¯ããã«å°ãããªããèªã¿ããããåäžããŸããã
ããããã«ãã»ã«åã®åé¡ãå¿é
ã§ããã éçºããã»ã¹äžã«ãæ©èœã®äžéšãå¥ã®ã³ã³ããŒãã³ãã«å
¥ããŠåå©çšãããå Žåã¯ã©ããªããŸããïŒ ç¬èªã®ViewModelãäœæããå¿
èŠããããŸããïŒ ã³ã³ããŒãã³ãã®ç¶æ
ãå€æŽããæ¹æ³ïŒViewModelã«çŽæ¥ã¢ã¯ã»ã¹ããããæ§æããããã£ãšãããªãã¯ã»ãã¿ãŒã䜿çšãã䟡å€ããããŸããïŒ
ãã®åé¡ããã®ä»ã®åé¡ã«ã€ããŠã®èããããã³ãã¡ã€ã«ã®äŸ-ã«ããã®äžã§ã
ããŒã1. ViewModelã®äœ¿çš
ããšãã°ãäžéšã®ãŠãŒã¶ãŒã®ããŒãã«ãäœæããŠã¿ãŸãããã 圌女ã¯ãšã³ããªãè¿œå ããã³åé€ã§ããŸãããå¿
èŠã«å¿ããŠèªã¿åãå°çšã¢ãŒãã«åãæ¿ããŸãã ãŸãã匷調衚瀺ããããŠãŒã¶ãŒã®ååãåé€ãã¿ã³ã«å«ããããã«ããŸãã
äŸ1.æšæºçãªã¢ãããŒã
MVVMã䜿çšããã«ãããè¡ãã«ã¯ã©ãããã°ããã§ããããïŒ
Sencha Fiddleã§ã®çºãFiddle.view.UsersGridExt.define('Fiddle.view.UsersGrid', { extend: 'Ext.grid.Panel', xtype: 'usersgrid', config: { readOnly: null }, defaultListenerScope: true, tbar: [{ text: 'Add', itemId: 'addButton' }, { text: 'Remove', itemId: 'removeButton' }], columns: [{ dataIndex: 'id', header: 'id' }, { dataIndex: 'name', header: 'name' }], listeners: { selectionchange: 'grid_selectionchange' }, updateReadOnly: function (readOnly) { this.down('#addButton').setDisabled(readOnly); this.down('#removeButton').setDisabled(readOnly); }, grid_selectionchange: function (self, selected) { var rec = selected[0]; if (rec) { this.down('#removeButton').setText('Remove ' + rec.get('name')); } } });
èªã¿åãå°çšã¢ãŒãã®èšå® readOnlyButton_click: function (self) { this.down('usersgrid').setReadOnly(self.pressed); }
ããªãåé·ã§ãããããã¯æããã§ããã³ã³ããŒãã³ãã®ãã¹ãŠã®ããžãã¯ã¯å
éšã«ãããŸãã ViewControllersã䜿çšã§ããããã«äºçŽããå¿
èŠãããããããã³ã³ããŒãã³ãã®äžéšãšèŠãªãããŸãããäŸã§ã¯ãããã䜿çšããã«å®è¡ã§ããŸãã
äŸ2. MVVMã®è¿œå
ã³ãŒããã³ãã©ãŒãåé€ãããã€ã³ãã£ã³ã°ïŒãã€ã³ãïŒã«çœ®ãæããŸãããã
Sencha Fiddleã§ã®çºãFiddle.view.UsersGrid Ext.define('Fiddle.view.UsersGrid', { extend: 'Ext.grid.Panel', xtype: 'usersgrid', reference: 'usersgrid', viewModel: { data: { readOnly: false } }, tbar: [{ text: 'Add', itemId: 'addButton', bind: { disabled: '{readOnly}' } }, { text: 'Remove', itemId: 'removeButton', bind: { disabled: '{readOnly}', text: 'Remove {usersgrid.selection.name}' } }], columns: [{ dataIndex: 'id', header: 'id' }, { dataIndex: 'name', header: 'name' }] });
èªã¿åãå°çšã¢ãŒãã®èšå® readOnlyButton_click: function (self) { this.down('usersgrid').getViewModel().set('readOnly', self.pressed); }
ãã£ãšè¯ãèŠããŸãããïŒ ç¹ã«ãreadOnly以å€ã«ããã«å€ãã®å
¥åãã©ã¡ãŒã¿ãŒãååšããå¯èœæ§ããããšæ³åããå Žåããã®å·®ã¯éåžžã«å€§ãããªããŸãã
ãããã®äŸãæ¯èŒãããšãããã€ã質åããããŸãïŒ
質å1. ViewModelãäœæããå Žæã¯ã©ãã§ããïŒ å€éšã³ã³ããã«èšè¿°ã§ããŸããïŒ-äžæ¹ã§ã¯å¯èœã§ããã匷åãªæ¥ç¶ãååŸããŸãããã®ã³ã³ããŒãã³ããå¥ã®å Žæã«ç§»åãããã³ã«ãæ°ããã³ã³ããã®ViewModelã«readOnlyããããã£ãè¿œå ããå¿
èŠããããŸãã ééããç¯ãã®ã¯éåžžã«ç°¡åã§ãããäžè¬ã«ã芪ã³ã³ããã¯ãããã«è¿œå ãããã³ã³ããŒãã³ãã®å
éšãç¥ãã¹ãã§ã¯ãããŸããã
質å2.ãªãã¡ã¬ã³ã¹ãšã¯äœã§ããïŒ ãªãã³ã³ããŒãã³ãå
ã«ç»é²ããã®ã§ããïŒ-åç
§ã¯ãViewModelã®idã³ã³ããŒãã³ãã«é¡äŒŒããŠããŸãã [åé€]ãã¿ã³ã«ã¯éžæãããŠãŒã¶ãŒã®ååãžã®ãã€ã³ãããããããç»é²ããŸããããåç
§ãæå®ããªããšæ©èœããŸããã
質å3.ãããè¡ãã®ã¯æ£ããã§ããïŒ 1ã€ã®ã³ã³ããã«2ã€ã®ã€ã³ã¹ã¿ã³ã¹ãè¿œå ãããå Žå-åç
§ã1ã€ã«ãªããŸããïŒ-ã¯ããããã¯ééãã§ãã ããã解決ããæ¹æ³ã«ã€ããŠèããå¿
èŠããããŸãã
質å4.å€éšããã³ã³ããŒãã³ãã®ViewModelã«ã¢ã¯ã»ã¹ããã®ã¯æ£ããã§ããïŒ-äžè¬ã«ãããã¯æ©èœããŸãããããã¯ã³ã³ããŒãã³ãã®å
éšãžã®ã¢ããŒã«ã§ãã ç§ã¯ãçè«çã«ã¯ã圌ãViewModelãæã£ãŠãããã©ããã«èå³ãããã¹ãã§ã¯ãããŸããã ãã®ç¶æ
ãå€æŽãããå Žåã¯ã察å¿ããã»ãã¿ãŒããã€ãŠæå³ãããšããã«åŒã³åºãå¿
èŠããããŸãã
質å5.æ§æããããã£ã䜿çšããåæã«ãããã®å€ã«ãã€ã³ãããããšã¯å¯èœã§ããïŒ çµå±ã®ãšããããã®ã±ãŒã¹ã®ããã¥ã¡ã³ãã«ã¯publishesããããã£ããããŸããïŒ-ããªãã¯ã§ããŸããããã¯è¯ãã¢ã€ãã¢ã§ãã ãã¡ããããã€ã³ãã£ã³ã°ã§åç
§ãæ瀺çã«æå®ããããšã«é¢ããåé¡ãé€ããŸãã ãã®å Žåã®readOnlyã¢ãŒãèšå®ã¯ãäŸ1ãšåãã«ãªããŸã-ãããªãã¯ã»ãã¿ãŒã䜿çšïŒ
äŸ3. Fiddle.view.UsersGrid Ext.define('Fiddle.view.UsersGrid', { extend: 'Ext.grid.Panel', xtype: 'usersgrid', reference: 'usersgrid', viewModel: { }, config: { readOnly: false }, publishes: ['readOnly'], tbar: [{ text: 'Add', itemId: 'addButton', bind: { disabled: '{usersgrid.readOnly}' } }, { text: 'Remove', itemId: 'removeButton', bind: { disabled: '{usersgrid.readOnly}', text: 'Remove {usersgrid.selection.name}' } }], columns: [{ dataIndex: 'id', header: 'id' }, { dataIndex: 'name', header: 'name' }] });
Sencha Fiddleã§ã®çºãä»ã®äœã
ããã¯æåŸã®è³ªåã«é¢ä¿ããŸãã å€éšã³ã³ããããå
éšã³ã³ããŒãã³ãã®ããããã£ïŒããŒãã«ã®éžæãããè¡ãªã©ïŒã«ãã€ã³ãããå Žå-ãã€ã³ãã¯æ©èœããŸããïŒ
蚌æ ïŒã ããã¯ãå
éšã³ã³ããŒãã³ããç¬èªã®ViewModelãæã€ãšããã«çºçããŸã-ããããã£ã®å€æŽã¯ãã®å
éšã§ã®ã¿ïŒããæ£ç¢ºã«ã¯ãæåã®éå±€ã§ïŒå
¬éãããŸãã å
¬åŒãã©ãŒã©ã ã§ã¯ããã®è³ªåãäœåºŠãæèµ·ãããŸãããæ²é»ããªãããç»é²ããããªã¯ãšã¹ãïŒEXTJS-15503ïŒã®ã¿ããããŸãã ã€ãŸãããã®èŠ³ç¹ããKDPVã®åçãèŠããšã次ã®ããšãããããŸãã

ã€ãŸã ã³ã³ãã1ã¯ãã³ã³ãã2ãé€ããã¹ãŠã®å
éšã³ã³ããŒãã³ãã«ãã€ã³ãã§ããŸããããã¯ãã³ã³ãã3ãšåãã§ãããã¹ãŠã®ã³ã³ããŒãã³ãã¯ãç¬èªã«å§ãŸãViewModeléå±€ã®æåã®ããããã£ã®å€æŽã®ã¿ãçºè¡ããŸãã
æ
å ±ãå€ãããïŒ ãããç解ããŠã¿ãŸãããã
ããŒã2ã
èŠå 以äžã«èª¬æãããœãªã¥ãŒã·ã§ã³ã¯å®éšçãªãã®ã§ãã äžäœäºææ§ã¯ãã¹ãŠã®å Žåã«ä¿èšŒãããããã§ã¯ãªãããã泚æããŠäœ¿çšããŠãã ããã ã³ã¡ã³ããä¿®æ£ããã®ä»ã®ãã«ããæè¿ããŸãã è¡ããïŒãããã£ãŠãMVVMã䜿çšããã³ã³ããŒãã³ãéçºã®ããžã§ã³ãæåã«å®åŒåããããšæããŸãã
- ã³ã³ããŒãã³ãã®ç¶æ
ãå€æŽããã«ã¯ãæ§æããããã£ãšãã®ãããªãã¯ã»ãã¿ãŒã䜿çšããŸãã
- ç¬èªã®æ§æããããã£ïŒã³ã³ããŒãã³ãå
ïŒã«ãã€ã³ãããæ©èœããããŸãã
- ç¬èªã®ViewModelããããã©ããã«é¢ä¿ãªããå€éšããã³ã³ããŒãã³ãã®ããããã£ã«ãã€ã³ãããæ©èœããããŸãã
- ããŒã¿ViewModel'eyã®éå±€å
ã§ã®ååã®äžææ§ã«ã€ããŠèããªãã§ãã ããã
ä¿®æ£çªå·1ã å€æŽãå
¬éããŸã
ããšãã°ããã€ã³ã3ããããç°¡åãªãã®ããå§ããŸããããããã§ã®ãã€ã³ãã¯ã
Ext.mixin.Bindable
äžçŽ
Ext.mixin.Bindable
ãšãã®
publishStateã¡ãœããã§ãã å
éšãèŠããšãå€æŽãViewModelã§å
¬éãããŠããããšãããããŸããViewModelã¯éå±€ã®æåã§ãã 芪ViewModelã«ããããèªèãããŸãããïŒ
publishState: function (property, value) { var me = this, vm = me.lookupViewModel(), parentVm = me.lookupViewModel(true), path = me.viewModelKey; if (path && property && parentVm) { path += '.' + property; parentVm.set(path, value); } Ext.mixin.Bindable.prototype.publishState.apply(me, arguments); }
ã« | åŸ |
---|
 |  |
Sencha Fiddleã®ã㢠ã
ä¿®æ£çªå·2ã ç¬èªã®æ§æããããã£ã«é¢é£ä»ããããŠããŸã
ãã©ã°ã©ã2ã«é¢ããŠã å€éšããã³ã³ããŒãã³ãã®ããããã£ã«ã¢ã¿ããããæ©äŒãããããå
éšããã¢ã¿ããããæ©äŒããªãããšã¯äžå
¬å¹³ã«æããŸãã ãããã
reference
瀺ã
reference
-å¯èœã§ãããããã¯ããŸãçŸãããªãã·ã§ã³ã§ã¯ãªããšå€æããã®ã§ãå°ãªããšãæåã§ããè¯ãæ¹æ³ãå®è¡ã§ããŸãã
Fiddle.view.UsersGrid Ext.define('Fiddle.view.UsersGrid', { extend: 'Ext.grid.Panel', xtype: 'usersgrid', viewModel: { data: { readOnly: false, selection: null } }, config: { readOnly: false }, tbar: [{ text: 'Add', itemId: 'addButton', bind: { disabled: '{readOnly}' } }, { text: 'Remove', itemId: 'removeButton', bind: { disabled: '{readOnly}', text: 'Remove {selection.name}' } }],
Sencha Fiddleãã¢è¯ãèŠããŸãããïŒ å€åŽã§ã¯æ瀺
reference
ãšãã€ã³ãããå
åŽ-ãªãã§ãã€ã³ãããŸãã çŸåšãã³ã³ããŒãã³ãã³ãŒãã¯å€æŽãããŠããŸããã ããã«ã2ã€ã®ã³ã³ããŒãã³ãã1ã€ã®ã³ã³ããã«è¿œå ããååã
reference
reference
-ãããŠããã¹ãŠãåäœããŸãïŒ
èªååããïŒ åã®
publishState
ã¡ãœããã«è¿œå ããŸãã
if (property && vm && vm.getView() == me) { vm.set(property, value); }
以äžã§ãã æ§æããããã£ãžã®ãã€ã³ãã£ã³ã°ãã©ã®çšåºŠç°¡æœã«ãªã£ãããè©äŸ¡ããŸãã
Fiddle.view.UsersGrid Ext.define('Fiddle.view.UsersGrid', { extend: 'Ext.grid.Panel', xtype: 'usersgrid', viewModel: { }, config: { readOnly: false }, publishes: ['readOnly'], tbar: [{ text: 'Add', itemId: 'addButton', bind: { disabled: '{readOnly}' } }, { text: 'Remove', itemId: 'removeButton', bind: { disabled: '{readOnly}', text: 'Remove {selection.name}' } }], columns: [{ dataIndex: 'id', header: 'id' }, { dataIndex: 'name', header: 'name' }] });
Ext.ux.mixin.Bindable Ext.define('Ext.ux.mixin.Bindable', { initBindable: function () { var me = this; Ext.mixin.Bindable.prototype.initBindable.apply(me, arguments); me.publishInitialState(); }, publishState: function (property, value) { var me = this, vm = me.lookupViewModel(), parentVm = me.lookupViewModel(true), path = me.viewModelKey; if (path && property && parentVm) { path += '.' + property; parentVm.set(path, value); } Ext.mixin.Bindable.prototype.publishState.apply(me, arguments); if (property && vm && vm.getView() == me) { vm.set(property, value); } }, publishInitialState: function () { var me = this, state = me.publishedState || (me.publishedState = {}), publishes = me.getPublishes(), name; for (name in publishes) { if (state[name] === undefined) { me.publishState(name, me[name]); } } } }, function () { Ext.Array.each([Ext.Component, Ext.Widget], function (Class) { Class.prototype.initBindable = Ext.ux.mixin.Bindable.prototype.initBindable; Class.prototype.publishState = Ext.ux.mixin.Bindable.prototype.publishState; Class.mixin([Ext.ux.mixin.Bindable]); }); });
Sencha Fiddleã®ã㢠ã
ä¿®æ£çªå·3ã ViewModelãšã³ã³ããŒãã³ãã®åé¢
æãé£ããïŒ
段èœ4 ã å®éšã®çŽåºŠã®ããã«ã以åã®ä¿®æ£ã¯äœ¿çšãããŸããã æå®ïŒåãæ§æããããã£ãæã€2ã€ã®ãã¹ããããã³ã³ããŒãã³ã-color ãããããViewModelã䜿çšããŠãã®å€ã«ãã€ã³ãããŸãã å¿
é ïŒå
éšã³ã³ããŒãã³ãã®ããããã£ãå€éšã®ããããã£ã«ãã€ã³ãããŸãã ãã£ãŠã¿ãŸããïŒ
Fiddle.view.OuterContainer Ext.define('Fiddle.view.OuterContainer', {
Fiddle.view.InnerContainer Ext.define('Fiddle.view.InnerContainer', {
Sencha Fiddleã®ã㢠ã

ã·ã³ãã«ã«èŠããŸãããæ©èœããŸããã ãªãã§ïŒ ããèŠããšã次ã®èšé²åœ¢åŒã¯ãŸã£ããåãã ããã§ãã
ãªãã·ã§ã³1
Ext.define('Fiddle.view.OuterContainer', {
| Ext.define('Fiddle.view.InnerContainer', {
|
ãªãã·ã§ã³2
Ext.define('Fiddle.view.OuterContainer', {
| Ext.define('Fiddle.view.InnerContainer', {
|
泚æã質åïŒ å
éšã³ã³ããã§ãã€ã³ãããViewModelã®
color
ããããã£ã«ïŒ å¥åŠãªããšã«ãäž¡æ¹ã®å Žå-å
éšãžã åæã«ãããã¥ã¡ã³ããšããããŒã®å³ããå€æãããšãViewModelããŒã¿ãšå€éšã³ã³ãããŒã¯ãViewModelããŒã¿ãšå
éšã³ã³ãããŒã®ãããã¿ã€ãã§ãã ãããŠä»¥æ¥ æåŸã®
color
å€ãåå®çŸ©ããããããã¿ã€ãã®å€ãå€æŽãããŠããç¶æ¿è
ïŒ
null
ïŒã®å€ã¯åããŸãŸã§ãã ã€ãŸã ååãšããŠãã°ãªããã¯ãããŸãã-ãããã¹ãã§ãã
ã©ãããã°ç¶æ³ããæãåºãããšãã§ããŸããïŒ æãæçœãªããšã¯ãå
éšViewModelãã
color
ãåé€ããããšã§ãã 次ã«ã
updateColor
ãã³ãã©ãŒãåé€ããå¿
èŠããããŸãã ãããŠãæ§æããããã£ãçå
ã«ãããŸãïŒ èŠªã³ã³ãããåžžã«
color
ããããã£ãæã€ViewModelãæã€ããšãæåŸ
ããŸãããã
ãã©ããïŒ åžæã¯ç§ãã¡ãæ±ã£ãŠãããã®ã§ã¯ãããŸããã å¥ã®ãªãã·ã§ã³ã¯ããã¹ãŠã®æ§æããããã£ïŒããã³ViewModelãã£ãŒã«ãïŒã®ååãå€æŽããŠãéè€ããªãããã«ããããšã§ãïŒçè«äžïŒïŒ
outerContainerColor
ããã³
innerContainerColor
ã ãããããããä¿¡é Œã§ããŸããã 倧èŠæš¡ãªãããžã§ã¯ãã§ã¯ãéåžžã«å€ãã®ååããããå®éã«ã¯ããŸãããŸãæ©èœããŸããã
å€éšã³ã³ãããèšè¿°ãããšãã«ããªãããã®æ¹æ³ã§ãã€ã³ãã£ã³ã°ãæå®ããã®ã¯çŽ æŽãããããšã§ãã
Ext.define('Fiddle.view.OuterContainer', { viewModel: { data: { color: null } }, items: [{ xtype: 'innercontainer', bind: { color: '{outercontainer.color}'
ç§ã¯èŠããããšã¯ãããŸããããããè¡ãããšãã§ããŸã
Ext.ux.app.SplitViewModel + Ext.ux.app.bind.Template Ext.define('Ext.ux.app.SplitViewModel', { override: 'Ext.app.ViewModel', config: { name: undefined, uniqueName: undefined, prefix: undefined }, nameDelimiter: '|', expressionRe: /^(?:\{[!]?(?:(\d+)|([a-z_][\w\-\.|]*))\})$/i, uniqueNameRe: /-\d+$/, privates: { applyData: function (newData, data) { newData = this.getPrefixedData(newData); data = this.getPrefixedData(data); return this.callParent([newData, data]); }, applyLinks: function (links) { links = this.getPrefixedData(links); return this.callParent([links]); }, applyFormulas: function (formulas) { formulas = this.getPrefixedData(formulas); return this.callParent([formulas]); }, bindExpression: function (path, callback, scope, options) { path = this.getPrefixedPath(path); return this.callParent([path, callback, scope, options]); } }, bind: function (descriptor, callback, scope, options) { if (Ext.isString(descriptor)) { descriptor = this.getPrefixedDescriptor(descriptor); } return this.callParent([descriptor, callback, scope, options]); }, linkTo: function (key, reference) { key = this.getPrefixedPath(key); return this.callParent([key, reference]); }, get: function (path) { path = this.getPrefixedPath(path); return this.callParent([path]); }, set: function (path, value) { if (Ext.isString(path)) { path = this.getPrefixedPath(path); } else if (Ext.isObject(path)) { path = this.getPrefixedData(path); } this.callParent([path, value]); }, applyName: function (name) { name = name || this.type || 'viewmodel'; return name; }, applyUniqueName: function (id) { id = id || Ext.id(null, this.getName() + '-'); return id; }, applyPrefix: function (prefix) { prefix = prefix || this.getUniqueName() + this.nameDelimiter; return prefix; }, getPrefixedData: function (data) { var name, newName, value, result = {}; if (!data) { return null; } for (name in data) { value = data[name]; newName = this.getPrefixedPath(name); result[newName] = value; } return result; }, getPrefixedDescriptor: function (descriptor) { var descriptorParts = this.expressionRe.exec(descriptor); if (!descriptorParts) { return descriptor; } var path = descriptorParts[2];
ããã§ããããæžããŸãïŒäºçŽãããŠããããããã€ã³ãã§ã¯ãªãç°ãªãæåã®ã¿ïŒïŒ
Ext.define('Fiddle.view.OuterContainer', { viewModel: { name: 'outercontainer', data: { color: null } }, items: [{ xtype: 'innercontainer', bind: { color: '{outercontainer|color}' } }] })
Sencha Fiddleã®ã㢠ã

ã€ãŸã ããå
·äœçãª
bind
ãViewModelã®
ååã§ç»é²ããŸããã ViewModelã³ãŒããå¥ã®ãã¡ã€ã«ã«ããå Žåãååã¯çç¥ã§ããŸã-aliasããååŸãããŸãã ãã¹ãŠããã以äžã®å€æŽã¯å¿
èŠãããŸããã ãã¬ãã£ãã¯ã¹ãªãã§ãå€ãæ¹æ³ã§ViewModelã«ãã€ã³ãã§ããŸãã ç¬èªã®ViewModelãæã€ïŒãŸãã¯è¡šç€ºãããïŒãã¹ããããã³ã³ããŒãã³ãã«å¯ŸããŠæå®ããŸãã
ãã®æ¡åŒµæ©èœã®å
éšã§ã¯ãååïŒ
name
ãŸãã¯
alias
ïŒãšäžæã®
id
ïŒã³ã³ããŒãã³ãã®å ŽåïŒã§æ§æããããã¬ãã£ãã¯ã¹ãViewModelãã£ãŒã«ãã«è¿œå ãããŸãã 次ã«ãã³ã³ããŒãã³ãã®åæåæã«ããã¹ãŠã®ãã€ã³ãã£ã³ã°ã®ååã«è¿œå ãããŸãã
ããã¯äœãäžããŸããïŒ
ViewModelããŒã¿ã¯éå±€çã«åå²ãããŸãã ãã€ã³ãã£ã³ã°ã§ã¯ãViewModelãåç
§ããŠããããããã£ã§å
·äœçã«è¡šç€ºãããŸãã ããã§ãViewModeléå±€å
ã§ã®ããããã£ã®è€è£œã«ã€ããŠå¿é
ããå¿
èŠããªããªããŸããã 芪ã³ã³ãããèŠãªããŠããåå©çšå¯èœãªã³ã³ããŒãã³ããäœæã§ããŸãã è€éãªã³ã³ããŒãã³ãã®ä»¥åã®ä¿®æ£ã«é¢é£ããŠãã³ãŒãã®éã¯å€§å¹
ã«åæžãããŸãã
ââ1-3ãä¿®æ£ããæåŸã®äŸãã ãããã®æ®µéã§ã¯ãäžäœäºææ§ã¯éšåçã«å€±ãããŸãã ã€ãŸã ã³ã³ããŒãã³ããéçºãããšãã«ã芪ã³ã³ããŒãã³ãã®ViewModelã«ããããããã£ã®ååšã«äŸåããŠããå ŽåãæåŸã®ä¿®æ£ã«ãããã¹ãŠãå£ããŸãã芪ViewModelã®åå/ãšã€ãªã¢ã¹ã«å¯Ÿå¿ãããã€ã³ãã£ã³ã°ã«ãã¬ãã£ãã¯ã¹ãè¿œå ããå¿
èŠããããŸãã
åèš
æ¡åŒµæ©èœã®ãœãŒã¹ã³ãŒãã¯GitHubã«ãããŸããããããïŒ
github.com/alexeysolonets/extjs-mvvm-extensionsãããã¯ããã€ãã®ãããžã§ã¯ãã§äœ¿çšãããŠããŸã-é£è¡ã¯éåžžãããå€ããªã£ãŠããŸãã ããå°ãªãã³ãŒããæžãããšã«å ããŠãã³ã³ããŒãã³ããã©ã®ããã«æ¥ç¶ãããŠãããã«ã€ããŠã®æ確ãªç解ããããŸãã
ç§ã«ãšã£ãŠã¯ã1ã€ã®è³ªåããã
override
ãã¹ãŠã®ViewModelã«äœçšããã°ããŒãã«ãªåœ¢åŒã§æåŸã®æ¡åŒµæ©èœãæ®ãïŒ
override
ïŒãããããç¶æ¿å
ã®ã¯ã©ã¹ãšããŠã¬ã³ããªã³ã°ãããïŒ 2çªç®ã®è§£æ±ºçã¯ããæ°äž»çãªãã®ã®ããã§ãããããã¯ããã«æ··ä¹±ãæãã§ããããïŒ äžè¬çã«ããã®è³ªåã¯æªè§£æ±ºã®ãŸãŸã§ãã
MVVMã§éçºããéã®åŸ®åŠãªéãã¯äœã§ããïŒ è©±ãåããŸããïŒ