Web Frontend Develope, Design, Music, Life——Stay Hungry, Stay Foolish~
标签类目:yui

使用YUI3组织网站结构

最近在做一个保险的重构项目,在着手开始做之前就是考虑怎么来组织前端的代码,我的做法是使用YUI3,在insure下有一个base.js,这个js定义了整个网站需要的组件,如公共的组件 日历 表单校验 购买流程 提示 级联等等,这些组件可以是使用YUI2开发,也可以是使用YUI3开发,也可以是使用原生的js来写,最后都会通过yui的loader加载后来使用。base.js里面大概是这样的:
yui-min.js的代码
var module = {
‘casecade’:{
fullpath: widgetsUrl+’cascade/cascade.js’,
require: ['node']
}

};//整个网站需要用到的一些模块定义,有新的模块添加或修改时就更新这个module
var yuiCfg  = {};//yui的一些配置
var INS = YUI(yuiCfg);//定义了保险的全局变量INS

前端Assets的目录结构是这样的:

js/
—base.js >定义了widgets组件的各个模块
—widgets/cascade/ >级联菜单组件
—widgets/calendar/ >日历组件
—widgets/validator/ >校验组件
—widgets/… >其它组件
—taikang/tk_traffic.js tk_estimate.js >泰康险种各个功能页面需要用到的js文件
—huatai/ht_traffic.js >华泰险种各个功能页面需要用到的js文件

css/
—index.css >首页的样式
—common.css >公共的样式
—taikang/tk_traffic.css … >泰康险种的样式
—huatai/ht_traffic.css … >华泰险种的样式

比如在tk_traffics.js里面就可以这样来使用,INS.use(’casecade’, ‘validator’, function(Y){
//泰康保险的页面逻辑
});

使用这样的目录结构在工程师嵌套页面的时候有很大的灵活性,因为头部工程师会把它做成一个公共的头,这个里面我把base.js和common.css放在公共头里面,每个险种的页面除了引用这样的公共头之外还会引用这个险种自有的样式以及js代码。把base.js放在头部之后,每个页面想要用某个组件都非常灵活,而且是使用了YUI的异步加载以及动态加载机制,如果服务器端提供了combo之后将会极大地提高前端的性能,对于团队开发来说也是比较灵活的方式。

YUI3中的继承和重用

YUI3中的继承

1.类继承

// parent
function Person() {
// “own” members
this.name = “Adam”;
}
// properties of the parent’s prototype
Person.prototype.getName = function() {
return this.name;
};
// child constructor
function Programmer(){}

Y.extend可以帮你实现类的继承
Y.extend(Programmer, Person);
Y.extend只会继承prototype里的成员,而不会继承构造函数内的成员,在这里Programmer没有name的属性。通过Y.extend可以给子类的prototype添加属性同时还可以给构造函数添加静态属性,如
Y.extend(Programmer, Person, {groksHTML: true}, {LIMIT: “sky”});
// the property works for all new objects
var bob = new Programmer();
alert(bob.groksHTML); // true
alert(Programmer.LIMIT); // “sky”
在类模式中你还可以通过子类的静态属性superclass访问父类的prototype属性,因此可以通过superclass.constructor访问父类的构造函数。
// child’s access to the parent constructor
var parent = Programmer.superclass.constructor;
alert(parent === Person); // true
因此你就可以在子类中初始化父类并且带同样的参数,如
// child
function Programmer() {
// initialize the parent using the child as “this”
Programmer.superclass.constructor.apply(this, arguments);
}
这样的话Programmer的实例就会有name这个属性了
var pro = new Programmer();
alert(pro.name); // “Adam”

2.原型继承

Douglas Crockford建议了这种继承方式,你可以忘掉类并且完全是对象之间的继承,你还可以自定义对象的属性和方法。
// parent object, created with a simple object literal
var parent = {
name: “John”,
family: “Wayne”,
say: function() {
return “I am ” + this.name + ” ” + this.family;
}
};
// the inheritance magic
// a new object is born from an existing one
var batman = Y.Object(parent);
// customize or augment the new object
batman.name = “Bruce”;
// use
batman.say(); // I am Bruce Wayne
使用这种继承方式,父类的成员通过原型链来继承,当你给子类增加一个同名的属性时,将不会覆盖父类的属性,但是会有优先权。
batman.say = function() {
return “Can’t tell you my real name”;
};
// test
batman.say(); // “Can’t tell you my real name”
不像类的继承模式,在子类里没有可以访问父类的方法,当你删除了子类的say方法时,父类的say方法就会被调用。
delete batman.say;
batman.say(); // “I am Bruce Wayne”
在新版的ECMAScript标准http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf中已经引入了原型继承模式,通过一个内建的方法Obejct.create(…)
// ECMAScript 5 (future)
var batman = Object.create(parent);

YUI3中的重用

1.对象扩充

在实际应用中,有时并不需要建立继承链,有时只是想在一个对象的基础上扩充一个新的对象,在YUI3中可以通过Y.augment(…)来实现。
下面的例子描述了通过Y.extend和Y.augment的不同
// parent, a.k.a. supplier of functionality
function Programmer(){}
Programmer.prototype.writeCode = function(){};
// a constructor that gets augmented with supplier’s members
function CodeMonkey(){}
Y.augment(CodeMonkey, Programmer);
var monkey = new CodeMonkey();
// a constructor that inherits from the parent-supplier
function Guru(){}
Y.extend(Guru, Programmer);
var guru = new Guru();
alert(typeof monkey.writeCode); // “function”
alert(typeof guru.writeCode); // “function”
// monkey is not a Programmer, while guru is
alert(monkey instanceof Programmer); // false
alert(guru instanceof Programmer); // true
我们可以看出monkey和guru都有了writeCode这个方法,但是仅仅guru是继承链的一部分
Y.augment也可以从一个构造函数扩充一个对象
var n00b = {};
Y.augment(n00b, Programmer);
// now n00b can writeCode
alert(typeof n00b.writeCode); // “function”
Y.augment还有一些选项,如第三个参数表示是否覆盖存在的属性(默认false),第四个参数是一个数组,定义了一个要扩充的白名单属性列表。

2.对象克隆

对象克隆是代码重用的另一种方式,它创建了和原对象一样的新对象,和Y.Object()的原型继承不同,对象克隆会把父对象的属性直接拷贝到子对象,而不是通过原型链。Y.clone()创建了一个深拷贝,它创建的拷贝是按值传递的,因此修改子/父对象互不影响。
// original object
var pro = {groks: ['html']};
// inherit
var wiz = Y.Object(pro);
// clone
var clone = Y.clone(pro);
pro.groks.push(’css’);
wiz.groks.join(); // “html,css”
wiz.groks.push(’js’);
pro.groks.join(); // “html,css,js”
clone.groks.join(); // “html”
clone.groks.join(); //”html”

3.对象混合

混合模式可以让你从多个对象获取属性和方法来创建一个新的对象,YUI3提供了Y.merge()这个方法
var mad_skillz = {bake: function(){}, mix: function(){}, eat: function(){}};
var ingredients = {sugar: “lots”, flour: 1, eggs: 2};
var dairy = {milk: 1};
// mixin
var cake = Y.merge(mad_skillz, ingredients, dairy);
Y.Object.keys(cake).join(); // “bake,mix,eat,sugar,flour,eggs,milk”
Y.merge和Y.clone很像,但是不同是Y.merge是浅拷贝并且可以通过同一个方法混合多个对象,当出现属性名冲突时,最后的会覆盖前面的。
Y.mix(…)是一个基础方法,它可以控制哪些属性可以被拷贝以及哪种模式,还可以混合同名属性,或忽略一些属性等。
// an object
var pro = {
groks: ['html', 'css', 'js'],
speaks: ['Latin'],
tweets: true
};
// a constructor
function WebGuru(){}
// augmenting the prototype of the constructor
// with some of pro’s properties
Y.mix(WebGuru, pro, true, ['groks', 'tweets'], 4);
// test
var guru = new WebGuru();
guru.groks.join(); // “html,css,js”
guru.tweets; // true
guru.speeks; // undefined
Y.mix有5个参数,参数1-对象接收者,参数2-对象提供者,参数3-是否覆盖,参数4-白名单列表,参数5-混合模式【default(0): object to object, 1: prototype to prototype (old augment)
2: prototype to prototype and object props (new augment), 3: prototype to object, 4: object to prototype】

想了解更多请阅读:

YUIBlog的“Inheritance Patterns in YUI 3”

YUIBlog的More code reuse patterns in YUI3”

克军的“YUI 3.x 中的Loader组件”

Jayli的“yui3中的面向对象”

返回顶部