本文用来介绍使用alpaca-spa构建多页的先后分离项目的js实现。javascript
关于alpaca-spa的其余功能,请参考官方文档css
Alpaca-spa.js是一款轻量的前端JS框架,提供前端路由功能,前端视图渲染功能,前端页面嵌套功能。目的是用来提升web项目的开发效率,先后端分离开发,同时使前端代码结构更加整洁。 Alpaca-spa.js 区别于其余框架的主要特色是轻巧灵活,移动端、PC端都适用,大小项目都适用,并且学习成本低, 框架没有复杂的概念与特性,不依赖开发环境(如node.js等),都是最基本的JavaScript语法,也就是说读者只要有JavaScript语言基础,就能够很快学会使用 Alpaca-spa.js框架用来构建前端页面。html
官方文档:http://www.tkc8.com前端
本文示例代码(oschina):https://gitee.com/cc-sponge/alpaca-spa-2.0java
示例代码(github):https://github.com/big-sponge/Alpaca-Spa-2.0node
完整的先后分离项目示例:http://full.tkc8.comjquery
视图功能是Alpaca-Spa.js的核心功能,主要解决前端JavaScript实现页面嵌套,页面数据渲染,页面局部渲染等功能。 使用alpaca-spa的View功能,能够轻松构建多页面先后分离结构,尤为是在开发后台功能时,很是实用。 固然,使用alpaca-spa开发移动端h5网站,单页面结构网站也是很是不错的选择。 使用视图功能须要配置web服务器,例如apache, nginx,node等。 这里使用apache举例,假设你的网站根目录位于:nginx
C:\www\
固然你能够配置apache的虚拟主机,将网站的根目录放在任意你喜欢的地方。git
若是大家项目的先后端在同一个域名下面,也就是网站根目录先后端用的是同一个,那前端的代码通常不会直接放在根木目下面, 在根目录下面创建一个叫 alpaca-spa
或者叫其余名字的目录(只要不与后端路由冲突既可),例如将前端代码放到 alpaca-spa
目录下面github
一个简单的目录结构以下:
--C:\www\alpaca-spa\ --main\ --controller\ index.js --view\ --index\ index.html index-2.html index-3.html --layout\ --part\ leftMenu.html layout.html main.js index.html
1. 示例中的www是项目的根目录,应该将web服务器的根目录设置为此目录。 2. alpaca-spa是前端项目的目录,目录下面有1个子目录,1个html文件。 main main目录用来存放当前项目中全部main模块的文件。能够建立多个模块。 index.html index.html用来作当前项目的入口文件 3.index目录里面有两个目录controller,view,一个js文件 controller 用来存放main模块的控制器的js代码。里面有一个控制器js文件,index.js view 用来存放main模块的视图部分的js代码。 示例中view目录里面有一个子目录index,用于存放index控制器中相关的模板, 本示例中,有三个模板:index.html,index2.html,index3.html 还有一个子目录layout,用于存放公共的布局信息, layout目录中的layout.html是默认的布局模板文件 layout目录中的还有一个子目录part,用来存放页面中其余公共区域,例如菜单等 main.js main.js是main模块的模块级别的js代码。 推荐在这个文件里面作模块的定义,例如:Alpaca.MainModule = {};
示例访问地址: http://www1.tkc8.com/alpaca-spa/index.html
了解完上面的目录结构以后,咱们来学习使用Alpaca.View()方法,参看下面的示例。
alpaca-spa/index.html 文件中的内容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>alpaca-spa.2.1</title> <!-- 简单调整一下样式 --> <link type="text/css" href="common/css/style.css"> <!-- 引入alpaca-spa.js--> <script type='text/javascript' src='http://spa.tkc8.com/common/js/jquery-2.1.4.min.js'></script> <script type="text/javascript" src="http://spa.tkc8.com/common/js/alpaca-spa-2.1.js"></script> <!-- 引入main模块main.js--> <script type="text/javascript" src="main/main.js"></script> <!-- 引入main模块下index控制器index.js--> <script type="text/javascript" src="main/controller/index.js"></script> <!-- 运行 alpaca-spa Js--> <script> $(function () { /* 配置baseUrl。 * 因为alpaca请求视图模版是从根目录进行寻址, * 当前项目不在根目录,在根目录的下一级目录中 * */ Alpaca.Config.baseUrl = "/alpaca-spa/"; /*启动alpaca,指定默认路由 #/main/index/index */ Alpaca.run("#/main/index/index"); }); </script> </head> <body> </body> </html>
alpaca-spa/main/main.js 文件中的内容:
/* 1 定义Index模块 */ Alpaca.MainModule = {};
alpaca-spa/main/controller/index.js 文件中的内容:
/* 1 定义Main模块中的Index控制器 */ Alpaca.MainModule.IndexController = { //index动做,建立一个视图index indexAction: function () { //视图默认渲染到#content位置,能够经过参数中传递to字段改变渲染位置 //视图模板默认位于index/view/index/index.html,能够经过参数中传递template字段改变模块路径 //即:默认模板位置为:[模块名]/view/[控制器名]/[动做名].html var view = new Alpaca.View({data:{desc:'我是一条数据,在controller中传递到view视图模版里面!'}}); //layout 布局视图 var layout = new Alpaca.Layout(); //part 部件视图,默认路由位于view/layout/part中,文件名默认与name属性相同 //part 的默认渲染位置与其name属性相同,固然也能够经过to属性指定 var part = new Alpaca.Part({name: 'leftMenu'}); //将part添加到layout中,part的默认渲染位置与其name属性相同,也能够经过to属性指定 layout.addChild(part); //设置视图的layout view.setLayout(layout); //在view中,向layout中传递数据 view.setLayoutData({'layoutData': 666}); //在view中,向part中传递数据 view.setPartData({leftMenu: {'partData': 888}}); return view; }, //index2动做,建立视图index2 index2Action: function () { var view = new Alpaca.View(); var layout = new Alpaca.Layout(); var part = new Alpaca.Part({name: 'leftMenu'}); layout.addChild(part); view.setLayout(layout); view.setLayoutData({'layoutData': '666 - 2'}); view.setPartData({leftMenu: {'partData': '888 - 2'}}); return view; }, //index3动做,建立视图index3 index3Action: function () { var view = new Alpaca.View(); var layout = new Alpaca.Layout(); var part = new Alpaca.Part({name: 'leftMenu'}); layout.addChild(part); view.setLayout(layout); view.setLayoutData({'layoutData': '666 -- 3'}); view.setPartData({leftMenu: {'partData': '888 -- 3'}}); return view; }, };
alpaca-spa/main/index/view/index.html 文件中的内容:
<div> 我是内容区域:当前显示的是index.html里面的内容 </div> <h5>我有一条数据:</h5> {{= it.desc }}
alpaca-spa/main/index/view/index2.html 文件中的内容:
<div> 我是内容区域:当前显示的是index2.html里面的内容 </div>
alpaca-spa/main/index/view/index3.html 文件中的内容:
<div> 我是内容区域:当前显示的是index3.html里面的内容 </div>
在浏览器中访问: http://www1.tkc8.com/alpaca-spa/index.html
点击按钮,能够看到内容区域切换到对应的页面了,总体布局layout、菜单leftMenu除了数据其余的都没有变化,
上面的示例中,咱们建立了Main模块,index控制器,index动做,而且在indexAction中经过Alpaca.View()方法建立了一个视图,运行结果是视图模板中的内容被渲染到了页面的#content位置中。这就是Alpaca.View()的用途。
Alpaca.View()方法
Alpaca.View(option) 是一个用来建立视图页面的方法,接受一个对象参数option,参数option中能够包含如下字段:
数据对象,为渲染模板提供数据
例如:Alpaca.View({data:{name:'Alpaca-spa'}})
设置被渲染位置,默认位置是#content
例如:Alpaca.View({data:{name:'Alpaca-spa'},to:'#divId'})
指定渲染的模板文件。默认是所属模块view目录下所属controller同名目录下action同名的.html文件,即:默认模板位置为:[模块名]/view/[控制器名]/[动做名].html
若是须要改变视图模板,只须要这样写便可:template:'index2',这样就会使用同名controller下的index2.html做为模板。
这是由于函数内部自动格式化了该参数,若是不想使用自动格式化功能,请使用notFormat参数,设置notFormat:true 便可。
例如:Alpaca.View({data:{name:'Alpaca-spa'},to:'body',template:'index2'})
默认为false,表示系统会自动格式化template参数,若是设置为true,以下例,视图将使用根目录下的index-test.html文件做为视图模板。 Alpaca.View(template:'/index-test.html',notFormat:true})
实际的web项目开发中,大部分页面都是有结构的,好比整体的布局,公用的菜单、页头、页尾等。Alpaca-sap.js使用layout,part来解决这类问题。
继续上面介绍View的示例:
观察alpaca-spa/main/controller/index.js 文件中的内容:
indexAction: function () { //视图默认渲染到#content位置,能够经过参数中传递to字段改变渲染位置 //视图模板默认位于index/view/index/index.html,能够经过参数中传递template字段改变模块路径 //即:默认模板位置为:[模块名]/view/[控制器名]/[动做名].html var view = new Alpaca.View({data:{desc:'我是一条数据,在controller中传递到view视图模版里面!'}}); //layout 布局视图 var layout = new Alpaca.Layout(); //part 部件视图,默认路由位于view/layout/part中,文件名默认与name属性相同 //part 的默认渲染位置与其name属性相同,固然也能够经过to属性指定 var part = new Alpaca.Part({name: 'leftMenu'}); //将part添加到layout中,part的默认渲染位置与其name属性相同,也能够经过to属性指定 layout.addChild(part); //设置视图的layout view.setLayout(layout); //在view中,向layout中传递数据 view.setLayoutData({'layoutData': 666}); //在view中,向part中传递数据 view.setPartData({leftMenu: {'partData': 888}}); return view; },
以及:alpaca-spa/main/view/layout/layout.html 文件中的内容为:
<style> .layout-css { border: 1px solid green; padding: 20px; } #content, #leftMenu { border: 1px dashed green; } #content { padding: 20px; } </style> <div class="layout-css"> <h2> 我是layout! 数据【{{=it.layoutData}}】是在控制器中传递给个人。</h2> <h5>左边菜单:</h5> <div id="leftMenu"></div> <h5>页面内容区域:</h5> <div id="content"></div> </div>
alpaca-spa/main/view/layout/part/leftMenu.html 文件中的内容为:
<style> .lm-css { padding: 20px;; } </style> <div class="lm-css"> <h3>我是左边的菜单,请把我放到左面! 数据【{{=it.partData}}】是在控制器中传递给个人。</h3> <h6>点下面的链接能够切换其余页面</h6> <button type="button" onclick="toIndex1()"> 页面Index1</button> <button type="button" onclick="toIndex2()"> 页面Index2</button> <button type="button" onclick="toIndex3()"> 页面Index3</button> </div> <script> /*必须注意 在模版中写js,注释不能够用“//”*/ var toIndex1 = function () { Alpaca.to('#/main/index/index'); }; var toIndex2 = function () { Alpaca.to('#/main/index/index2'); }; var toIndex3 = function () { Alpaca.to('#/main/index/index3'); } </script>
上面的示例演示了如何使用 layout、part来渲染复杂页面。
Alpaca.Layout()方法
Alpaca.Layout(option) 是用来建立一个layout布局的视图对象的方法,接受一个对象参数option,参数option中能够包含如下字段:
数据对象,为渲染模板提供数据
例如:Alpaca.Layout({data:{name:'Alpaca-spa'}})
设置被渲染位置,默认位置是body
例如:Alpaca.Layout({data:{name:'Alpaca-spa'},to:'#divId'})
指定layout的名字。默认为layout
layout默认的模板路径是所属模块view目录下layout目录下的layout.html文件
经过name字段能够修改模板的路径为:所属模块view目录下layout目录下与name同名的html文件
例如:Alpaca.Layout({data:{name:'Alpaca-spa'},to:'body',name:'layout2'})
Alpaca.Part()方法
Alpaca.Part(option) 是用来建立一个part布局的视图对象的方法,接受一个对象参数option,参数option中能够包含如下字段:
数据对象,为渲染模板提供数据
例如:Alpaca.Part({data:{name:'Alpaca-spa'}})
指定Part的名字。
Part默认的模板路径是所属模块view\layout\part目录下与其name同名的html文件
Part默认的渲染位置是id与其name同名的元素
经过name字段能够达到指定他的视图模板路径,以及渲染位置的效果,例如,
例如:Alpaca.Part({data:{name:'Alpaca-spa'},name:'top'})
设置被渲染位置,默认位置是id与其name同名的元素
例如:Alpaca.Part({data:{name:'Alpaca-spa'},to:'#divId'})
<body></body>
位置,经过设置Alpaca.ViewModel.DefaultLayoutCaptureTo = "body"; 能够全局改变layout的默认渲染位置
若是只修改当前视图的渲染位置,有两种方法:
var layout = new Alpaca.Layout({to:'body'}});
或者
var layout = new Alpaca.Layout(); layout.setCaptureTo('.layout-area');
<div id="content"> </div>
位置,经过设置Alpaca.ViewModel.DefaultViewCaptureTo = "body";能够全局改变view的默认渲染位置
若是只修改当前视图的渲染位置,有两种方法:
var view = new Alpaca.View({to:'#content'}});
或者
var view = new Alpaca.View(); view.setCaptureTo('.content-area');
layout、view的默认渲染位置很是重要,一个路由执行后,url中的hash是否改变,就依据layout、view的默认位置决定。而hash是否改变,会影响刷新点击按钮的结果。
则view的CaptureTo等于DefaultLayoutCaptureTo时
,hash会改变则layout的CaptureTo等于DefaultLayoutCaptureTo时
,hash会改变视图渲染完毕后会执行view.ready()方法,例如
var view = new Alpaca.View() //视图渲染完成后执行ready方法。 view.ready(function () { console.log('视图渲染完成了...'); }) return view;
经过设置view.show方法能够自定义视图显示效果,例如:
var view = new Alpaca.View(); //自定义视图渲染效果为闪入效果。 //注意:在自定义视图显示效果时,须要调用onLoad事件,来触发执行ready函数。 view.show = function (to, html) { var that = this; $(to).fadeOut("fast", function () { $(to).html(html); $(to).fadeIn("fast", function () { that.onLoad(); }); }); }; return view;
上面面示例代码,实现了视图渲染时的闪入效果。
若是在控制器中定义了init()方法,那么在执行当前控制器的全部action方法前都会执行init()方法。若是在控制器中定义了release()方法,那么在执行完成当前控制器的全部action方法以后,都会执行release()方法,
模块中也能够定义init()、release()方法。
参考示例:
/* 定义Index模块中的TestController */ Alpaca.IndexModule.TestController = { //init方法,当前控制下的全部动做在执行前,都会执行init方法 init:function(){ console.log('执行action以前,执行init()方法'); }, //release方法,当前控制下的全部动做在执行前,都会执行release方法 release:function(){ console.log('执行action以后,执行release)方法'); }, };
1:若是未使用layout,则view的CaptureTo等于DefaultLayoutCaptureTo 2:若是使用了layout,则layout的CaptureTo等于DefaultLayoutCaptureTo