文档章节

学习 AngularJS (五) scope

刘军兴
 刘军兴
发布于 2015/12/09 14:53
字数 1588
阅读 105
收藏 1

继续看 kityminder-editor 部分代码, 一层层进入到 undoRedo.directive.js, 以及对应的模板文件 undoRedo.html,
又看不懂里面的 angularjs 相关代码了, 怎么办?? --- 只能是回学校重新学啊.

幸好买的书到了, 《精通AngularJS》. 但为了弄懂 kityminder 就得学这么多东西, 是不是很复杂? 
万一以后领导/客户说还要改点什么, 一定会更复杂吧...?

将粗看一下部分开始章节, 期望重点了解 scope, directive 概念.

AngularJS 的 MVC 模式

MVC 太知名了, 招聘时年轻的学子们有问你们用不用 MVC 模式, 我都不知道该怎么回答. 看他们表情仿佛是若不用 MVC,
就很落伍很低级 -> 不来. 所以, 还是赶紧学一下什么是 MVC 吧!

MVC (model-view-controller), 是一种架构(architect)模式, 相当抽象. 当前有很多变种和派生 (如 MVP,
MVVM 模式), 开发者有自己对 MVC 的理解并有不同的设计架构. 导致同样的 MVC 名字有不同的架构...

AngularJS 采用注重实效的方式 -> MVW(model-view-whatever) 模式.

书上例子: hello-world 使用 ng-controller:

<div ng-controller='HelloCtrl'>
  <h1>Hello, {{name}}!</h1>
</div>

<script>
function HelloCtrl($scope) {
  $scope.name = 'angular';
}
</script>

要亲自实验一下才放心, 于是写简单网页吧, 看看到底能行不? --- 测试结果: 没通过...

换一下写法, 下面这种才能通过:

<div ng-app='demo' ng-controller='HelloCtrl'>
  <h1>Hello {{ name }}!</h1>
</div>

<script>
angular.module('demo', []) // 必须有一个 module 吗?
  .controller('HelloCtrl', ['$scope', function($scope) { // 必须注册到 module 吗?
    console.log('HelloCtrl() is called, $scope is: ', $scope);
    $scope.name = 'World';
  }]);
</script>

(这样, 看这书是不是前景堪忧啊...) 还是先继续看 scope (作用域)概念吧.

 

作用域 (scope)

AngularJS 中的 $scope 对象是模板的域模型(domain model), 也称为作用域实例 (instance).
通过为其属性赋值, 可以传递数据给模板渲染.

上面的 HelloCtrl 例子中, 输出的 $scope 如下图样子:

 

初看应是一个 Scope 类的实例, 以 $$, $ 开头的属性和方法应该是 angularjs 内部使用的. name 属性是我们添加的.
还注意到有 $id, $parent, $root 属性, 应是构成了 scope 的树结构(层次结构).

书上写向 scope 赋值, 可以传递数据给模板渲染, 那我们来做实验, 手动在 console 中输入语句为 $scope.name 赋新值,
看看能发生什么...?  --- 答案是: 没变化. 这意味着什么?

既然 $scope 对象是模板 (对应 view 吗?) 的域模型 (对应 model 吗?), ... 那么就有了 M&V of MVC 了吗?

作用域 (scope) 可以加入与模板相关的数据(data)和提供相关的功能(function). 例子, 用函数 getName() 替代
name 属性 (实验通过):

angular... .controller(..., function($scope) {
  $scope.getName = function() {
    return 'World';
  }
});
// 对应模板写作: Hello, {{ getName() }}

证明了啥? 证明 AngularJS expression 能支持调用 $scope 上的函数......

$scope 对象可以精准地控制领域模型 (domain model) 的哪些数据和操作在视图上 (view) 上是有效的.
概念上来说, AngularJS 的作用域 (scopes) 与 MVVM 模式的视图模型 (view-model) 非常相似.

控制器

控制器(controller) 的主要职责是初始化作用域 (scope) 实例 (instance).

可以 1. 属性 在 $scope; 2. 方法 于 $scope, 一般是 UI 相关的行为. 

在初始化 scope instance (View-Model of MVVM) 时, controller 与 ng-init 可以做同样的工作.

实验: 我们即有 ng-init 又有 controller, 会发生什么?

<div ng-controller='HelloCtrl' ng-init='name = "Warlord"' >
  Hello {{ name }}!
</div>
// controller 部分中设置 $scope.name = 'World', 其它不变.

结果显示 Hello Warlord! 这说明了什么?

既然 controller 能用, 则尽量将代码放到 controller 中, 而不是将 js 混在 html 模板中.
书上说控制器就是一个 js 函数, 不需要扩展任何 angularjs 特定的类, 不需要调用特定 angularjs api ...
但我单独写 controller 函数却无法通过实验, 也许我还不太熟悉 angular, 又或者旧版本可以写函数?

模型

AngularJS 的模型 (model) 实际上就是普通的 js 对象. 不需要去扩展任何 angularjs 底层类.

可以使用任何 js 类或对象, 属性也不仅限于原始值 (primitive values).

AngularJS 没有侵略性, 它让模型对象远离框架特定的代码. (请一下此设计)

深入作用域

每个 $scope 都是 Scope 类的实例. (我们上面观察 $scope 对象时可注意到这一点)

作用域层级

问题: controller 函数的参数 $scope 从何而来?
答案是: ng-controller 指令使用 scope 对象的 $new(isolate, parent) 方法创建新的作用域, 传递给 controller 函数.
   angularjs 在新应用启动时自动创建 $rootScope 作为其他所有 scope 的父 scope. (?是否 ng-app 启动一个新应用)

ng-controller 指令是作用域创建 (scope-creating) 指令. 每当 DOM 树中遇到此类指令, 都会创建 Scope 类的
新实例 $scope. 新的 $scope 拥有 $parent 属性, 指向它的父作用域.

由于 DOM 是树结构, 附加在 DOM 上的创建 scope 的指令创建出 scope 树也是不奇怪的.

如重复器(repeater)指令 ng-repeat 会创建子作用域, 看例子:

<div ng-controller='HelloCtrl'>
  <ul>
    <li ng-repeat='i in [2,3,5,7]'>Number is {{ i }}</li>
  </ul>
</div>

页面显示出 2,3,5,7 在一个 ul 中. 查看 html 发现有多个 DOM 元素 class 中含有 ng-scope:

 

按照书上指引, 找到一个 Firefox 的扩展 AngScope - AngularJS 作用域查看器 for Firebug, 在 DOM 元素上右键
点击, 出现菜单 'Inspect Angular Scope', 然后可以查看该元素所属作用域. (启发: 也许还有别的 angular 插件...)
(Chrome 类似扩展为 Batarang)

经过查看会发现一些惊人的事实, body 上的 scope.$id = 1, .parent = null, 这应该是为 demo ng-app 创建的根
作用域. div HelloCtrl ng-controller 的 scope.$id = 2, .parent = scope#1;
每个被重复的 li 都有自己的 scope, $id 对应为 3,4,5,6, 其 .parent = scope#2.
也即每个 li 都创建了一个新的 scope...

而且这些 scope 的 __proto__ 属性也比较怪, 似乎就是其 $parent 的值, 也是一层一层向上直到 null.
这种技术似乎很少看到. 也许我应该多花点时间看看其它 js 库? (可是还有事情要忙, 没时间怎么办?) 

用 Chrome + 扩展 Batarang 查看似乎更方便:

 

从而这里就能明白, 为什么在一个 repeater 里面可以访问到 $index, $first, $last, $even, $odd 等属性的原因了.

(休息一下, 下篇接着学...)

© 著作权归作者所有

共有 人打赏支持
刘军兴
粉丝 56
博文 187
码字总数 231243
作品 0
昌平
私信 提问
AngularJs学习笔记--expression

一、Angular表达式 vs. Js 表达式   这很容易让人将angular视图表达式联想为javascript表达式,但这并不完全正确,因为angular不是通过javascript的eval()对表达式进行求值。你可以将angul...

武文海
2015/02/06
0
0
AngularJS - Top 6 Concepts that Developers Loved

This article represents top 6 popular AngularJS topics that has been used most by the AngularJS developer community to date. The inference is derived based on number of tagged d......

perfectspr
2014/12/03
0
0
《AngularJS学习整理》系列分享专栏

《AngularJS学习整理》系列分享专栏 《AngularJS学习整理》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201748.html 文章 教你用AngularJS框架一行JS代码实现...

开元中国2015
11/09
0
0
Angular.js 相关记录

AngularJS作用域文档:http://docs.angularjs.org/api/ng.$rootScope.Scope ng-view 指令的角色是为当前路由把对应的视图模板载入到布局模板中。 AngularJS内置过滤器:http://code.angular...

彭博
2014/04/25
0
2
angular 调试时出现$http.get(...).success is not a function错误

我是angular 初学者,在调试时出现$http.get(...).success is not a function错误,我在网上找了一下,没有得到解决,求一下大神,帮我看一下出现了什么问题谢谢! 具体错误:TypeError: $h...

宸紫懿
2016/12/29
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

PHP生成CSV之内部换行

当我们使用PHP将采集到的文件内容保存到csv文件时,往往需要将采集内容进行二次过滤处理才能得到需要的内容。比如网页中的换行符,空格符等等。 对于空格等处理起来都比较简单,这里我们单独...

豆花饭烧土豆
14分钟前
0
0
使用 mjml 生成 thymeleaf 邮件框架模板

发邮件算是系统开发的一个基本需求了,不过搞邮件模板实在是件恶心事,估计搞过的同仁都有体会。 得支持多种客户端 支持响应式 疼彻心扉的 outlook 多数客户端只支持 inline 形式的 css 布局...

郁也风
18分钟前
2
0
让哲学照亮我们的人生——读《医务工作者需要学点哲学》有感2600字

让哲学照亮我们的人生——读《医务工作者需要学点哲学》有感2600字: 作者:孙冬梅;以前读韩国前总统朴槿惠的著作《绝望锻炼了我》时,里面有一句话令我印象深刻,她说“在我最困难的时期,...

原创小博客
今天
3
0
JAVA-四元数类

public class Quaternion { private final double x0, x1, x2, x3; // 四元数构造函数 public Quaternion(double x0, double x1, double x2, double x3) { this.x0 = ......

Pulsar-V
今天
17
0
Xshell利用Xftp传输文件,使用pure-ftpd搭建ftp服务

Xftp传输文件 如果已经通过Xshell登录到服务器,此时可以使用快捷键ctrl+alt+f 打开Xftp并展示Xshell当前的目录,之后直接拖拽传输文件即可。 pure-ftpd搭建ftp服务 pure-ftpd要比vsftp简单,...

野雪球
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部