文档章节

学习 AngularJS (五) scope

刘军兴
 刘军兴
发布于 2015/12/09 14:53
字数 1588
阅读 97
收藏 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 等属性的原因了.

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

© 著作权归作者所有

共有 人打赏支持
刘军兴
粉丝 54
博文 184
码字总数 226359
作品 0
昌平
AngularJs学习笔记--expression

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

武文海
2015/02/06
0
0
Angular.js 相关记录

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

彭博
2014/04/25
0
2
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
angular js 自学笔记(一)

js中的mvc mvc设计模式,简单说来是将复杂的代码设计规范化,把应用的输入,处理,输出分开,M是指数据模型,V是指用户界面,C则是控制器。像我刚接触的SSH框架中,例如struts,就是利用mvc的...

烽穹寒渊
2015/03/09
0
0
Angular 中得 scope 作用域梳理

$scope 的使用贯穿整个 Angular App 应用,它与数据模型相关联,同时也是表达式执行的上下文.有了 $scope 就在视图和控制器之间建立了一个通道,基于作用域视图在修改数据时会立刻更新 $scope,同...

顽Shi
2014/09/21
0
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

人生苦短:Python里的17个“超赞操作

人生苦短,我选Python”。那么,你真的掌握了Python吗? 1. 交换变量 有时候,当我们要交换两个变量的值时,一种常规的方法是创建一个临时变量,然后用它来进行交换。比如: # 输入 a = 5 b ...

糖宝lsh
40分钟前
4
0
咕泡-spring中常用设计模式概述

设计模式就是经验之谈,供后人借鉴,解决一些具有代表性的问题 设计模式来源于生活,反过来帮助我们更好生活 设计模式提升代码的可读性、可扩展性、维护成本、复杂业务问题 千万不要死记硬背...

职业搬砖20年
今天
2
0
day59-20180817-流利阅读笔记-待学习

假·照骗,真·社交焦虑 雪梨 2018-08-17 1.今日导读 发朋友圈之前,不少人为了展现更美好的生活状态会对照片加以“微调”,或是加个滤镜显得逼格更高,或是磨个皮瘦个脸拉个大长腿。现在,国...

aibinxiao
今天
19
0
OSChina 周五乱弹 —— 姑娘在这个节日里表白你接受么?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @Sharon啊:完全被这个小姐姐圈粉了,学两首她的歌去哈哈 分享王贰浪的单曲《往后余生(翻自 马良)》 《往后余生(翻自 马良)》- 王贰浪 手...

小小编辑
今天
949
16
为什么HashMap要自己实现writeObject和readObject方法?

为什么HashMap要自己实现writeObject和readObject方法? 如果你有仔细阅读过HashMap的源码,那么你一定注意过一个问题:HashMap中有两个私有方法。 private void writeObject(java.io.Objec...

DemonsI
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部