概述

·  ExtJs5能够搭建Js的MVC框架,通过配置路由能够通过左边树形菜单导航到所需的页面,效果如下:

搭建JS框架

  新建home.htm页面作为ExtJs加载的主体页面,页面引入ExtJs需要的JS和ExtJs入口Js文件app.js

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ExtJS演示</title>
<script type="text/javascript" src="Ext/ext-all.js"></script>
<script type="text/javascript" src="Ext/ext-locale-zh_CN.js"></script>
<link rel="stylesheet" type="text/css" href="Ext/packages/ext-theme-crisp/build/resources/ext-theme-crisp-all_01.css">
<script type="text/javascript" src="app.js"></script>
</head>
<body>
</body>
</html>

  app.js是ExtJs框架的入口,新建ExtJs中Application程序,指定所有新建ExtJs类的命名空间必须是MyApp开头,类似 MyApp.***,另外在app.js同级目录下新建app文件夹,里面新建文件夹view和viewmodel,这些文件夹的命名和规则必须是确定,不能任意修改,否则文件加载的时候,找不到相应的Js文件;

//ExtJs的入口,加载该Js之后,自动调用launch方法内容项
Ext.application({
name : 'MyApp',
extend:'MyApp.Application',
autoCreateViewport:'MyApp.view.main.Main',
// controllers:['Users'],
listen: {
controller: {
'#': {
unmatchedroute: 'onUnmatchedRoute'
}
}
},
onUnmatchedRoute: function(hash) {
alert('Unmatched', hash);
},
init:function(){
var me=this;
me.setDefaultToken('all');
},
launch : function() {
}
});

在app目录下,新建Application.js,命名MyApp.Application,代码如下,切记定义Js组件的名称,必须和文件路径对应

Ext.define('MyApp.Application',{
extend:'Ext.app.Application',
name:'MyApp',
// stores:[
// 'UserStore@MyApp.store'
// ]
});

在app目录下,新建文件夹view\main,里面新建main.js,主要继承Ext.container.Container容器控件,负责页面布局使用,页面布局模式采用border使用,分为头部、导航、中间页面内容展示;

Ext.define('MyApp.view.main.Main',{
extend:'Ext.container.Container',
xtype:'app-main',
requires:['MyApp.view.main.MainController','MyApp.view.main.Header','MyApp.view.main.Navigation','MyApp.view.main.ContentPanel'],
controller:'main',
layout:{type:'border'},
items:[
{region:'north',xtype:'app-header'},
{region:'west',xtype:'app-navigation'},
{region:'center',xtype:'app-contentPanel'}
]
});

在app\view\main,新建总部内容MainController.js,类型是Ext.app.ViewController。内容如下,主要负责Main.js的Action和hander的绑定,控制页面的路由导航

var com={'message-view':'MyApp.view.message.MessageController','UserGrid':'MyApp.view.user.UserGridController'};
Ext.define('MyApp.view.main.MainController',{
extend:'Ext.app.ViewController',
requires:[
'Ext.window.MessageBox'
],
alias:'controller.main',
control:{
'app-navigation':{
selectionchange:'onTreeNavSelectionChange'
}
},
onTreeNavSelectionChange:function(selModel,records)
{
var record=records[];
console.log(record.getId());
if(record)
this.redirectTo(record.getId());
},
routes: {
':id': {
action: 'handleRout',
before: 'beforeHandleRout'
}
},
handleRout: function (id) {
console.log('Handle:'+id);
var me=this,
mainView = me.getView(),
navigationTree = mainView.down('app-navigation'),
contentPanel = mainView.down('app-contentPanel'),
store=navigationTree.getStore(),
node=store.getNodeById(id);
contentPanel.removeAll(true),
controlName=com[id];
Ext.create(controlName);//MyApp.view.message.MessageController
var module = Ext.apply({}, {
xtype: id,
itemId: id,
//glyph: node.get('glyph'),
title: node.get('text')
// tooltip: node.get('text')
});
contentPanel.add(module);
var text = node.get('text'),
title = node.isLeaf() ? (node.parentNode.get('text') + ' - ' + text) : text;
contentPanel.setTitle(title);
//Ext.suspendLayouts(); //暂停布局
Ext.resumeLayouts(true); //恢复布局
},
beforeHandleRout: function (id, action) {
//动态实例化controller
action.stop();
var me=this,
store=Ext.StoreMgr.get('NavigationStore');
node=store.getNodeById(id);
if(node)
{
action.resume();
}
else
{
Ext.Msg.alert(
'路由跳转失败',
'找不到id为' + id + ' 的组件. 界面将跳转到应用初始界面',
function() {
me.redirectTo('all');
}
);
action.stop();
}
},
});

在app\view\main,新建头部Header.js,内容如下

Ext.define('MyApp.view.main.Header',{
extend:'Ext.Container',
xtype:'app-header',
height:,
layout:{type:'hbox',align:'middle'},
items:[
{xtype:'component',html:'<h2>XX系统</h2>'},
{xtype:'component',html:'ExtJs实例',flex:}
]
});

在app\view\main,新建导航Navigation.js,内容如下,PS 树形结构的id名称要和视图的xtype对应

Ext.define("MyApp.view.main.Navigation",{
extend:'Ext.tree.Panel',
xtype:'app-navigation',
rootVisible:false,
userArrows:true,
// hideHeaders:true,
width:,
minWidth:,
split:true,
collapsible:true,
store:Ext.create('Ext.data.TreeStore', {
id:'NavigationStore',
root: {
expanded: true,
id:'all',
text:'All',
children: [
{text: "消息管理", id: "message-view", leaf: true},
{text: "用户列表", id: "UserGrid", leaf: true}
]
}
})
});

在app\view\main,新建总部内容ContentPanel.js,内容如下

Ext.define('MyApp.view.main.ContentPanel',{
extend:'Ext.panel.Panel',
xtype:'app-contentPanel',
autoScroll:true
});

在app\view\user,新建用户页面UserGrid.js,内容如下

Ext.define('MyApp.view.user.UserGrid', {
extend: 'Ext.grid.Panel',
xtype: 'UserGrid',
title: '用户列表',
requires:['MyApp.store.UserStore'],
store:Ext.create('MyApp.store.UserStore'),
controller:'usergrid',
initComponent:function(){
var me = this;
me.columns = [
{xtype: 'rownumberer',header: '序号', width: , align: 'center'},
{xtype: 'rownumberer',header: '用户名', width: , align: 'center'},
{xtype: 'rownumberer',header: '年龄', width: , align: 'center'},
];
me.callParent();
},
width: ,
height:,
border:true,
listeners:{
itemdblclick: {
fn: 'userClick',
scope: "controller"
}
}
});

在app\view\user,新建用户视图控制器UserGridController.js,内容如下

Ext.define('MyApp.view.user.UserGridController',{
extend:'Ext.app.ViewController',
alias:'controller.usergrid',
requires:["MyApp.view.user.UserGrid"],
userClick:function( view, record, item, index, e, eOpts){
alert('hello'+record.get('name'))
}
});

在app\model ,新建UserModel.js,内容如下

Ext.define('MyApp.model.UserModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'age', type: 'int'},
{name: 'phone', type: 'string'}
]
});

在app\store,新建UserStore.js,内容如下

Ext.define('MyApp.store.UserStore', {
extend: 'Ext.data.Store',
model: 'MyApp.model.UserModel',
autoLoad: true,
alias:'user-store',
proxy: {
type: 'ajax',
api: {
read: 'data/users.json'
},
reader: {
type: 'json',
rootProperty: 'users',
successProperty: 'success'
}
}
});

需要注意事项:

1、文件目录必须按Ext.define的定义的顺序建立,这个是默认约定的,否则找不到文件Js;

2、导航的id值必须是和新建的控件名称的xtype类型对应,否则加载控件失败;

3、ViewController和View绑定,在Js里面requires的内容项,默认会加载相应的Js文件;

4、如果提示,extjs Cannot read property 'isBufferedStore' of undefined,主要原因在于store内容为空导致的;

完整代码如下

DEMO下载

参考地址 Extjs5.0(6):控制器(Controller、ViewController)和路由器(Router)

ExtJS5搭建MVVM框架的更多相关文章

  1. “老坛泡新菜”:SOD MVVM框架,让WinForms焕发新春

    火热的MVVM框架 最近几年最热门的技术之一就是前端技术了,各种前端框架,前端标准和前端设计风格层出不穷,而在众多前端框架中具有MVC,MVVM功能的框架成为耀眼新星,比如GitHub关注度很高的Vu ...

  2. 前端MVVM框架设计及实现(一)

    最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造轮子写一个简单的MVVM框架了 借鉴的自然还是从正美的avalon开始了,我记得还是去年6月写过一个系列的av ...

  3. 整合MVVM框架(Prism)

    整合MVVM框架(Prism) 我们基础的框架已经搭建起来了,现在整合MVVM框架Prism,在ViewModel做一些逻辑处理,真正把界面设计分离出来. 这样方便我们系统开发分工合作,同时提高系统可 ...

  4. js架构设计模式——前端MVVM框架设计及实现(一)

    前端MVVM框架设计及实现(一) 最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造轮子写一个简单的MVVM框架了 借鉴的自然还是从正美的avalon开始了,我 ...

  5. 迷你MVVM框架 avalonjs 1.3.9发布

    本次升级,avalon改进了许多内部方法,大大提升性能,并且带来异步刷新视图的新功能. ms-html内部不再使用异步 head元素中的avalon元素加入ms-skip指令 重构计算属性,现在超级轻 ...

  6. [转]MVP+WCF+三层结构搭建项目框架

    最近,我一直在重构之前做的一个项目,在这个过程中感慨万千.原先的项目是一个运用了WCF的C/S系统,在客户端运用了MVC模式,但MVC的View.Model耦合以及WCF端分布式欠佳等问题让我有了重构 ...

  7. angularjs+requlirejs 搭建前端框架(1)

    第一部分:发发牢骚吧 随着富前端时代的逐渐深入,越来越多的前端技术框架层出不穷,可以说是百花齐放.让我们这些爱好前端的人疲于奔命,今天学习这个框架,明天研究那个框架,哎,说不出的蛋疼...感觉好累.. ...

  8. 基于WPF系统框架设计(6)-整合MVVM框架(Prism)

    应用场景 我们基础的框架已经搭建起来了,现在整合MVVM框架Prism,在ViewModel做一些逻辑处理,真正把界面设计分离出来. 这样方便我们系统开发分工合作,同时提高系统可维护性和灵活性. 具体 ...

  9. 剖析手写Vue,你也可以手写一个MVVM框架

    剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...

随机推荐

  1. Educational Codeforces Round 60 (Rated for Div. 2)

    A. Best Subsegment 题意 找 连续区间的平均值  满足最大情况下的最长长度 思路:就是看有几个连续的最大值 #include<bits/stdc++.h> using n ...

  2. 洛谷P4178 Tree (算竞进阶习题)

    点分治 还是一道点分治,和前面那道题不同的是求所有距离小于等于k的点对. 如果只是等于k,我们可以把重心的每个子树分开处理,统计之后再合并,这样可以避免答案重复(也就是再同一个子树中出现路径之和为k的 ...

  3. python学习日记(isinstance和issubclass)

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() isinstance(obj, Foo) issu ...

  4. vue数组中对象属性变化页面不渲染问题

    问题引入 Vue之所以能够监听Model状态的变化,是因为JavaScript语言本身提供了Proxy或者Object.observe()机制来监听对象状态的变化.但是,对于数组元素的赋值,却没有办法 ...

  5. GWAS条件分析(conditional analysis)

    一.为什么要做GWAS的条件分析(conditional analysis) 我们做GWAS的时候,经常扫出一堆显著的信号,假设rs121是我们扫出来与某表型最显著相关的位点(P=1.351e-36) ...

  6. Springboot 2.返回cookies信息的get接口开发 和 带cookis去请求

    首先要有一个启动类,默认的启动类的名字就是Application.java.启动的时候直接右键点击run就可以 Application.java: import org.springframework ...

  7. Mybatis的原理与JVM内存结构(面试题)

    Mybatis的原理 1.Mapper 接口在初始SQL SessionFactory注册的 2.Mapper 接口注册在名为MapperRegistry类的 HasMap中 key=Mapper c ...

  8. gdb core 调试多线程

    ref :http://blog.sina.com.cn/s/blog_62dc94eb0100flyn.html 如果目标进程已经core dump了,那么 gdb -c core xxx   xx ...

  9. PYTHON语言之常用内置函数

    一 写在开头本文列举了一些常用的python内置函数.完整详细的python内置函数列表请参见python文档的Built-in Functions章节. 二 python常用内置函数请注意,有关内置 ...

  10. [Android] Android 实现类似 今日头条 视频播放列表

    演示实例如下: Talk is cheap. Show me the code 话不多说,代码在这里下载! https://github.com/wukong1688/Android_BaseVide ...