发表于: 2021-11-21 23:08:51
0 924
基础ng属性指令
布尔属性
布尔属性代表一个true
或false
值。当这个属性出现时,这个属性的值就是true
(无论实际定义的值是什么)。如果未出现,这个属性的值就是false
。
当在AngularJS中使用动态数据绑定时,不能简单地将这个属性值设置为ture
或false
,因为 根据标准定义只有当这个属性不出现时,它的值才为false
。因此AngularJS提供了一组带有ng-
前缀版本的布尔属性,通过运算表达式的值来决定在目标元素上是插入还是移除对应的属性。
1.ng-disabled
使用ng-disabled
可以把disabled
属性绑定到以下表单输入字段上:
<input> (text、checkbox、radio、number、url、email、submit);<textarea>;<select>;<button>。
当写普通的HTML输入字段时,如果在元素标签上出现了disabled
属性就会禁用这个输入字段。通过ng-disabled
可以对是否出现属性进行绑定。
<input type="text" ng-model="someProperty" placeholder="TypetoEnable"><button ng-model="button" ng-disabled="!someProperty">AButton</button>
在下面的例子,文本字段会被禁用五秒,直到在$timeout
中将isDisabled
属性设置为true
。
<textarea ng-disabled="isDisabled">Wait5seconds</textarea>angular.module('myApp', [])
.run(function($rootScope, $timeout) {
$rootScope.isDisabled = true;
$timeout(function() {
$rootScope.isDisabled = false;
}, 5000);
});
2.ng-readonly
通过ng-readonly
可以将某个返回真或假的表达式同是否出现readonly
属性进行绑定。
Type here to make sibling readonly:
<input type="text" ng-model="someProperty"><br/>
<input type="text" ng-readonly="someProperty" value="Some text here"/>
3.ng-checked
通过ng-checked
将某个表达式同是否出现checked
属性进行绑定。
//默认会把复选框勾选<label>someProperty={{someProperty}}</label><input type="checkbox" ng-checked="someProperty" ng-init="someProperty=true" ng-model="someProperty">
4.ng-selected
ng-selected
可以对是否出现option
标签的selected
属性进行绑定。
<label>Select Two Fish:</label><input type="checkbox" ng-model="isTwoFish"><br/><select>
<option>One Fish</option>
<option ng-selected="isTwoFish">Two Fish</option></select>
类布尔属性
ng-href
、ng-src
等属性虽然不是标准的HTML布尔属性,但是由于行为相似,所以在AngularJS源码内部是和布尔属性同等对待的。
1.ng-href
当使用当前作用域中的属性动态创建URL时,应该用ng-href
代替href
。
这里的潜在问题是当用户点击一个由插值动态生成的链接时,如果插值尚未生效,将会跳转到错误的页面(通常是404)。这时,如果使用ng-href
,AngularJS会等到插值生效后再执行点击链接的行为。
<!-- 当href包含一个{{expression}}时总是使用ng-href--><a ng-href="{{ myHref }}">I'm feeling lucky, when I load</a><!-- 用户单击之前,href不会加载 --><a href="{{myHref}}">I'm feeling 404</a>
将插值生效的事件延迟两秒,来观察实际的行为。
angular.module('myApp',[]).run(function($rootScope,$timeout) {
$timeout(function() {
$rootScope.myHref = 'http://google.com';
}, 2000);});
2.ng-src
AngularJS会告诉浏览器在ng-src
对应的表达式生效之前不要加载图像。
<h1>WrongWay</h1><img src="{{imgSrc}}"/><h1>Rightway</h1><img ng-src="{{imgSrc}}"/>angular.module('myApp',[]).run(function($rootScope,$timeout) {
$timeout(function() {
$rootScope.imgSrc='https://www.google.com/images/srpr/logo11w.png';
}, 2000);});
在指令中使用子作用域
ng-app
和ng-controller
是特殊的指令,因为它们会修改嵌套在它们内部的指令的作用域。ng-app
为AngularJS应用创建$rootScope
,ng-controller
则会以$rootScope
或另外一个ng-controller
的作用域为原型创建新的子作用域。
1.ng-app
任何具有ng-app
属性的DOM元素将被标记为$rootScope
的起始点。$rootScope
是作用域链的起始点,任何嵌套在ng-app
内的指令都会继承它。在JS代码中通过run
方法来访问$rootScope
。
<html ng-app="myApp">
<body>
{{ someProperty }}
<button ng-click="someAction()"></button>
</body></html>angular.module('myApp',[]).run(function($rootScope) {
$rootScope.someProperty='hello computer';
$rootScope.someAction=function() {
$rootScope.someProperty='hello human';
};});
2.ng-controller
内置指令ng-controller
的作用是为嵌套在其中的指令创建一个子作用域,避免将所有操作和模型都定义在$rootScope
上。用这个指令可以在一个DOM元素上放置控制器。ng-controller
接受一个参数expression
,这个参数是必需的。expression
参数是一个AngularJS表达式。
子$scope
只是一个JS对象,其中含有从父级$scope
中通过原型继承得到的方法和属性,包括应用的$rootScope
。嵌套在ng-controller
中的指令有访问新子$scope
的权限。$scope
对象的职责是承载DOM中指令所共享的操作和模型。操作指的是$scope
上的标准JS方法。模型指的是$scope
上保存的包含瞬时状态数据的JS对象。持久化状态的数据应该保存到服务中,服务的作用是处理模型的持久化。
<div ng-controller="SomeController">
{{ someModel.someProperty }}
<button ng-click="someAction()">Communicate</button></div>angular.module('myApp',[]).controller('SomeController',function($scope) {
//创建模型
$scope.someModel = {
// 添加属性
someProperty: 'hello computer'
}
// 设置$scope自身的操作
$scope.someAction = function() {
$scope.someModel.someProperty = 'hello human';
};});
在这个例子中,首先,我们使用了$rootScope
的子作用域,它提供了一个干净的对象供我们操作。使用子作用域意味着其上的数据模型和操作在应用的其他地方是无法访问的,只能被这个作用域内的指令及其子作用域访问。其次,显式声明了数据模型。
<div ng-controller="SomeController">
{{ someBareValue }}
<button ng-click="someAction()">Communicate to child</button>
<div ng-controller="ChildController">
{{ someBareValue }}
<button ng-click="childAction()">Communicate to parent</button>
</div></div>angular.module('myApp',[]).controller('SomeController',function($scope) {
// 反模式,裸值
$scope.someBareValue = 'hello computer';
// 设置 $scope 本身的操作,这样没问题
$scope.someAction = function() {
//在SomeController和ChildController中设置{{someBareValue}}
$scope.someBareValue = 'hello human, from parent';
};}).controller('ChildController', function($scope) {
$scope.childAction = function() {
// 在ChildController中设置{{ someBareValue }}
$scope.someBareValue = 'hello human, from child';
};});
这个例子中,在已有的控制器中嵌套了第二个控制器,并且没有设置模型对象的属性。由于原型继承的关系,修改父级对象中的someBareValue
会同时修改子对象中的值,但反之则不行。这个例子充分说明了子控制器是复制而非引用someBareValue
。
如果将模型对象的某个属性设置为字符串,它会通过引用进行共享,因此在子$scope
中修改属性也会修改父$scope
中的这个属性。下面的例子展示了正确的做法:
<div ng-controller="SomeController">
{{ someModel.someValue }}
<button ng-click="someAction()">Communicate to child</button>
<div ng-controller="ChildController">
{{ someModel.someValue }}
<button ng-click="childAction()">Communicate to parent</button>
</div></div>angular.module('myApp', [])
.controller('SomeController', function($scope) {
// 最佳实践,永远使用一个模式
$scope.someModel = {
someValue: 'hello computer'
}
$scope.someAction = function() {
$scope.someModel.someValue = 'hello human, from parent';
};
})
.controller('ChildController', function($scope) {
$scope.childAction = function() {
$scope.someModel.someValue = 'hello human, from child';
};
});
无论点击哪个按钮,值都会进行同步修改。
注意,虽然这个特性是使用ng-controller
时最重要的特性之一,但在使用任何会创建子作用域的指令时,如果将指令定义中的scope
设置为true
,这个特性也会带来负面影响。下面的内置指令都有同样的特性:ng-include
、ng-switch
、ng-repeat
、ng-view
、ng-controller
、ng-if
。
3.ng-include
使用ng-include
可以加载、编译并包含外部HTML片段到当前的应用中。模板的URL被限制在与应用文档相同的域和协议下,可以通过白名单或包装成被信任的值来突破限制。更进一步,需要考虑跨域资源共享(CORS)和同源规则来确保模板可以在任何浏览器中正常加载。
使用ng-include
时AngularJS会自动创建一个子作用域。如果你想使用某个特定的作用域,例如ControllerA
的作用域,必须在同一个DOM元素上添加ng-controller="ControllerA"
指令,这样当模板加载完成后,不会像往常一样从外部作用域继承并创建一个新的子作用域。
<div ng-include="other.html" ng-controller="MyController" ng-init="name='World'">
Hello {{name}}</div><!--ng-include等价写法--><div ng-include src="other.html">
Hello {{name}}</div>
4.ng-switch
这个指令和ng-switch-when
及on="propertyName"
一起使用,可以在propertyName
发生变化时渲染不同指令到视图中。
<input type="text" ng-model="person.name"/><div ng-switch on="person.name">
<p ng-switch-default>And the winner is</p>
<h1 ng-switch-when="Ari">{{person.name}}</h1></div>
在switch
被调用之前用ng-switch-default
来输出默认值。
5.ng-view
ng-view
指令用来设置将被路由管理和放置在HTML中的视图的位置。
6.ng-if
使用ng-if
指令可以完全根据表达式的值在DOM中生成或移除一个元素。如果赋值给ng-if
的表达式的值是false
,那对应的元素将会从DOM中移除,否则对应元素的一个克隆将被重新插入DOM中。ng-if
同ng-show
和ng-hide
指令最本质的区别是,它不是通过CSS显示或隐藏DOM节点,而是真正生成或移除节点。当一个元素被ng-if
从DOM中移除,同它关联的作用域也会被销毁。而且当它重新加入DOM中时,会通过原型继承从它的父作用域生成一个新的作用域。ngIf
重新创建元素时用的是它们编译后的状态。如果ng-if
内部的代码加载之后被jQuery修改过(例如用.addClass
),那么当ng-if
的表达式值为false
时,这个DOM元素会被移除,表达式再次成为true
时这个元素及其内部的子元素会被重新插入DOM,此时这些元素的状态会是它们的原始状态,而不是它们上次被移除时的状态。也就是说无论用jQuery的.addClass
添加了什么类都不会存在了。
<div ng-if="2+2===4">
Hi, I do exist</div>
7.ng-repeat
ng-repeat
用来遍历一个集合或为集合中的每个元素生成一个模板实例。集合中的每个元素都会被赋予自己的模板和作用域。同时每个模板实例的作用域中都会暴露一些特殊的属性。
- $index:遍历的进度(0...
length-1
) - $first:当元素是遍历的第一个时值为
true
- $middle:当元素处于第一个和最后元素之间时值为
true
- $last:当元素是遍历的最后一个时值为
true
- $even:当
$index
值是偶数时值为true
- $odd:当
$index
值是奇数时值为true
评论