AngularJS指令
HTML5 允许扩展的(自制的)属性,以 data- 开头。
AngularJS 属性以 ng- 开头,但是您可以使用 data-ng- 来让网页对 HTML5 有效。
二者效果相同。
ng-app:
标记在一个AngularJS的作用范围,标记范围尽可能小,解析快。可以在同一个页面创建多个ng-app节点,但不推荐。angular找到第一个ng-app过后就不会再找。
<div ng-app="myApp1" ng-controller="App1Controller">
<input type="button" value="按钮1" ng-click="do1()">
</div>
<div ng-app="myApp2" ng-controller="App2Controller">
<input type="button" value="按钮2" ng-click="do2()">
</div>
需要手动的让第二个div被myApp2管理angular.bootstrap(document.querySelector('[ng-app="myApp2"]'),['myApp2']);
,第一个参数传哪个DOM元素,可以用document.querySelector
来选择,第二个参选传哪个处理模块
var myApp2 = angular.module('myApp2', []);
myApp2.controller('App2Controller', ['$scope', function($scope) {
$scope.do2 = function() {
console.log(22222);
};
如有需要两个模块管理,一般定义好myApp1和myApp2后,通过angular.module('myApp', ['myApp1', 'myApp2']);
组合成myApp,然后在上一级中指定myApp<body ng-app="myApp">
ng-bind:
ng-bind 将作用域中的值绑定到innerHTML上,效果比表达式更友好,没有闪过表达式原型的情况。ng-bind指令在绑定的值包含HTML时会转义,为了安全(跨站脚本攻击),如下代码会输出<h1>shit</h1>
<body ng-app ng-init="username='<h1>shit</h1>'">
<strong ng-bind="username"></strong>
若要输出不转义的语义HTML,可以用ng-bind-html指令<strong ng-bind-html="username"></strong>
除此之外,需要安装angular-sanitize,可以用npm install angular-sanitize --save
来安装,在页面中<script src="node_modules/angular-sanitize/angular-sanitize.js"></script>
引入,使用自定义的模块才可以依赖别的包里面定义模块,angular定义的默认模块没有依赖任何angular.module('myApp', ['ngSanitize']);
跨站脚本攻击示意如下,在文章评论处插入跨站脚本,服务器会存储下来,后面用户在加载页面时,会执行这段script脚本(参考www.wooyun.org)
![](https://img.haomeiwen.com/i5315044/a9917cfd58726a44.png)
ng-repeat:
对初始的data数组赋值可以用下面方法
$scope.data = [];
for (var i = 1; i < 10; i++) {
$scope.data[$scope.data.length] = {
id: i,
name: '赵小黑的小' + i,
age: 20 + i
};
}
ng-repeat主要应用于数组,如下遍历数组中每一个元素,分别创建li。item in data 循环取出data数组中的每一行为item
<ul ng-controller="ListController">
<li ng-repeat="item in data" data-id="{{item.id}}">
<span>{{$first?'开始':''}}</span>
<strong>{{item.name}}</strong>
<span>{{item.age}}</span>
<span>{{$last?'没有了':''}}</span>
</li>
</ul>
可以在scope中查看每个li的属性,自带了一些是否首尾项奇偶等属性
![](https://img.haomeiwen.com/i5315044/170fd6dc0aeee68a.png)
ng-class
定义好style后,通过<li ng-repeat="item in xiaoheishenghuo" ng-class="{red:$even,green:$odd}" data-id="{{item.id}}">
来使隔行换色。red:$even
表示当even属性返回为true,会添加red这个class
<style>
.red {color: red; }
.green {color: green; }
</style>
select下拉框选项,首先在model中建立style,当选中red时,给style赋值red通过ng-class="{red:style=='red', green:style=='green'}
来根据style的值决定用哪个class
<body ng-app>
<select ng-model="style">
<option value="red">红色</option>
<option value="green">绿色</option>
</select>
<!-- <div id="box" ng-class="style"></div> -->
<div id="box" ng-class="{red:style=='red', green:style=='green'}"></div>
<script src="bower_components/angular/angular.js"></script>
</body>
给数组赋值有重名$scope.students = ['胡shit', '赵四', '网商务', '李三', '李三', '李三'];
,使用<li ng-repeat="name in students">{{name}}</li>
会报错,应该加上index name in students track by $index
使用startWith来判断是填入的姓时是红色,刚开始时,lastname为undfined,下面的都不是以undfined开头,但是当填入数据后再删除,lastname为空字符串,所有的都是以空字符开头,就都是红色。可以加上{red:lastname!=''&&name.startsWith(lastname)}
来加上非空判断
<input type="text" ng-model="lastname">
<ul ng-controller="ListController">
<li ng-repeat="name in students track by $index" ng-class="{red:name.startsWith(lastname)}">{{name}}</li>
</ul>
Loading用法<body ng-controller="ListController" ng-class="{loading:loading}">
加入loading,在代码中先设为true,3s后设为false移除loading面板
angular.module('myApp', [])
.controller('ListController', ['$scope', '$timeout', function($scope, $timeout) {
$scope.loading = true;
$timeout(function() {
$scope.loading = false;
}, 3000);
}]);
样式代码如下
<style>
body.loading > .tips {
display: block;
}
.tips {
display: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(100, 100, 100, .5);
font-size: 40px;
line-height: 100vh;
text-align: center;
}
</style>
其他指令
show / hide
ng-show 决定是否显示 ng-hide 是否隐藏 ng-if 是否存在DOM元素
ng-show=false相当于添加了ng-hide的style class,里面样式display: none;
配合上面例子的loading变量,ng-show="loading"
或ng-hide="!loading"
ng-if中的表达式为false时,这个元素会被remove掉
src / href
ng-link/ng-src指令用于解决当链接类型的数据绑定时造成的加载BUG,如下若使用src="{{imgUrl}}"
,Angular没加载完会先直接请求这个地址,此时地址无效,控制台会有请求错误,等Angular加载后再请求到实际地址。图片将从一个无效图片转为实际图片。使用ng-cloak可以解决闪过的无效图片问题,但控制台还是会有错误。因此Angular封装了ng-src和ng-href
<body ng-app ng-init="imgUrl='22.png'" ng-cloak>
![]({{imgUrl}})
<a ng-href="{{imgUrl}}">跳转到图片</a>
</body>
ng-switch
根据当前的值显示或隐藏对应部分,配合 ng-switch-when, ng-switch-default 使用
我喜欢的网站
<select ng-model="myVar">
<option value="google">www.google.com</option>
<option value="taobao">www.taobao.com</option>
</select>
<hr>
<div ng-switch="myVar">
<div ng-switch-when="google">
<h1>Google</h1>
<p>欢迎访问Google</p>
</div>
<div ng-switch-when="taobao">
<h1>淘宝</h1>
<p>欢迎访问淘宝</p>
</div>
<div ng-switch-default>
<h1>切换</h1>
<p>选择不同选项显示对应的值。</p>
</div>
</div>
ng-checked
ng-mode绑定到checked,ng-checked 和 ng-selected也绑定,但不会双向绑定。 只会做数据到视图的同步,不会做视图到数据的同步
<p>
<input type="checkbox" ng-model="checked">全选/取消全选</p>
<ul>
<!-- ng-checked 和 ng-selected 只会做数据到视图的同步,不会做视图到数据的同步 -->
<li>选项01
<input type="checkbox" ng-checked="checked">
</li>
<li>选项02
<input type="checkbox" ng-checked="checked">
</li>
</ul>
自定义指令
定义指令的名字,应该使用驼峰命名法。自定义指令与定义控制器类似,第一个参数指令名,第二个是数组。<itcast-button></itcast-button>加载组件。把重复的封装好,让我们使用更方便。例如自定义指令实现Bootstrap的Button样式
demoApp.directive('itcastButton', [function() {
// 该函数应该返回一个指令对象
return {
template:'<input type="button" value="itcast" class="btn btn-lg btn-primary btn-block" />'
};
}]);
页面上<btn primary="true" lg block>itcast</btn>
自定义属性,@会取标签上对应的属性值,primary="true"会取消样式
demoApp.directive('btn', [function() {
return{
scope:{
primary:'@',
lg:'@',
block:'@',
},
template:'<button class="btn {{primary==\'true\'?\'btn-primary\':\'\'}}">button</button>'
}
}]);
<btn>itcast</btn>
我们要实现将btn元素替换成bootstrap的button样式,首先要使用ng-transclude指令,通过replace: true 替换指令在HTML中绑定的<btn>元素
demoApp.directive('btn', [function() {
return {
// 指令对象的transclude必须设置为true才可以在模版中使用ng-transclude指令
transclude: true,
replace: true, // 替换指令在HTML中绑定的元素
template: '<button class="btn btn-primary btn-lg" ng-transclude></button>'
};
}]);
参考
https://angular-ui.github.io/bootstrap/
https://material.angularjs.org/latest/demo/bottomSheet