访问视图
常见地视图模式时一个视图对应一个控制器,视图包含一个id,通过id传入控制器;在视图之中的元素则使用class
这里会使用jquery的选择器,为了减少使用,可以设置一个专门用于存放选择器到变量的映射表
<div id="users">
<form>
<input type="search" value="" placeholder="Enter a query">
<button type="button">Search</button>
</form>
</div>
jQuery(function($) {
exports.SearchView = Controller.create({
//选择器局部变量名地映射
elements: {
"input[type=search]": "searchInput",
"form": "searchForm"
},
//实例化时调用
init: function(elem) {
this.el = $(elem);
this.refreshElements();
this.searchForm.submit(this.proxy(this.search));
},
search: function() {
console.log("Searching:", this.searchInput.val());
},
//私有
$: function(selector) {
//需要一个el属性,同时传入选择器
return $(selector, this.el);
},
//设置本地变量
refreshElements: function() {
for(var key in this.elements) {
this[this.elements[key]] = this.$(key);
}
}
});
new SearchView("#users");
});
委托事件
通过设置一个events对象代理,进行事件的委托和移除
jQuery(function($){
exports.SearchView = Controller.create({
//所有事件名称,选择器和回调的映射
events: {
"submit form": "search"
},
init: function(element){
//.....
this.delegateEvents();
},
search: function(){
//...
},
//根据第一个空格分割
eventSplitter: /^(\w+)\s*(.*)$/,
delegateEvents: function(){
for (var key in this.events) {
var methodName = this.events[key];
var method = this.proxy(this[methodName]);
var match = key.match(this.eventSplitter);
var eventName = match[1], selector = match[2];
if (selector === '') {
this.el.bind(eventName, method);
} else {
this.el.delegate(selector, eventName, method);
}
}
}
});
new SearchView("#users");
});
状态机
作用:管理多控制器,根据需要显示和隐藏视图
组成: 状态和转换器; 它包含一个活动状态和许多非活动状态;
var Events = {
bind: function() {
this.o = this.o || $({});
this.o.bind.apply(this.o ,arguments);
},
trigger: function() {
this.o = this.o || $({});
this.o.trigger.apply(this.o, arguments);
}
}
var StateManchine = function() {};
StateManchine.fn =StateManchine.prototype;
//添加事件绑定或触发行为
$.extend(StateManchine.fn, Events);
//这个add函数将传入的控制器添加至状态列表并创建一个active函数;当调用active的时候,控制器状态转化为激活状态,对于激活状态的控制器,状态将基于它调用activate,对于其他控制器,状态机会调用deactivate;
StateManchine.fn.add = function(controller) {
this.bind("change", function(e, current) {
if(controller == current)
controller.activate();
else
controller.deactivate();
});
controller.active = $.proxy(function() {
this.trigger("change", controller);
}, this);
};
//使用
var con1 = {
activate: function() {
$("#con1").addClass("active");
},
deactivate: function() {
$("#con1").removeClass("active");
}
};
var con2 = {
activate: function() {
$("#con2").addClass("active");
},
deactivate: function() {
$("#con2").removeClass("active");
}
};
//创建状态机并添加状态
var sm = new StateManchine;
sm.add(con1);
sm.add(con2);
//会触发con1.activate;con2.deactivate;
con1.active();
//会触发con2.activate;con1.deactivate;
sm.trigger("change", con2);
路由选择
由于应用是单页面的,URL一般不会变;当考虑到具体情况,需要对其进行改变
使用URL中的hash####
改变URL会造成页面刷新;操作URL的一种办法是改变hash值,因为hash不会发送给服务器,改变其不会造成刷新
//设置
window.location.hash = "foo";
//去掉#
var hashValue = window.location.hash.slice(1);
注意要限制这种改动的次数,过多的设置hash会影响性能,特别是在移动端,可能会造成页面频繁滚动
检测hash的变化####
监听
window.addEventListener('hashchange', function(event){});
- 设置location.hash或修改hash后重新载入时触发;