书单推荐

# 《单页Web应用:JavaScript从前端到后端》http://download.csdn.net/detail/epubitbook/8720475

# 《MVC的JavaScript Web富应用开发》

http://download.csdn.net/detail/u012070181/7361155

SPA单页Web富应用,顾名思义,就是只有一张Web页面的应用。浏览器一开始会加载必须的HTML、CSS 和 JavaScript,只有所有的操作都在这张页面上完成,这一切都是由JavaScript来控制。因此,单页Web应用必将包含大量的JavaScript代码,复杂度可想而知,模块化开发和框架设计的重要性不言而喻。

随着单页Web应用的崛起,各种框架也不断的涌现,如Vuejs、ReactJs、Angularjs、Backbone.js、Ember.Js等,还有RequireJS等模块加载器。但是,本书没有讲解这些框架和模块加载器,这也正是我喜欢书本的原因之一。作者自己很少使用框架,并且框架的限制过多,一旦不符合框架本身的设计哲学,结果可能适得其反。———— 事实上所有的框架使用都是如此。

但不管是使用框架还是按照书的方法开发,书中的思想都是适用的。

第一个SPA应用

width:100%;

height:100%;

overflow:hidden;

background: #777;

}

#spa {

position: absolute;

top: 8px;

left: 8px;

right: 8px;

bottom: 8px;

border-radius: 8px 8px 08px;

background: #fff;

}

.spa-slider {

position: absolute;

bottom:0;

right: 2px;

width: 300px;

height: 16px;

cursor: pointer;

border-radius: 8px 0 0 0;

background: #f00;

}

var spa = (function( $ ) {var$chatSlider,toggleSlider,onClickSlider,initModule;var configMap ={

extended_height :434,

extended_title :'Click to retract',

retracted_height :16,

retracted_title :'Click to extend',

template_html :'

toggleSlider= function() {var slider_height =$chatSlider.height();if( slider_height ===configMap.retracted_height) {

$chatSlider.animate({height: configMap.extended_height})

.attr('title',configMap.extended_title);return true;

}else if (slider_height ===configMap.extended_height) {

$chatSlider.animate({ height : configMap.retracted_height})

.attr('title',configMap.retracted_title);return true;

}return false;

};

onClickSlider= function( event ) {

toggleSlider();return false;

};

initModule= function( $container ) {//render HTML

$container.html(configMap.template_html);

$chatSlider= $container.find( '.spa-slider');

$chatSlider.attr('title', configMap.retracted_title)

.click( onClickSlider );return true;

};return{

initModule : initModule

}

}( jQuery ));

$(function(){

console.log(spa);

spa.initModule($('#spa'));

})

View Code

变量作用域

要么全局,要么局部,而javascript中唯一能定义变量作用域的语块就只有函数。

换个方式来看,函数就像监狱(prison),在函数中定义的变量就像是囚犯(prisoner).

正如监狱限制囚犯不让他们从监狱逃脱一样,函数也限定了局部变量不让他们逃脱到函数之外:

functionprison () {var prisoner = 'i am local!'}

prison();

console.log(prisoner);//prisoner is not defined

要是真这么简单就好了!!!这里有一个Javascript 作用域的陷阱,可以在函数中声明全局变量。成功帮助囚犯(prisoner)越狱。那就是只要忽略 var 关键字即可:

functionprison () {

prisoner= 'i am local!' // 没有书写 var 关键字}

prison();

console.log(prisoner);//i am local!

这种陷阱经常出现在for循环计数器中。所以请务必要避免这种错误:

# 错误的做法,没有书写var关键字functionprison () {for( i = 0 ; i < 10 ; i++) {//...

}

}

prison();

console.log(i);//i is 10

# 正确的做法,养成 var 定义变量的方式functionprison () {for( var i = 0 ; i < 10 ; i++) {//...

}

}

prison();

console.log(i);//i is not defined

变量提升

在JavaScript的函数中,当变量被声明时,声明会被提升到所在函数的顶部。然后被赋予undefined值。这就使得在函数的任意位置声明变量都将存在于整个函数中。尽管它在赋值之前,它的值一直是undefined。

functionprison () {

console.log(prisoner);//undefined

var prisoner = "Lee";

console.log(prisoner);//Lee

}

全局作用域和变量提升的行为结合时,需要注意仍然遵循变量提升的规则

var prisoner = "Mp";functionprison () {

console.log(prisoner);//undefined

var prisoner = "Lee";

}

Javascript 对象 和 原型链

Javascript 对象是基于原型的,而当今其他广泛使用的语言全部是基于类的对象。

- 在基于类的编程中,使用类来描述对象是什么样子的;

- 在基于原型的编程中,我们需要先创建一个对象,然后告诉Javascript引擎,我们想要更多想这样的对象;

打个比方,如果建筑是基于类的系统,则建筑师会先画出房子的蓝图,然后房子按照该蓝图建造。

如果i建筑师基于原型的,建筑师会先建造一所房子,然后将房子都建成像这种模样的。

我们使用先前囚犯的示例,对比一下两种编程方式的不同。创建一名囚犯所要的条件有哪些,囚犯的属性包括名字(name)、囚犯ID、性别(sex)和年龄(age)。

基于类的编程方式,以C#为例

/*step 1 :定义类*/public class Prisoner {publicint sex = 0;

publicint age = 30;

public string name;

public string id;/*step 2 : 定义构造函数*/public Prisoner ( string name, string id) {this.name =name;this.id =id;

}

}/*step 3 : 实例化对象*/Prisoner firstPrisoner= new Prisoner( 'Joe', '12A');

Prisoner secondPrisoner= new Prisoner( 'Sam', '2BC' );

基于原型的编程方式,以javascript为例

/*step 1:定义原型*/

var info ={

sex :0,

age :18};/*step 2:定义对象的构造函数*/

var Prisoner = function( name, id ) {this.name =name;this.id =id;

}/*step 3:将构造函数关联到原型*/Prisoner.prototype=info;/*step 4 :实例化对象*/Prisoner firstPrisoner= new Prisoner( 'Joe', '12A');

Prisoner secondPrisoner= new Prisoner( 'Sam', '2BC' );

通过两种不同的编程方式和step步骤的对比,我们发现它们都遵循类似的顺序,如果你习惯了类,则适应原型应该不难。但魔鬼隐藏在细节中,如果你没有学习基于原型的相关知识,就以其他语言的类编程理解方式一头扎进Javascirpt,很容易被某些看起来简单的东西绊倒。我们通过上述两个demo,来总结一下:

1、两者都首先创建了对象的模板

2、模板在基于类的编程中叫做类,在基于原型的编程中叫做原型对象

3、构造函数。在基于类的语言中,构造函数是在类的内部定义的。当实例化对象时,就十分的清晰明了。在Javascript中,对象的构造函数和原型对象是分开设置的。所以需要额外多一步来将它们连接在一起。

4、实例化对象,javascript使用new操作符。这实际上违背了它基于原型的核心思想,可能是试图让熟悉基于类继承的开发人员更容易理解。不幸的是,大部分开发人员容易搞混淆了。

基于第4个问题,我们的解决方案是使用 Object.create 作为 new 操作符的代替,使用它来创建Javascript对象时,更接近原型开发的感觉:

var info ={

sex :0,

age :18};

Prisoner firstPrisoner=Object.create( info );

firstPrisoner.name= 'Joe';

firstPrisoner.id= '12A';

Prisoner secondPrisoner=Object.create( info );

secondPrisoner.name= 'Sam';

secondPrisoner.id= '2BC';

但这样手动设置每个对象的成员变量name和id是痛苦的,因为会有重复的代码显得不整洁。另一种更优的方案是,使用object.create + 工厂模式,来创建并返回最终的对象:

var info ={

sex :0,

age :18};var FactoryPrisoner = function( name, id ) {var prisoner =object.create( info );

prisoner.name=name;

prisoner.id=id;returnprisoner;

}var firstPrisoner = FactoryPrisoner( 'Joe', '12A');var secondPrisoner = FactoryPrisoner( 'Sam', '2BC' );

函数 —— 更深入的窥探

理解函数是理解Javascript的关键之一,是构建专业的单页应用的重要基础。

自执行匿名函数

在 javascript 的开发过程中,我们经常遇到一个问题:在全局作用域中定义的东西在每个地方都可用。但有时候我们不想和所有人共享这些内容,或因为这很可能覆盖对方的内容。比如自己在开发第三方库、创建javascript插件的时候,不希望使用者使用内部变量。

# demo 1(function(){var private_variable = "private";

})();

console.log(private_variable);//private_variable is not defined

# demo 2

var prison = (function(){return "Lee is in prison";

})();

console.log(prison);//Lee is in prison

# demo 3(function($){

console.log($);

})(jQurey)

模块模式

单页应用非常庞大,不能定义在一个文件中。我们应该将文件分为一个个的模块,每个模块都有它们自己的私有变量;

我们仍然使用自执行匿名函数来控制变量的作用域,并且把代码分为多个文件:

var prison = (function(){var prisoner_name = 'Lee',

jail_term= '20 year term';return{

prisoner : prisoner_name,

sentence : jail_term

};

})()

console.log(prison.prisoner_name);//undefined

console.log(prison.prisoner); //Lee

console.log(prison.sentence); //20 year term

prison.prisoner_name= "Mp";

console.log(prison.prisoner);//Lee

这里出现一个问题, prison.prisoner_name 没有被更新,这里有2个原因:

1、它是在函数中使用了 var 关键词创建的局部变量。无法被外部访问;

2、它不是对象或者原型上的属性,所以它无法访问或者赋值;

也就是说,这些匿名函数中定义的属性,是无法通过外部直接调用或者赋值的。为了能更新它们,我们的做法是添加内部方法来访问并且修改内部的变量

var prison = (function(){var prisoner_name = 'Lee';return{

prisoner : prisoner_name,

update_prisoner_name :function(name) {

prisoner_name=name;

},

out_prisoner_name :function(){returnprisoner_name;

}

};

})()

console.log(prison.prisoner);//Lee

prison.update_prisoner_name("Mp");

console.log(prison.prisoner);//Lee

console.log(prison.out_prisoner_name()); //Mp

我们注意到,我们依然不能在该对象或者原型上直接访问。我们只能使用匿名函数返回的对象中的方法来访问。这也是利用了【闭包】

什么是闭包?

闭包是一种抽象的概念,理解起来可能有些困难,所以在回答什么是闭包之前,先了解一些背景知识。

随着程序的运行,它们会因各种事情而占用计算机的内存,比如保存变量的值。如果程序运行了却从不释放不再需要的内存,久而久之会导致电脑崩溃。

在一些语言中,如C,内存的管理都是由程序员处理的。而像Java 和 Javascript,实现了自动释放内存的机制,当代码不再需要时,就自动从电脑的内存中移除它。这种自动化系统叫做垃圾回收器。关于内存是手动释放好还是自动释放好这里不讨论,只要知道Javascript 有垃圾回收机制就足够了。

那么问题来了,javascript垃圾回收器是怎么知道哪些东西【不再需要的】呢?万一把我想保留的变量移除了怎么办,有什么方法可以让某些变量不被回收?

我们先来回答第一个问题:javascript垃圾回收器比较一根筋!!

它想:既然函数已经执行完毕了,我们应该就不再需要访问该函数环境中的东西了。

所以当函数执行完毕时,函数中所有创建的东西就会从内存中移除。

回答第二个问题:有的,这种方法被称之为闭包!

varmenu,

outer_function;

outer_function= function() {var fruit = 'apple';var food = 'cake';return function() {return{

food : food,

fruit : fruit

}

}

}

menu= outer_function(); //inner_function

console.log(menu()); //{food: "cake", fruit: "apple"}

从上面这个demo中我们发现,尽管outer_function()函数执行完毕了。理论上内部的两个变量 fruit 和 food 应该被销毁。但我们现在却可以使用menu()来获取。

这种解决方法就叫闭包。使用闭包的套路其实很简单:一个返回函数的函数!

java 单页面spa_Javascript 与 SPA单页Web富应用相关推荐

  1. 什么是单页面应用(SPA)和多页面应用(MPA)

    背景 最初我们的应用都是多页面应用,多页面应用就是每次客户单请求都返回一个新的页面.在互联网初期,这个问题并没有带来很差的用户体验,但是随着移动互联网的发展以及用户的体验, 开发者开始考虑,为什么我们 ...

  2. 什么是单页面应用(竞价单页面)

    在早期的 Web 应用中,前端的作用很弱,业务逻辑和数据处理都在后端,后端给前端返回一个 HTML 页面,前端只负责展示.在这种模式下,单个 HTML 页面被当做一个功能原件,表单提交,超链接跳转都可 ...

  3. H5中的history单页面,手动实现单页面开发,细说h5单页面原理

    就目前来看,前端的单页面开发占了很大一部分,一方面无刷新的切换增强了体验,并且浏览器记录依然存在,前进后退都没问题,在之前我们通地址栏中的hash改变来触发onhashchange方法来实现单页面应用 ...

  4. html5 移动端单页面布局,移动端单页布局-如何更好的自适应各尺寸屏幕

    #### 移动端单屏布局 > 本篇不属于汇总类的文章,而是把自认为最优的解决方案来进行一些说明. #### 为什么会有单屏布局 作为一个前端开发者,我是实在没有理解单屏布局的优势在哪里,尤其是要 ...

  5. 前端单页面拆分多个单页面

    问题现状 后端采用 ==多服务 + nginx== 的技术架构 根据业务拆分成不同的项目,具体服务通过location由nginx转发代理到不同的机器(端口)上. 前端采用的是 ==dva + roa ...

  6. uniapp 表单页面_uniapp自定义表单模板经验分享

    极简属性:data (仅提供方法和极简示例,实践党可自行扩展,伸手党请绕行) 表单组件通用 注:此data是组件的一个隐藏属性 示例: template: {{sexs[grouplist.sexIn ...

  7. java实现页面高效刷新_selenium高效应对Web页面元素刷新的实例讲解

    当我们在页面上进行selenium.type()或者selenium.click()操作的时候,往往需要需要等待一个元素的出现,对于一般的网页,当我们进入一个新页面的时候,往往会使用selenium. ...

  8. 单页面 Web 应用(Single Page Application,SPA)的工作原理介绍

    原文地址 SPA 无处不在,但在网络开发人员中仍然是一个颇有争议的话题. 自 2003 年左右首次出现以来,单页 Web 应用程序已经取得了长足的进步.它们已成为现代 javascript 领域不可或 ...

  9. 对SPA(单页面应用)的总结

    目录 1.单页面应用(SPA)的概念: 2.作用(好处) 3.缺点 4.实现SPA 1.单页面应用(SPA)的概念: 1.single-page application是一种特殊的Web应用.它将所有 ...

最新文章

  1. SecureCRT如何与Linux虚拟机进行关联
  2. 微软从水里捞起了一个数据中心:存储效果更好,故障率仅陆上1/8
  3. 将Java程序作成exe文件的几种方法【转载】
  4. 14-运算符(比较、三元、逻辑)14-运算符(比较、三元、逻辑)
  5. Python如何将列表分成均匀大小的块?
  6. 多系统通讯-DotNetMQ
  7. 获取2个地址之间的距离(高德API)
  8. P1352-没有上司的舞会【树形dp】
  9. 二维数组 类型_Java第六章 | 二维数组的创建及使用、数组排序算法
  10. 谁给讲讲语音识别中的CTC方法的基本原理?
  11. 小规模团队如何“微服务”管理
  12. 飓鼎玩笑傲江湖服务器维护,12月24日维护更新公告 - 笑傲江湖12月24日维护更新公告 - 17173笑傲江湖官网合作专区 - 17173.com中国游戏第一门户站...
  13. win7精简_还不升级!Bug最少的win10 LTSC版,极致精简,比win7更快更干净
  14. win10 java jdk环境变量 配置
  15. 自定义chrome新标签页
  16. 【MYSQL】MYSQL 主要函数
  17. 英特尔暂缓扩建大连芯片厂 或吞并全球最大芯片生厂商之一美光科技
  18. ubuntu 搜狗输入法突然只能输入拼音
  19. 西北工业大学NOJ-Python程序设计作业81-90
  20. Windows Server 2012 R2 搭建FTP服务

热门文章

  1. 帮朋友处理一个excel的问题(我也学到了)
  2. Couple number
  3. VUE - v-charts 图表高级设置
  4. MaxCompute执行引擎核心技术DAG揭秘
  5. Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置
  6. 社会主义核心价值观PPT模板
  7. 实验10 Bezier曲线生成
  8. 给定两个字符串str1和str2,查找str2在str1中出现的位置
  9. oracle-账户解锁
  10. WordPress代码和分析-页面模板是从哪里来的