-
Notifications
You must be signed in to change notification settings - Fork 0
angularjs笔记
参考:https://www.cnblogs.com/jcomet/p/4350304.html
在angular1.5的版本之前,都是以directive作为组件化的形式,而directive本身是一个指令,而并非是一个组件,所以它并不能很好的承担组件这一个职责,所以google在angular1.5的版本中推出了component组件,用于承担应用之中组件化开发的重担。
在项目中一些指令是需要共用的,我们可以使用一个专门的模块来编写这些指令,然后在需要的模块里引用即可。
如:定义一个metricZoomDirective.js文件,代码如下:
(function(_angular){
if(!_angular){
return;
}
_angular.module("metricZoomDirective",[]).directive("singleMetricZoom",function(){
return {
restrict:"EA",
//replace:true,
templateUrl:"../wxapp/template/singleMetricComponent.html",
controller:function($scope,$element,$attrs,$transclude,$scope, $rootScope,$timeout,$stateParams){}
}
});
})(window.angular);在引用该模块,如var app = angular.module('myApp', ['ui.router', 'ngSanitize', 'ui.select', "highcharts-ng","metricZoomDirective"]);这样就可以使用该指令了。
在项目中遇到中文变乱码的问题。
问题出现的代码如下(其实最开始我也是想用$http.post这样来做的,但是发现这样不知道怎么传递请求参数,所以就使用了下面的方法。):
$http({
url:getUrl("addAvailableRateReport"),
method:"POST",
params:$scope.addReport
}).success(function(rs){
$scope.isCreate=false;
getRateList();
});出现这样的问题,但是在PC上没有这样问题。认为是$http这个的请求问题,于是用jquery的ajax做了一次请求发现是不会出现乱码的。但是肯定用angular是可以的。
改用下面代码就不会出现乱码了:
$http.post(getUrl("addAvailableRateReport"),$scope.addReport).success(function(rs){
$scope.isCreate=false;
getRateList();
});注意使用$http.post需要设置头部Content-Type,不然会报错Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.还需要对参数的传入做分解,否则会没有参数的,会作为一段字符串。
。所以需要如下设置:
app.config(['$stateProvider', '$urlRouterProvider','$httpProvider', function ($stateProvider, $urlRouterProvider,$httpProvider){
//$http.post请求是对参数的分解,要不然参数会带不过去
$httpProvider.defaults.transformRequest = function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
};
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
}]);这样就不会有问题了。可以参考:https://www.cnblogs.com/wolf-sun/p/6878868.html
指令基础知识详解参考:http://www.jb51.net/article/83051.htm
link:function link(scope, iElement, iAttrs, controller) { ... }
链接函数负责注册DOM事件和更新DOM。它是在模板被克隆之后执行的,它也是大部分指令逻辑代码编写的地方。
scope - 指令需要监听的作用域。
iElement - instance element - 指令所在的元素。只有在postLink函数中对元素的子元素进行操作才是安全的,因为那时它们才已经全部链接好。
iAttrs - instance attributes - 实例属性,一个标准化的、所有声明在当前元素上的属性列表,这些属性在所有链接函数间是共享的。
controller - 控制器实例,也就是当前指令通过require请求的指令direct2内部的controller。比如:direct2指令中的controller:function()
{this.addStrength = function(){}},那么,在当前指令的link函数中,你就可以通过controller.addStrength进行调用了。
Pre-linking function 在子元素被链接前执行。不能用来进行DOM的变形,以防链接函数找不到正确的元素来链接。
Post-linking function 所有元素都被链接后执行
ng-bind-html和ng-bind从字面意就可以看出来,前者可以针对html的字符串,让浏览器解析,而后者只能是字符串,浏览器是直接显示的。
还有往往下拉框显示,需要对象的多个属性值的组合,使用例子如下:
<ui-select-choices repeat="subSystem in subSystems | propsFilter:{subSystemName:$select.search,subSystemId:$select.search}">
<div ng-bind-html="subSystem.subSystemName+'('+subSystem.subSystemId+')'|highlight:$select.search"style="display:inline-block;"></div>
</ui-select-choices> ui-select的使用可以参考:https://github.com/angular-ui/ui-select/wiki/ui-select
例如:我不想出现搜索框的,可以在标签里加search-enabled="false"。示例代码:
<ui-select ng-model="sort.selected" theme="select2" search-enabled="false" on-select="selectSort()">
<ui-select-match placeholder="请选择">
{{sort.selected.name}}
<i class="glyphicon glyphicon-menu-down wing"></i>
</ui-select-match>
<ui-select-choices repeat="sortItem in sortList">
{{sortItem.name}}
</ui-select-choices>
</ui-select>在使用ui-select时,有些是固定的ng-model="sort.selected"这里sort对象里的selected是固定的写法。
还有对选项的分组处理,第一次我做了,但是没生效,只是一个简单的错误(没有加单引号)。在ui-select-choices里添加group-by属性
<ui-select-choices group-by="'groupName'" title="选择指标" repeat="metricCode in metricCodes | propsFilter: {name: $select.search}">
<div style="display:inline-block;">{{metricCode.name}}</div>
</ui-select-choices>如何在作用域之间通信呢?
1.创建一个单例服务,然后通过这个服务处理所有子作用域的通信。
2.通过作用域中的事件处理通信。但是这种方法有一些限制;例如,你并不能广泛的将事件传播到所有监控的作用域中。你必须选择是否与父级作用域或者子作用域通信。
$on、$emit和$broadcast使得event、data在controller之间的传递变的简单。
$emit:子传父 传递event与data
$broadcast:父传子 child controller传递event与data
$on:监听或接收数据。。用于接收event与data
$broadcast、$emit事件必须依靠其他事件(ng-click等)进行触发,而不能单纯写一个这个。
$on倒是可以直接写,因为它属于监听和接收数据的。
$on的方法中的event事件参数:
event.name 事件名称
event.targetScope 发出或者传播原始事件的作用域
event.currentScope 目前正在处理的事件的作用域
event.stopPropagation() 一个防止事件进一步传播(冒泡/捕获)的函数(这只适用于使用$emit发出的事件)
event.preventDefault() 这个方法实际上不会做什么事,但是会设置defaultPrevented为true。直到事件监听器的实现者采取行动之前它才会检查defaultPrevented的值。
event.defaultPrevented 如果调用了preventDefault则为true
第一次在项目中见到使用方式:
1.在定义指令。
app.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished')
})
}
}
}
});2.在页面上使用指令。
on-finish-render="ngRepeatFinished" 3.在控制器中监听。
$scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
getUserName(-10);
});上面的例子是使用指令来增加页面的水印,在单循环列表的页面上是没有问题的,但是在多重循环的页面上就会出现问题。如下
<div ng-repeat="func in functions" on-finish-render style="margin-bottom: 60px">
<div class="report-header">
<div>
{{func.name}}
</div>
</div>
<div class="report-body container" style="margin-top: 10px">
<div class="row" ng-repeat="(index,value) in func.colTitles" style="padding: 5px 0" ng-style="{'background-color':((tabIndex==0&&(index==4||index==7))||((tabIndex==1||tabIndex==2)&&index==11))?'#ddcccc':''}">
<div class="col-xs-6" style="padding-right: 0">
<label>{{value}}</label>
</div>
<div class="col-xs-6">
{{func.colValues[index]}}
</div>
</div>
</div>
</div>如上面的代码,页面前半部分有水印,后面就没有来,定位发现,angluarjs绘制是先绘制外层的循环,当外层的循环绘制完成后,才会再去绘制里面的的子循环。由于我们的指令on-finish-render放在外层循环里,所以外层循环完后就触发指令,这时获取的高度就会不对,绘制的水印也会出现问题。修改后代码:
<div ng-repeat="func in functions" style="margin-bottom: 60px">
<div class="report-header">
<div>
{{func.name}}-{{$last}}
</div>
</div>
<div ng-if="$last" class="report-body container" style="margin-top: 10px">
<div class="row" ng-repeat="(index,value) in func.colTitles" on-finish-render style="padding: 5px 0" ng-style="{'background-color':((tabIndex==0&&(index==4||index==7))||((tabIndex==1||tabIndex==2)&&index==11))?'#ddcccc':''}">
<div class="col-xs-6" style="padding-right: 0">
<label>{{value}}</label>
</div>
<div class="col-xs-6">
{{func.colValues[index]}}
</div>
</div>
</div>
<div ng-if="!$last" class="report-body container" style="margin-top: 10px">
<div class="row" ng-repeat="(index,value) in func.colTitles" style="padding: 5px 0" ng-style="{'background-color':((tabIndex==0&&(index==4||index==7))||((tabIndex==1||tabIndex==2)&&index==11))?'#ddcccc':''}">
<div class="col-xs-6" style="padding-right: 0">
<label>{{value}}</label>
</div>
<div class="col-xs-6">
{{func.colValues[index]}}
</div>
</div>
</div>
</div>将水印代码放在外层最后一个的子循环里。
这个是可以在任意标签声明变量赋值的,但是为什么我声明一个对象数组,就是不会显示,郁闷。代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<body>
<div ng-app="">
<h1 ng-init="myText='Hello World222!'">{{myText}}</h1>
<p> ng-init 指令创建了 AngularJS 变量,你可以在应用中使用它。</p>
<div ng-init="sortList=[{name:‘首次告警时间’,value:0},{name:‘最近告警时间’,value:1},{name:‘告警级别’,value:2}]">
<select>
<option ng-repeat="item in sortList" value="item.value">item.name</option>
</select>
</div>
</div>
</body>
</html>
这里是对象数组的声明中英文符号的问题引起的。
指令用于循环输出指定次数的 HTML 元素。注意是带html标签的。
参考:http://www.runoob.com/angularjs/ng-ng-repeat.html
里面还有一些特殊属性:
$index
$first
$last
$middle
even
odd个人认为应该与repeat有所区别,上面的例子里有使用repeat的。
参考:https://www.cnblogs.com/BGOnline/p/5980751.html
三种使用方法:
1、通过$scope绑定(不推荐)
2、通过对象数组绑定
3、通过key/value键值对绑定
参考:http://blog.csdn.net/jumtre/article/details/50802136
基础知识,参考http://www.runoob.com/angularjs/angularjs-filters.html
实例代码:
<ui-select ng-model="selectSubSystem.selected" theme="select2" on-select="selectSubSystem()">
<ui-select-match placeholder="选择子系统">
{{selectSubSystem.selected.subSystemName}}({{selectSubSystem.selected.subSystemId}})
<i class="glyphicon glyphicon-menu-down wing"></i>
</ui-select-match>
<ui-select-choices repeat="subSystem in subSystems | propsFilter: {subSystemName: $select.search,subSystemId:$select.search}">
<div ng-bind-html="subSystem.subSystemName+'(' + subSystem.subSystemId + ')'"
style="display:inline-block;"></div>
</ui-select-choices>
</ui-select> .filter('propsFilter', function () {
//过滤
return function (items, props) {
var out = [];
if (angular.isArray(items)) {
items.forEach(function (item) {
var itemMatches = false;
var keys = Object.keys(props);
for (var i = 0; i < keys.length; i++) {
var prop = keys[i];
var text = props[prop].toLowerCase();
if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
itemMatches = true;
break;
}
}
if (itemMatches) {
out.push(item);
}
});
} else {
out = items;
}
return out;
}; 这里我知道propsFilter: {subSystemName: $select.search,subSystemId:$select.search}后面是跟的过滤的条件,但是item需要过滤的集合是如何传入的呢?$select.search是绑定搜索输入框的。
点击事件传送当前被点击的对象:
<div ng-click="showHide($event,$index)" showClick>可以通过$($event.target).closest('div')这样来获取节点
angular.min-1.4.5.js:107 Error: [$rootScope:inprog] http://errors.angularjs.org/1.4.5/$rootScope/inprog?p0=%24digest
使用$scope.$apply()提交变量更改,AngularJS报如上错误信息时,代表angular说它已经在处理脏数据了,你别老催他。实际上是起冲突了,使用$scope.$applyAsync()或去掉$scope.$apply()就OK了。
<div class="imgCommon metric-view-graph-panel" ng-repeat="(key,value) in metricIdMapName">
<div class="graph-header1" style="padding: 0;z-index: 99999 !important;">
<div class="pull-left m-l-5 m-t-15 m-r-10" ng-click="imgShow($event)">
<span class="glyphicon glyphicon-minus glyphicon-add" act="notouch"></span>
</div>
<div class="graph-name-div m-t-5" ng-click="imgShow($event)">
<div style="display: inline-block;max-width: 100%">
<h4 class="ng-binding">[{{key}}]{{value}}</h4>
</div>
</div>
<div class="pull-right m-r-20" style="font-size: 15px;margin-top: 10px;">
<i class="tool-title glyphicon glyphicon-menu-down rotate180 m-r-10" ng-click="changeTitle($event)"></i>
<i class="glyphicon glyphicon-refresh" style="margin-right:20px;" ng-click="refresh(key)"></i>
<span class="glyphicon glyphicon-fullscreen" act="notouch" ng-click="funllScreen(key)"></span>
</div>
<div class="chart_div chart_img">
<div class="graph_div graph_img" id="graph_{{key}}">
</div>
</div>
</div>
</div>从上面的代码可以看到,我们给函数传递当前的事件对象是这样做的ng-click="imgShow($event)";当然也可以传递自己想要的传递参数,如传递id, ng-click="refresh(key)";同样我们也可以给属性加上$scope里的值,如

从上图中可以看出属性id已经成功的将值写入了,但是ng-click="refresh(key)"依然没有变化,当初的我以为应该是ng-click="refresh(107450600)",就是key会转化成相应的数字,还以为不是这样传值的,结果debug后在js函数里获取的是正确的,最终确认是这样的 只是前台的html让人误解了。
使用我们需要引用highcharts-ng.js
<script src="js/highcharts-ng.js"></script>在模块里引用
var app = angular.module('myApp', ['ui.router', 'ui.select',"highcharts-ng"]);在html里使用
<highchart style="height:250px;display:block;" config="chartConfig"></highchart>其中chartConfig是$scope里拼接好生成图的json对象。在这里主要说说饼图与不使用angular的区别。
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.y}</b> 占比: {point.percentage:.1f} %',
distance:15
}
},
series:{
animation:false
}
},在普通里,我们这样设置就可以控制饼图的图例的显示了;但是在angular这样设置是不行的,它需要设置在每个数据的点里(如下)
pieSerie.data.push({
name:alarm.statisticsName,
y:alarm.counts,
color:COLORS[i],
dataLabels: {
format: '<b>{point.y}</b> 占比: {point.percentage:.1f} %',
}
});在项目中我们的首页是一个,通过url路径跳转到不同的页面,但是页面的标题都要随之变化。在angularjs里,我居然采用下面代码来实现
$("title").text("相同进程对比");当时就因为哪个title标签在ng-controller的控制之外,我不知道该如何对其进行控制,所以才采用了jquery这种粗劣的方式来解决问题的。
angularjs可以有以下两种方式来解决这个问题:
1.html采用如下方式:<title ng-bind="$root.pageTitle"></title>,这样我们可以在controller中通过$scope.$root.pageTitle="test";这样来赋值。 2.html采用如下方式:<title ng-bind="pageTitle"></title>,这样我们在contriller中引入父的scope($rootScope),$rootScope.pageTitle="test1";这样来赋值。
今天在使用该插件的时候,发现没有效果,主要是