扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
js中继承跟java中的继承不太一样,一般通过call()和apply()两种方式完成,js中的继承是以复制的形式完成的,复制一个父对象,而不像java中直接继承父对象,还有通过原型的方式完成继承,也有弊端,总之js中的继承只是形式上的对面向对象语言的一种模仿,本质上不是继承,但用起来效果是一样的
10余年的金林网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。营销型网站建设的优势是能够根据用户设备显示端的尺寸不同,自动调整金林建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。成都创新互联从事“金林网站设计”,“金林网站推广”以来,每个客户项目都认真落实执行。
至于为什么要继承:通常在一般的项目里不需要,因为应用简单,但你要用纯js做一些复杂的工具或框架系统就要用到了,比如webgis、或者js框架如jquery、ext什么的,不然一个几千行代码的框架不用继承得写几万行,甚至还无法维护
Base做的事情包括:
给模块增加自定义事件支持
给模块增加set和get方法
设置一些默认执行的方法,比如_init
提供模块的构建功能
提供模块的扩展功能
自定义事件
自定义事件模式是非常实用的,自定义事件用比较专业的词语描述的话,可以称为观察者模式,这种模式背后的主要动机就是促进形成松散耦合。在这种模式中,并不是一个对象调用另外一个对象的方法,而是一个对象订阅另外一个对象的特定活动并在状态改变后等到通知。这意味着我们在做一些事情的时候,不需要关注另外事情的进展,让另外一件事情来监听进展,然后做出对应的处理即可。这样的话,不同的事情之间就不会存在太多的关联,从而降低开发的复杂度。
set和get方法
为了保护和更好地稳定模块的执行,需要对模块参数的修改做一些限制和处理。所以需要提供set和get方法(现在的Base还没有在get的时候做一些处理),set可以用于在设置模块属性的时候,做一些过滤和处理,保证设置值的正确性,而且更重要的是,可以在set中触发一个属性修改的事件,从而可以做到修改属性的时候触发一些其他的变化。get则可以用于在访问属性的时候,对返回的属性做一些处理。对于模块内部而言,还需要有一个私有的_set和_get属性,从而可以和外部对模块的访问进行区分。
一些默认执行的方法
默认执行的方法会在两个地方存放,一个是在构造函数中,还有一个是在模块原型上的initliazer方法中。构造函数内主要处理模块间和实例的关系,这些处理是会继承到子模块中的,而在initliazer中主要处理模块真正相关的要执行的一些实例化方法,这样能保证模块在被继承的时候,自有的一些初始化方法不会被继承下去。而initliazer方法是由_init方法调用的,_init方法是模块实例化的时候必定会执行的方法,而initliazer是一个可选的初始化方法。
模块的构建和扩展
Base核心部分就是对模块的构建和扩展。先上代码
Base._build = function (moduleName, superModule, prototypeMethod, attrMember, staticMember, curConstructor) {
//使用prototype方式继承
var Module = function () {
Module.superclass.constructor.apply(this, arguments);
//保存对实例的引用
Module._instances[$.zid(this)] = this;
};
if(curConstructor){
Module = curConstructor;
}
//如果给定了构造函数,就在给定的构造函数上进行扩展,否则试用默认的构造函数
return Base._handlerClass(moduleName, Module, superModule, prototypeMethod, attrMember, staticMember)
};
Base._handlerClass = function (moduleName, module, superModule, prototypeMethod, attrMember, staticMember) {
var tempFn = function () {
},
o = {
name:moduleName,
value:module
};
//创建对象来保存实例的引用
module._instances = {};
//模块NAME
if (moduleName) {
module.NAME = moduleName;
}
/*Module.toString = function(){
return moduleName;
};*/
//如果没有传入要继承的对象,则默认为Base
superModule = superModule || Base;
attrMember = attrMember || {};
staticMember = staticMember || {};
prototypeMethod = prototypeMethod || {};
//挂载ATTRS属性
//如果是继承于另外一个模块,则需要将ATTRS进行合并处理
if (superModule.NAME !== BASE) {
$.extend(attrMember, superModule.ATTRS);
}
//@20120830修复构造函数自带ATTRS时对应的处理方式
module.ATTRS = module.ATTRS || {};
$.extend(module.ATTRS, attrMember);
//挂在静态属性
$.extend(module, staticMember);
//拷贝一份prototype,防止构造函数直接执行
tempFn.prototype = superModule.prototype;
module.prototype = new tempFn();
//把方法添加到Module的原型上
$.extend(module.prototype, prototypeMethod);
//修改构造器,防止回溯失败
module.prototype.constructor = module;
//保存对超类的引用
module.superclass = superModule.prototype;
if (superModule.prototype.constructor == Object.prototype.constructor) {
superModule.prototype.constructor = superModule;
}
//保存生成的对象
Base.classList.push(o);
return module;
};
代码细节都有注释,就不多说,主要还是把具体做的事情描述下
确定构造函数。
创建一个空对象来保存实例的引用。
确定模块名。
确定是否继承于其他模块。
拷贝参数的策略(ATTRS)和静态成员
创建原型并拷贝实例成员(原型上的成员)
修复创建原型后构造器指向不对的问题
创建对超类的引用,从而可以手动访问超类
保存生存的对象引用
返回改造完成后的模块
注:以上构造模块的思路主要参考自YUI3的Base模块。
在下一篇中,将用这个Base模块来构建一个tab组件
动态加入到DOM中的对象无法继承原有的事件,所以无效,举例:
// $.ajax... ajax部分省略
var tr = "";
if(data.length){
for(var i=0; idata.length; i++){
tr = 'tr';
tr += 'td' + data.status == 0 ? "正常" : "报警" + 'td';
tr += '/tr';
$("#table1").find("tbody").append(tr);
}
}
// tr的点击事件
$("#table1 tbody").find("tr").click(function(){
// do something
});
上面的例子中,table1中原有的tr标签有点击事件,而通过ajax获取数据动态创建添加到DOM中的tr标签并没有继承点击事件,点击无任何反应。解决办法有两种:
纯js方法:将tr的点击事件写成函数,然后为动态创建的tr标签添加该函数的onclick事件:
for(var i=0; idata.length; i++){
tr = 'tr onclick="OnTrClick()"'; // 创建时为tr指定click事件
tr += 'td' + data.status == 0 ? "正常" : "报警" + 'td';
tr += '/tr';
$("#table1").find("tbody").append(tr);
}
jquery方法:jquery中可使用live()、on()两个方法来完成类似效果,其原理是利用事件委派机制,需要注意的是jquery 1.9版本已不再支持live()方法。
// tr的点击事件 (jquery 1.9以下)
$("#table1 tbody").find("tr").live("click", function(){
// do something
});
// tr的点击事件【推荐】 (jquery 1.7以上)
$("#table1 tbody").find("tr").on("click", function(){
// do something
});
1、活版印刷
一个成功的网站只有很少的字体是类似的款式,而不是使用的字体。最好的网站应该使用无衬线和无衬线字体,而不是两者的结合。
印刷术的网站也应该小心使用的字体,好的设计会加入一些类似的字体,而不是一个范围内型面。大多数浏览器都能识别特定数量的安全字体,这样设计主要是利用以避免并发症的发生。
2、代码质量
当创建一个网站,它是很好的做法,以符合标准。这包括代码中的错误,代码为更好的布局,以及确保你的ID和类的正确识别。这通常是通过描述指定元件做什么。
不符合标准的网站无法使用或容易出错的,标准可以涉及到正确的页面布局的可读性,以及确保适当地关闭了编码元素。DOCTYPE声明,这是用来突出显示代码中的错误。系统识别错误和不符合网页设计标准。
3、视觉设计
良好的视觉设计网站上的标识,其目标市场。这可以是一个年龄组或特定的文化链,因此,设计人员应了解其受众的趋势。设计人员也应该明白他们设计的,这意味着一个企业网站不应该被设计成一个社交媒体网站,例如相同类型的网站。
4、交互设计
对于网站来说,好的交互设计对网页设计的整体起着至关重要的作用,一个好的交互不仅能大大提升页面整体的设计效果,增强页面的“活跃度”,还能有效提高用户体验,“屏蔽”单调的操作流程,使得产品、文化的表现都能最大化的呈现并传达到相关的受众。
5、内容更新
企业Web站点建立后,要不断更新网页内容。站点信息的不断更新,让浏览者了解企业的发展动态和网上职务等,同时也会帮助企业建立良好的形象。
参考资料来源:百度百科-网页设计
什么是backbone
backbone不是脊椎骨,而是帮助开发重量级的javascript应用的框架。
主要提供了3个东西:1、models(模型) 2、collections(集合) 3、views(视图)
backbone.js文件本身很小,压缩后只有5.3KB,作为一个框架级别的核心JS文件,这个数字很可怕。
除此之外,这个JS还必须依赖于另一个JS文件:underscore.js(包含许多工具方法,集合操作,js模板等等)。
简介
用Backbone.Model表示应用中所有数据,models中的数据可以创建、校验、销毁和保存到服务端。
当models中值被改变时自动触发一个"change"事件、所有用于展示models数据的views都会侦听到这个事件,然后进行重新渲染。
Backbone.Collection和我们平时接触的JAVA集合类相似,具有增加元素,删除元素,获取长度,排序,比较等一系列工具方法,说白了就是一个保存models的集合类。
Backbone.View中可以绑定dom el和客户端事件。页面中的html就是通过views的render方法渲染出来的,当新建一个view的时候通过要传进一个model作为数据,例如:
Js代码
var view = new EmployeeView({model:employee});
也就是说model就是以这种方式和view进行关联的。
特点
创建models或者views的语法:extends,相当于类继承
models的创建,销毁,校验等一系列改变都会触发相应的事件
示例
需求:用backbone.js和jquery实现一个可编辑的员工信息表格。
功能:1、录入员工信息。2、删除员工信息。3、双击表格可对员工信息进行修改。4、能对员工信息进行有效性校验。5、能对员工信息进行持久化。
设计:
用Employee类(继承自Backbone.Model)表示员工信息,包含ID、姓名、性别、年龄和职位字段。
Js代码
window.Employee = Backbone.Model.extend({
// 模型值校验
validate:function(attrs){
for(var key in attrs){
if(attrs[key] == ''){
return key + "不能为空";
}
if(key == 'age' isNaN(attrs.age)){
return "年龄必须是数字";
}
}
}
});
声明Employee类之后就可以新增一个Employee的示例对象了:
Js代码
var employee = new Employee();
Employee类中不必声明ID、姓名等业务字段。当需要给employee设置这些信息时候,只需要调用
Js代码
employee.set({'id':1,'name':'Jason'});
当然,如果需要对employee的信息进行校验,需要给Employee类配置一个validate方法,这个方法的参数attrs就是set进去的json数据。这样,当employee里面的数据每次发生改变的时候都会先调用这个validate方法。
Model类定义好之后就可以开始定义集合类了,在集合类里面可以对里面的每个Model进行增加,删除等一系列操作,还可以调用fetch方法从server端获取集合的初始值。
Js代码
window.EmployeeList = Backbone.Collection.extend({
model : Employee,
// 持久化到本地数据库
localStorage: new Store("employees"),
});
window.Employees = new EmployeeList();
设置 localStorage属性后Employees里面的数据自动会同步保存到本地数据库里面,每当调用Employees.fetch()后又会从localStorage里面恢复数据。
View类主要负责一切和界面相关的工作,比如绑定html模板,绑定界面元素的事件,初始的渲染,模型值改变后的重新渲染和界面元素的销毁等:
Js代码
window.EmployeeView = Backbone.View.extend({
tagName : 'tr',
template : _.template($('#item-template').html()),
events : {
"dblclick td" : "edit",
"blur input,select" : "close",
"click .del" : "clear",
},
initialize : function(){
// 每次更新模型后重新渲染
this.model.bind('change', this.render, this);
// 每次删除模型之后自动移除UI
this.model.bind('destroy', this.remove, this);
},
setText : function(){
var model = this.model;
this.input = $(this.el).find('input,select');
this.input.each(function(){
var input = $(this);
input.val(model.get(input.attr("name")));
});
},
close: function(e) {
var input = $(e.currentTarget);
var obj = {};
obj[input.attr('name')] = input.val();
this.model.save(obj);
$(e.currentTarget).parent().parent().removeClass("editing");
},
edit : function(e){
// 给td加上editing样式
$(e.currentTarget).addClass('editing').find('input,select').focus();
},
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
// 把每个单元格的值赋予隐藏的输入框
this.setText();
return this;
},
remove: function() {
$(this.el).remove();
},
clear: function() {
this.model.destroy();
}
});
这个类里面的代码比较多,但主要和界面的渲染有关。一个EmployeeView对象对应table里面的一个tr元素。每次new一个EmployeeView对象的时候都会先调用initialize方法,这个方法里面绑定的事件确保了tr元素对应的model值每次发生改变或者被删除时都会同步到界面。也就是说当每次操作界面对数据进行修改后都是先把当前的变更保存到view绑定的model对象里面,然后model里面的事件机制会自动触发一个"change"事件对界面进行修改。
template中使用的方法_.template($('#item-template').html())是前面提到的underscore.js中提供一个工具方法,可以通过界面的HTML模板和一个JSON生成动态的HTML,说白了就是把JSON里面的值填充到HTML模板中对应的占位符里面去,牛X的是HTML模板里面支持一些常用的逻辑表达式如if,else,foreach等:
Html代码
script type="text/template" id="item-template"
td%= eid %/td
td class="username"
div class="display"%= username %/div
div class="edit"input class="username" name="username"/input/div
/td
td class="sex"
div class="display"%= sex=="1" ? "女":"男" %/div
div class="edit"
select name="sex" class="sex" style="width:45px"
option value="0"男/optionoption value="1"女/option
/select
/div
/td
td class="age"
div class="display"%= age %/div
div class="edit"
input class="age" name="age"/input
/div
/td
td class="position"
div class="display"%= position %/div
div class="edit"
input class="position" name="position"/input
/div
/td
td
a href="#" class="del"删除/a
/td
/script
setText方法主要负责把model里面的数据设置到每个tr里面的隐藏输入域里面。
close方法被绑定到了input和select元素的blur事件中。当用户对单元格数据进行修改后都会把鼠标点击到界面其他地方然后输入框会自动隐藏并且把修改的数据显示在表格上面。close方法首先从当前被编辑的元素中拿到最新值,然后封装成一个对象,调用model的save方法后首先执行model的validate方法,如果校验通过则保存到本地存储并触发"change"事件。
最后还需要一个主界面View,这个View主要绑定了界面中的录入表单的“增加”按钮事件,Employees的相关事件以及页面初始化时从本地存储中恢复数据:
Js代码
window.AppView = Backbone.View.extend({
el : $("#app"),
events : {
"click .#add-btn" : "createOnEnter"
},
// 绑定collection的相关事件
initialize: function() {
Employees.bind('add', this.addOne, this);
// 调用fetch的时候触发reset
Employees.bind('reset', this.addAll, this);
Employees.fetch();
},
createOnEnter : function(e) {
var employee = new Employee();
var attr = {};
$('#emp-form input,#emp-form select').each(function(){
var input = $(this);
attr[input.attr('name')] = input.val();
});
employee.bind('error',function(model,error){
alert(error);
});
// set方法中会自动调用model的validate方法进行校验,如果不通过则返回false
if(employee.set(attr)){
Employees.create(employee);
}
},
addOne : function(employee){
employee.set({"eid":employee.get("eid")||Employees.length});
employee.bind('error',function(model,error){
alert(error);
});
var view = new EmployeeView({model:employee});
$(".emp-table tbody").append(view.render().el);
},
addAll : function(){
Employees.each(this.addOne);
}
});
initialize方法中绑定了Employees的add和reset事件,也就是说每当往Employees中添加一个model的时候都会调用AppView的addOne方法,这个方法主要绑定了model的error事件以及把EmployeeView生成的html插入到界面中的合适位置。
OK,万事俱备,只欠启动,整个应用的初始化方法就是AppView的initialize方法,因此只需要新建一个AppView就可以了:
Js代码
window.App = new AppView();
整个示例的JS代码很少,加上注释只有100行左右,感兴趣的
应该不存在jq对象这一概念的吧,jq是用JS写的,所以应该是指JS的继承吧,JS是通过原型链实现继承的。首先所有的函数类都是继承自obejct,object继承自null(即object的__proto__指向null,你定义的函数类的__proto__指向object的prototype),然后你new出来的函数类对象上的__proto__就指向函数类的prototype。当需要访问对象的某个属性或函数的时候就会沿着this和__proto__一直往上找。这样实现继承。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流