组建和架构的包括固定的写法,风格还有规范,通过一个栗子(仅包含一个grid和点击事件),来描述extjs下的mvc和mvvm的整体结果
组建化
<!DOCTYPE HTML> <html manifest=""> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta charset="UTF-8"> <title>htjy</title> <link type="text/css" rel="stylesheet" href="css/font-awesome.css"> <!-- The line below must be kept intact for Sencha Cmd to build your application --> <script type="text/javascript" src="/ext/build/ext.js"></script> <script type="text/javascript" src="/ext/build/ext-all.js"></script> <script src="/ext/packages/ext-locale/build/ext-locale-zh_CN.js"></script> <link href="/ext/packages/ext-theme-crisp/build/resources/ext-theme-crisp-all.css" rel="stylesheet" /> </head> <body></body> <script> Ext.onReady(function() { //模型描述 Ext.define('User', { extend: 'Ext.data.Model', fields: [{ name: 'firstName', type: 'string' }, { name: 'lastName', type: 'string' }, { name: 'age', type: 'int' }, { name: 'eyeColor', type: 'string' }] }); //仓库整合 Ext.define('UserStore', { extend: 'Ext.data.Store', model: "User", data: [{ firstName: 'Ed', lastName: 'Spencer' }, { firstName: 'Tommy', lastName: 'Maintz' }, { firstName: 'Aaron', lastName: 'Conran' }, { firstName: 'Jamie', lastName: 'Avins' }] }); var store = Ext.create('UserStore'); Ext.create('Ext.grid.Panel', { title: 'Simpsons', store: store, columns: [{ text: 'firstName', dataIndex: 'firstName' }, { text: 'lastName', dataIndex: 'lastName' }, { text: 'age', dataIndex: 'age' }, { text: 'eyeColor', dataIndex: 'eyeColor' }], listeners: { itemclick: function() { console.log('click el2'); } }, height: 200, width: 400, renderTo: Ext.getBody() }); }); </script> </html>
通过Sencha初始化+一个栗子的代码,虽然这养完成了任务,但只用到了组建,还没有用到更为重要的框架
mvc
跟着网上的呆毛,不明觉厉的使用方式
model:
Ext.define('app.model.User', { extend: 'Ext.data.Model', fields: [{ name: 'firstName', type: 'string' }, { name: 'lastName', type: 'string' }, { name: 'age', type: 'int' }, { name: 'eyeColor', type: 'string' }] });
controller:
Ext.define('app.controller.User', { extend: 'Ext.app.Controller', init: function() { this.control({ 'userlist': { itemclick: this.userlistHighlight } }); }, userlistHighlight: function() { console.log('click el'); } });
view:
Ext.define("app.view.user.List", { extend: "Ext.grid.Panel", alias: 'widget.userlist', store: Ext.create('app.store.User'), columns: [{ text: 'firstName', dataIndex: 'firstName' }, { text: 'lastName', dataIndex: 'lastName' }, { text: 'age', dataIndex: 'age' }, { text: 'eyeColor', dataIndex: 'eyeColor' }] });
Viewport:单页面入口
Ext.define("app.view.Viewport", { extend: "Ext.container.Viewport", layout: "fit", uses:['app.view.user.List','app.controller.User'], items: { xtype:"userlist" } });
Application:架构启动
Ext.define('app.Application', { extend: 'Ext.app.Application', name: 'app', stores: [ // TODO: add global / shared stores here ], controllers: ['User'], autoCreateViewport: true, launch: function() {} });
通过Sencha初始化+上面的代码,就可以正确的运行了,混合了配置信息和异步加载信息等多种方式,组建的使用错误不大,但是架构的使用,略微蛋疼
1.uses是什么鬼?
一次性将所有js文件全部加载绝不是一个好主意,延迟加载/按需加载也就逐步转换为架构的一部分,而user与requires就是依赖元素(其中加载器中的require方法-.-毕竟干的都是一件事)
requires:初始化依赖文件,
uses:业务(初始化后)依赖文件
createOverride: function (className, data, createdFn) { var me = this, overriddenClassName = data.override, requires = data.requires, uses = data.uses, mixins = data.mixins, mixinsIsArray, compat = data.compatibility, depedenciesLoaded, classReady = function () { var cls, dependencies, i, key, temp; if (!depedenciesLoaded) { dependencies = requires ? requires.slice(0) : []; if (mixins) { if (!(mixinsIsArray = mixins instanceof Array)) { for (key in mixins) { if (Ext.isString(cls = mixins[key])) { dependencies.push(cls); } } } else { for (i = 0, temp = mixins.length; i < temp; ++i) { if (Ext.isString(cls = mixins[i])) { dependencies.push(cls); } } } } depedenciesLoaded = true; if (dependencies.length) { // Since the override is going to be used (its target class is // now created), we need to fetch the required classes for the // override and call us back once they are loaded: Ext.require(dependencies, classReady); return; } // else we have no dependencies, so proceed } // transform mixin class names into class references, This // loop can handle both the array and object forms of // mixin definitions if (mixinsIsArray) { for (i = 0, temp = mixins.length; i < temp; ++i) { if (Ext.isString(cls = mixins[i])) { mixins[i] = Ext.ClassManager.get(cls); } } } else if (mixins) { for (key in mixins) { if (Ext.isString(cls = mixins[key])) { mixins[key] = Ext.ClassManager.get(cls); } } } // The target class and the required classes for this override are // ready, so we can apply the override now: cls = me.get(overriddenClassName); // We don't want to apply these: delete data.override; delete data.compatibility; delete data.requires; delete data.uses; Ext.override(cls, data); // This pushes the overridding file itself into Ext.Loader.history // Hence if the target class never exists, the overriding file will // never be included in the build. me.triggerCreated(className); if (uses) { // This "hides" from the Cmd auto-dependency scanner since // the reference is circular (Loader requires us). Ext['Loader'].addUsedClasses(uses); // get these classes too! } if (createdFn) { createdFn.call(cls, cls); // last but not least! } }; me.triggerExists(className, 2); if (!compat || Ext.checkVersion(compat)) { // Override the target class right after it's created me.onCreated(classReady, me, overriddenClassName); } return me; }
requires属性下的js直接被加载,而uses下的js被加入usedclass方法,用以初始化完成后在加载
2.store: Ext.create('app.store.User')是什么鬼?
创建/配置`仓库`,grid非常依赖的实例,很显然,creat代表着创建,每次加载grid都会创建一个store在内存中...为了达到复用目的(类似于create,show),可以使用StoreManage进行管理
3.Viewport
domcument.body的封装,代表整个浏览界面(body,所有没有renderto),主要用于方便布局,一个页面只有一个viewport
4.Application
应用程序的封装(类似于路由的全局封装),包含了应用程序应该绑定的Models、Views和Controllers,可以通过响应的属性进行管理(其实等价于requires),其中view可以被Controller管理(controller的效果依赖view的存在),所以这个地方需要描述Models和Controllers
当然了,application的配置又回在初始化时提前加载,所以是在view中使用requires分散压力,还是一口气配置完成,就看需求了
修改后标准的mvc:
Application:应用程序关联设置
Ext.define('app.Application', { extend: 'Ext.app.Application', name: 'app', stores: ['User'], controllers: ['User'], models:['User'], autoCreateViewport: true, launch: function() {} });
viewreport:body的封装,无需在引用
Ext.define("app.view.Viewport", { extend: "Ext.container.Viewport", layout: "fit", items: { xtype:"userlist" } });
view:真正的视图,完全找不到业务逻辑,如果页面需要修改,在此处
Ext.define("app.view.user.List", { extend: "Ext.grid.Panel", alias: 'widget.userlist', store: 'User', columns: [{ text: 'firstName', dataIndex: 'firstName' }, { text: 'lastName', dataIndex: 'lastName' }, { text: 'age', dataIndex: 'age' }, { text: 'eyeColor', dataIndex: 'eyeColor' }], initComponent: function() { this.callParent(); } });
controller:真正的逻辑层,可以通过他来关联views(原因你懂得,实践胜于理论),如果逻辑出错,就在这里,依赖选择器
Ext.define('app.controller.User', { extend: 'Ext.app.Controller', views:['user.List'], init: function() { this.control({ 'userlist': { itemclick: this.userlistHighlight } }); }, userlistHighlight: function() { console.log('click el'); } });
至此mvc的方式就已经完成了,尽管聊过延迟加载,其实在mvc模式下,延迟加载的解决方案相当的糟糕-。-
mvvm
根据官网的呆毛,进行尝试
Application:应用程序关联设置
Ext.application({ name: 'app', extend: 'app.Application', autoCreateViewport:'app.view.main.Main' });
view容器:view木有任何逻辑,但参与调用/绑定的设计,以减少工作量,此处有迷之`main`参数,木有加载配置
Ext.define('app.view.main.Main', { extend: 'Ext.container.Container', xtype: 'app-main', controller: 'main', viewModel: { type: 'main' }, layout: { type: 'border' }, items: [{ xtype: 'panel', bind: { title: '{name}' }, region: 'west', html: '<ul><li>This area is commonly used for navigation, for example, using a "tree" component.</li></ul>', width: 250, split: true, tbar: [{ text: 'Button', handler: 'onClickButton' }] },{ region: 'center', xtype: 'tabpanel', items:[{ title: 'Tab 1', html: '<h2>Content appropriate for the current navigation.</h2>' }] }] });
controller:所有的逻辑都在这里,我们可以将alias注释掉,做几个小测试
Ext.define('app.view.main.MainController', { extend: 'Ext.app.ViewController', requires: [ 'Ext.window.MessageBox' ], // alias: 'controller.main', onClickButton: function () { Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this); }, onConfirm: function (choice) { if (choice === 'yes') { // } } });
vm:静态数据,此处可以添加各种get方法用以修改数据转换的逻辑
Ext.define('app.view.main.MainModel', { extend: 'Ext.app.ViewModel', // alias: 'viewmodel.main', data: { name: 'app' } //TODO - add data, formulas and/or methods to support your view });
总之,vm+c分散了业务的代码
以上是官网的呆毛,如果根据这种格式去写第二个栗子就会发现,完全运行不起来。。。八层是该类未被加载的意思,但是,官网的例子又是为毛...
bootstrap.json-->可以在该文件下看见一下内容
"app.view.main.MainController": { "idx": 17, "alias": ["controller.main"], "alternates": [] }, "app.view.main.MainModel": { "idx": 18, "alias": ["viewmodel.main"], "alternates": [] }
在这里增加自己的测试项目,就可以相关像官网一样实现了
以上为ext下的mvvm实现,感觉也就是mvc+双向绑定,不如angular这种舒服
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步