我是AngularJS的新手,我正在学习一门课程。我对一个展示如何使用隔离范围概念的示例有一些疑问。
因此,提供的示例是一个包含app.js文件的单页应用程序,该文件包含所有应用程序逻辑:
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/main.html',
controller: 'mainController'
})
.when('/second', {
templateUrl: 'pages/second.html',
controller: 'secondController'
})
.when('/second/:num', {
templateUrl: 'pages/second.html',
controller: 'secondController'
})
});
myApp.controller('mainController', ['$scope', '$log', function($scope, $log) {
$scope.person = {
name: 'John Doe',
address: '555 Main St., New York, NY 11111'
}
}]);
myApp.controller('secondController', ['$scope', '$log', '$routeParams', function($scope, $log, $routeParams) {
}]);
/* Declare a directive named "searchResult" */
myApp.directive("searchResult", function() {
return {
restrict: 'AECM', // This represent the ways to declare the directive into my code
templateUrl: 'directives/searchresult.html', // This is the template page that implement the directive
replace: true, // This specify that the directive in the main HTML code is replaced by the template code
/* This isolate the directive scope (the model of the directive) from its parent scope (the controller that handle the page in which
the directive is used). Because I can't directly use the person.name and the person.address property declared in the parent scope I
specify that I use the person-name and the person-address passed as custom attribute of the search-result directive where it is used (in the main.html)
*/
scope: {
personName: "@",
personAddress: "@"
}
}
});
这是main.html页面,该页面使用搜索结果指令:
搜索
<h3>Search Results</h3>
<div class="list-group">
<search-result person-name="{{ person.name }}" person-address="{{ person.address }}"></search-result>
</div>
这是searchResult.html的代码,它是我指令的模板:
<a href="#" class="list-group-item">
<h4 class="list-group-item-heading">{{ personName }}</h4>
<p class="list-group-item-text">
{{ personAddress }}
</p>
</a>
因此,根据我的理解(但如果我做了错误的断言,请纠正我),范围隔离以以下方式工作:
为了避免这个问题,我可以通过其父作用域(例如主页面的控制器)来隔离子指令的作用域。
要做到这一点,我只需在指令JavaScript解密中插入scopeJSON对象:
scope: {
.............
.............
.............
}
但现在,根据我的指令,我不能再直接访问父作用域(控制器作用域)中声明的名称和地址属性。
因此,如果我必须使用这些值,我会以这种方式声明隔离的指令范围对象:
scope: {
personName: "@",
personAddress: "@"
}
这意味着personName属性具有搜索结果HTML声明中声明的人名的text值(以及personAddress中的dame内容,实际上在我的main文件中我有
<search-result person-name="{{ person.name }}" person-address="{{ person.address }}"></search-result>
从这里我可以直接访问个人名称和人员地址,因为我在这里使用控制器范围(父范围)
因此,现在在我的JavaScript指令中,我将这些值获取到隔离子作用域对象的personName和personAddress属性中,并在指令模板中访问这些属性,方法如下:
<a href="#" class="list-group-item">
<h4 class="list-group-item-heading">{{ personName }}</h4>
<p class="list-group-item-text">
{{ personAddress }}
</p>
</a>
我的推理正确吗?还是我遗漏了什么?
您的理解是正确的。隔离作用域与普通作用域的不同之处在于,它在原型上不继承其父作用域。这在创建可重用组件时很有用,因为这些组件不应该意外读取或修改父作用域中的数据,而且它也不与父作用域强耦合。
要扩展通过隔离范围可用的内容,有三个选项可供选择(来自文档):
@或@attr-将本地作用域属性绑定到DOM的值属性结果总是一个字符串,因为DOM属性是字符串。如果未指定属性名称,则属性名称为假定与本地名称相同。给定作用域的小部件定义:{localName:"@myAttr"},那么小部件作用域属性localName将反映插值hello{{name}}的值。随着name属性的更改小部件作用域上的localName属性。名称是从父作用域(不是组件作用域)。
=或=attr-在本地作用域属性和通过值定义的名称的父作用域属性之间设置双向绑定attr属性的。如果未指定属性名称,则属性假定名称与本地名称相同。给定和小部件范围定义:{localModel:"=myAttr"},则小部件作用域属性localModel将在父作用域上反映parentModel的值。对的任何更改parentModel将反映在localModel中localModel将反映在parentModel中。如果父作用域属性不存在,它将抛出NON_ASSIGNABLE_MODEL_EXPRESSION例外使用=可以避免这种行为?或=?attr以便将属性标记为可选。如果你想浅看更改(即$watchCollection而不是$watch),您可以使用=*或=attr(如果属性是可选的,则=?或=*?attr)。
&或者&attr-提供了一种在父作用域。如果未指定属性名称,则属性名称假定与本地名称相同。给定和小部件范围定义:{localFn:'&myAttr'},则隔离作用域属性localFn将指向count=count+value表达式的函数包装器。经常希望通过表达式传递来自隔离作用域的数据对于父作用域,可以通过传递local变量名和值到表达式包装器fn中。例如如果表达式是increment(amount),那么我们可以指定amount通过将localFn调用为localFn({amount:22})。
这是正确的。在指令中使用孤立的作用域可以使其在新的上下文中可用,而不会污染其父作用域。
@属性字符串绑定=双向模型绑定&回调方法绑定
更深入地理解指令的范围
在此处输入链接描述
$scope和$rootscope混淆
请让我知道这是否有助于