来自 奥门威尼斯网址 2019-09-17 19:53 的文章
当前位置: 威尼斯国际官方网站 > 奥门威尼斯网址 > 正文

AngularJs前端架构

用“MEAN”技术栈开发web应用(一)AngularJs前端架构

2015/09/09 · CSS, HTML5, JavaScript · 1 评论 · MEAN

原文出处: 吕大豹   

angular路由

前言

不知何时突然冒出“MEAN技术栈”这个新词,听起来很牛逼的样子,其实就是我们已经熟悉了的近两年在前端比较流行的技术,mongodb、express、angularjs、nodejs,由于这几项技术涵盖了从前端到后端再到数据库,可以用他们完整的开发一个web应用了,所以成了一个非常牛逼的组合,颇有当年LAMP的气势。前端要从切图仔迈向全栈的路上,这几门技术必须得有所涉猎。本系列文章利用自己虚构的一个小项目为例,对“使用MEAN技术栈开发web应用”做一个入门级的介绍。

北京小课堂

分享人:吴昊杰

目录

1.背景介绍

2.知识剖析

3.常见问题

4.解决方案

5.编码实战

6.拓展思考

7.参考文献

8.更多讨论

AngularJs的争议

angular,简称ng,是google出品的优秀框架,在2013~2014年大红大紫,但是国内好像慢一拍,我从2015年才看到使用ng的项目大量出现。ng自出现伊始就有人诟病太难上手了,完全不同的开发方式,团队开发更是不知道如何组织代码。不过随着jquery这位老大哥逐渐被抛弃,大家开始慢慢接受mvvm这样的编程思维。然而一个不好的消息是,ng团队打算重构的angular2.0版本要发生重大变革,与1.0不能同日而语,虽然官方有1.0向2.0迁移的方案,但额外的工作总是不太好的,而且使用2.0还要付出更多的学习成本。

再加上今年又有react这个实力派雄起,ng的风头顿时被抢过去了,人们又开始研究react下的编程方式。不过我估计react的真正实用也得等到一两年后。眼下angular1.x也仍然是一个不错的选择。尽管有2.0的变革,但是1.4还是一个稳定版本,我们使用稳定版本肯定是不会有问题的。

所以我的结论是,但用无妨,不会存在白学了这种事情,就算将来angular1.x废弃了,你学到的编程思维还是在的。

本文讨论如何使用AngularJs进行前端的架构,对于ng的基础知识不做讲解,需要了解的同学可以看我之前写过的一个系列

1.背景介绍

一般来说,我们认为AngularJS是一套前端的MVC框架。那么,为了实现视图的中转,肯定会涉及到路由的概念。这里我们就来说说有关AngularJS的路由——ngRoute。

首先谈谈APP应用。平时我们用的app总是多页面,如果用原生安卓或者苹果,那当然很流畅啦。但是当我们用一般的html页面做移动端,简单时候我们可以用这样的标签去链接页面时,速度还是可以的。   但是当我们的应用越来越多时,切换起来没那么流畅。又是碍于网速,页面加载进来有点慢。但是在angular里面,我们可以用路由进行切换。因为在angular里面,我们用户一般在加载这样的应用时,会整个的缓存在手机上。我们用路由进行切换时,不用再发起HTTP请求了。体验比原来好。

练手项目简介

为了系统的学习“MEAN”技术栈,我虚构了一个小项目,先做一个介绍。

QuestionMaker,是一个用于生成调查问卷的系统,用户可以编辑试题(选择题、填空题),并可以实时预览编辑结果。然后还可以编辑一份试卷,为试卷添加试题,然后保存为一分完整的调查问卷。有点类似于调查派。先上一张截图吧:

图片 1

项目的功能主要是CRUD操作,所以非常适合angular的应用场景,双向绑定对于实现实时预览这样的功能简直是信手拈来。

项目的前后端是完全分离的,后端不渲染页面,只提供数据接口,前端使用ng的动态模板来渲染页面,通过ajax请求来获取所需数据。

项目我已经开源到github,有兴趣的同学可以查看:

2.知识剖析

ngRoute是一个AngularJS的模块。其不是在AngularJS的核心库当中。

            在使用ngRoute的时候,实际上,我们是在应用的主模块中引入ngRoute模块并添加$routeProvider服务到主模块的config方法中来达到我们的目标。这与其他一些库的使用方式是类似的,如ng-grid。

            在ngRoute中,主要有$route、$routeProvider、$routeParams三个服务项目。

            $routeProvider用于在主应用主模块的配置方法中。$route与$routeParams一般常见于控制器中。

服务$routeProvider用来定义一个路由表,即地址栏与视图模板的映射

服务$routeParams保存了地址栏中的参数

服务$location用来实现用于获取当前url以及改变当前的url,并且存入历史记录

服务$route完成路由匹配,并且提供路由相关的属性访问及事件,如访问当前路由对应的controller

指令ngView用来在主视图中指定加载子视图的区域

angular路由可以实现多视图的单页Web应用。 当请求一个url时,根据路由配置匹配这个url,然后请求模板片段,并插入到ng-view中去。这种做法使网页局部刷新,减少了切换网页时带来的突兀感, 也减少了项目的代码量。

前端目录结构

用ng来构建一个项目应该如何安排目录结构呢?为了不人工增加复杂度,我这里没有用bower来管理依赖库,也没有其他文章中介绍的那样用yeoman来生成项目,只是单纯的手动来创建目录,这样可以把我们的注意力集中到项目的核心上,目录结构是这样的:

前端的代码都在src目录下,包括入口文件index.html,这样方便我们后续做合并压缩等编译工作,编译后的文件可以一并放入dist目录下。

3.常见问题

ngRoute实现原理和如何使用路由?

首页index.html

这是项目的入口页面,其实就是一个大容器,在这里加载所有的js和css文件,然后提供一个视图容器就够了,因为从这个页面以后,我们页面就不再会有跳转,全部是通过前端路由来做局部刷新,首页的代码非常精简:

JavaScript

<!doctype html> <html ng-app="QMaker"> <head> <meta charset="utf-8"> <title>Question Maker</title> <link rel="stylesheet" href="/src/lib/bootstrap-3.3.5/css/bootstrap.min.css"> <script src="/src/lib/jquery-1.9.1.min.js"></script> <script src="/src/lib/angular-1.4.1.min.js"></script> <script src="/src/lib/angular-ui-router.min.js"></script> <link rel="stylesheet" href="/src/css/base.css"> <!--{main}--> <script src="/src/js/app.js"></script> <script src="/src/js/controllers.js"></script> <script src="/src/js/directives.js"></script> <script src="/src/js/filters.js"></script> <script src="/src/js/routes.js"></script> <script src="/src/js/services.js"></script> <!--{endmain}--> </head> <body> <div class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a href="#/" class="navbar-brand">Question Maker</a> </div> </div> </div> <div class="maincontent container-fluid" ui-view> </div> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!doctype html>
<html ng-app="QMaker">
<head>
    <meta charset="utf-8">
    <title>Question Maker</title>
    <link rel="stylesheet" href="/src/lib/bootstrap-3.3.5/css/bootstrap.min.css">
    <script src="/src/lib/jquery-1.9.1.min.js"></script>
    <script src="/src/lib/angular-1.4.1.min.js"></script>
    <script src="/src/lib/angular-ui-router.min.js"></script>
 
    <link rel="stylesheet" href="/src/css/base.css">
    <!--{main}-->
    <script src="/src/js/app.js"></script>
    <script src="/src/js/controllers.js"></script>
    <script src="/src/js/directives.js"></script>
    <script src="/src/js/filters.js"></script>
    <script src="/src/js/routes.js"></script>
    <script src="/src/js/services.js"></script>
    <!--{endmain}-->
</head>
 
<body>
    <div class="navbar navbar-default">
        <div class="container-fluid">
            <div class="navbar-header">
                <a href="#/" class="navbar-brand">Question Maker</a>
            </div>
        </div>
    </div>
    <div class="maincontent container-fluid" ui-view>
 
    </div>
</body>
 
</html>

ngRoute实现原理

我们知道,设置

<ahref="#div1">div1</a>

            <ahref="#div2">div2</a>

            <ahref="#div3">div3</a>

        <divid="div1">我是div1</div>

            <divid="div2">我是div2</div>

            <divid="div3">我是div3</div>

这样的锚点,a链接会在同一页面中跳转。ngRoute利用了这一特性将锚点出的文件设置为模板,在锚点被链接时,监听到url的变化,加载相应的模板文件。

入口文件app.js

有了入口页面,还得有一个js的启动入口,就是这个app.js了,在这里它只做了两件事情:

  1. 启动angular,代码只有一行:

JavaScript

var app = angular.module('QMaker', ['ui.router']);

1
var app = angular.module('QMaker', ['ui.router']);

我们拥有了一个名为app的全局模块。这里把ui.router给注入了,因为我们整个应用都用ui-router来做路由,后面会做详细介绍。

2. 把ui-router的$state和$stateParams服务挂到$rootScope上,这样我们在后面所有的模块中,都能够访问到路由参数,不必在每个地方都注入一次了。代码也是相当简单:

JavaScript

app.run(function($rootScope, $state, $stateParams) { $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; });

1
2
3
4
app.run(function($rootScope, $state, $stateParams) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
});

4.解决方案

控制器合集controllers.js

controller.js里面是所有的controller定义,由于这个项目比较小,而且反正最后都要合并,所以就都放在一个文件里了,这样可以使用链式写法app.controller(‘a’, …).controller(‘b’, …), 一口气将所有的controller都定义好。如果项目比较大,controller多,可以把controllers建为一个文件夹,然后在里面放各个controller。

controller里面就是跟业务相关的一些代码了,如试题数据的初始化,添加答案、删除选项等操作。

但是当我们需要发起ajax请求的时候,如保存试题,就不宜在controller里面直接写了,这样会造成逻辑混杂代码混乱。所有需要请求服务端的操作,我们可以抽象为一个个服务,进行“分层”,通过ng提供的service机制来做调用。

NGROUTE包含以下部分:

服务$routeProvider用来定义一个路由表,即地址栏与视图模板的映射

服务$routeParams保存了地址栏中的参数

服务$location用来实现用于获取当前url以及改变当前的url,并且存入历史记录

服务$route完成路由匹配,并且提供路由相关的属性访问及事件,如访问当前路由对应的controller

指令ngView用来在主视图中指定加载子视图的区域

$routeProvider提供了定义路由表的服务,它有两个核心方法,when(path,route)和otherwise(params)。

本文由威尼斯国际官方网站发布于奥门威尼斯网址,转载请注明出处:AngularJs前端架构

关键词: