YUIConf 刚刚结束, 我首先看的是Luke Smith的这个<class inheritance and composition in YUI>以及Eric的<App framework — You’ve Been Wanting This>, 主要讲了YUI中怎么实现类继承以及MVC的演讲:
Y.extend 实现了和原生继承一样的方式, Y.extend = function (SubClass, SuperClass, proto, static)
Y.extend(SubClass, SuperClass, {
someProperty: "booga!",
someMethod: function(){},
},{
someStaticMethod: function(){}
});
等价于下面的代码:
function SubClass() { // constructor}
SubClass.prototype = new SuperClass();
SubClass.prototype.someProperty = "booga!";
SubClass.prototype.someMethod = function () { ... };
SubClass.someStaticMethod = function () { ... };
Y. extend好处是创建了一个”干净”的继承关系, 不需要依赖YUI其它的模块, 保证了instanceof, 通过使用SubClass.superclass来控制父类的执行; 不足是没有实现多继承, 必须通过手动运行父类构造函数来保证链式调用; 适合简单的类继承
Y.Object, 拷贝一个新的对象
Y.Object = (function () {
function F() {}
return function (obj) {
F.prototype = obj;
return new F();
};
})();
Y. Object避免拷贝了过多的属性, 可以被用来构造工厂函数, 可以用来存储对象的初始值; 缺点是没有多继承, 在构造工厂函数的时候也许会产生凌乱, 在for/in循环中不能使用hasOwnProperty.
Y.augment, Y.augment = function (to, from, force, whitelist, config), to - 接受者, object/constructor, from - 提供者, constructor,to为constructor时, 会把from里的prototype里的东西传给to里面的prototype, 和extend不同的是它只是增加方法, 而不会暗示继承关系, 有点像多继承, 但是不是, 看下面这个例子:
YUI().use(´oop´, function(Y) {
function Foo() {}
Foo.prototype.doSomething = function () { /* something */ };
function Bar() {}
Y.augment(Bar, Foo);
var b = new Bar();
if (b instanceof Bar) {} // true
if (b instanceof Foo) {} // FALSE
});
使用Y.augment的好处是延迟构造函数的执行, 可以聚合多个类的方法, 支持类/对象的聚合; 缺点是instanceof聚合的类为false, 会消耗更多的内存, 对构造函数的控制受到了限制.
Plugins可以让你无缝地给对象(如nodes/widgets)添加功能,
Y.Plugin.Host.prototype.plug = function (Plugin, config) {
if (Plugin && Plugin.NS) {
config.host = this;
this[Plugin.NS] = new Plugin(config);
}
};
你也可以继承Y.Plugin.Base, 会获得更多的功能, 如对宿主的控制, 看下面的例子, 在给Widget类设计的一个Plugin里, 可以在render事件触发前改写_uiAnimSetVisible这个事件:
// A plugin class designed to animate Widget´s show and hide methods.
function WidgetAnimPlugin(config) {
//...
}
WidgetAnimPlugin.NAME = ´widgetAnimPlugin´;
WidgetAnimPlugin.NS = ´fx´;
WidgetAnimPlugin.ATTRS = {
animHidden : {
//...
},
};
Y.extend(WidgetAnimPlugin, Y.Plugin.Base, {
initializer : function(config) {
// Override Widget´s _uiSetVisible method, with the custom animated method
this.beforeHostMethod("_uiSetVisible", this._uiAnimSetVisible);
},
_uiAnimSetVisible : function(show) {
// Instead of flipping visibility, use the animation
// instances configured for the plugin to animate
// hide/show.
if (this.get("host").get("rendered")) {
if (show) {
this.get("animHidden").stop();
this.get("animVisible").run();
} else {
this.get("animVisible").stop();
this.get("animHidden").run();
}
// Prevent the default method from being invoked.
return new Y.Do.Prevent();
}
}
});
使用Plugin的好处是避免方法/熟悉冲突, unplug后保留了宿主的行为, 普通的Plugin可以为不同类型的宿主工作, Y.Base和Y.Nodes类的实例可以直接使用.
Class Extensions, 当调用这个Y.Base.create = function(NAME, SuperClass, ext, proto, static)时, 会调用构造函数, 设置属性, 运行初始化方法.
MVC, 在YUI中App Framework实现了MVC, 由Y.Model, Y.ModelList, Y.View, Y.Controller(将会被Y.Router代替)的一些组件构成一个MVC结构来写单页面Javascript应用程序的框架,你可以用这些组件分别和一起创建任何简单的非交互式的视图或是基于URL的进程,数据绑定或者完全客户端式的同步。
YUI的MVC也是学习Backbone这个经典的MVC框架, 如果用过Backbone的话所以有些东西比较熟悉, Y.Model一般用来管理数据和状态, 观察属性, 管理事件, 维护需求逻辑, 通常有数据交互这一层; Y.View就是一个渲染的容器, 一般在这里订阅事件, 比较轻量级; Y.Router是一个基本的导航管理系统, 使用了HTML5的pushState和popState(或者降级使用基于hash的历史管理), 保证url可以被收藏并且浏览器后退前进按钮可用, Y.Router的一个例子:
router = new Y.Router();
router.route(/library/:lib/, function (req) {
var lib = req.params.lib;
if (lib === yui) {
Y.log(YUI Library is awesome!);
}
});
router.save(/library/yui/);// => YUI Library is awesome!
Y.Router的原理图如下:

Y.App是把前面三者组合起来的一个基础, 看下面的例子:
var usersApp = new Y.App({
views: {
users: {
type : Y.UsersView,
preserve: true
},
user: {
type : Y.UserView,
parent: users
}
}
});
var users = new Y.UsersList();
usersApp.route(´/user/´, function () {
this.showView(users, {modelList: users});
});
usersApp.route(´/user/:id/´, function (req) {
var user = users.getById(req.params.id);
this.showView(user, {model: user}, function (view) {
// Called after transition.
});
});
同时Eric还引入了一个Pjax的概念, pushState+Ajax=Pjax, 主要用来处理用户点击链接, 然后更新URL, 再去动态加载/更新内容, 它的原理图如下:

重新来看Y.App的话其实它就是一个使用Pjax的View/Router, 有一个激活的View, 处理各个View的生命周期以及过渡, 在做一个App时经常使用到的一个技术是模板技术, YUI也借鉴了Mustache的优点即将引入handlebars模块, Y.Handlebars, 看一个Handlebars的模板:
<script id="entry-template" type="text/x-handlebars-template">
<div class="entry">
<h1><{{title}}</h1>
{{#if author}}
<p class="author">{{author}}</p>
{{/if}}
<div class="body">{{body}}</div>
</div>
</script>
看看Y.Handlebars是怎么处理的:
YUI().use(´handlebars´, ´node-base´, function (Y) {
var template = Y.one(´#entry-template´).getContent(),
render = Y.Handlebars.compile(template),
entry = {
title : ´The Adventures of Tom Selleck´,
body : ´Tom crossed the river in his Ferrari…´,
author: ´Ryan Grove´
};
Y.one(#entry).setContent(render(entry));
});
有一个例子Photonearme就是使用了YUI的App Framework, 同时又实现了响应设计, 源代码请移步这里, YUIConf还有更精彩的内容, 待续.
了解更多:
http://yuilibrary.com/yui/docs/app/
https://gist.github.com/1367067
Recent Comments