angular开发指引
- 第一步:构建HTML标准模板库
views文件夹:元素HTML集合(反复调用的网页公共代码库,如tab切换,按钮,表格等公共页面元素)
- 第二步:向内存中写入模板内容
<script type="text/ng-template" id="templateId.html">
<p>This is the content of the template</p>
</script>
var App= angular.module('App', []);
App.run(function($templateCache) {
$templateCache.put('templateId.html', '模板内容');
});
- 第三步:制作指令(E)模板库
App.directive('directiveName', {//tab
scope:{item:'=directiveName'},
templateUrl: 'templateId.html',
link: function($scope, iElm) {
}
});
- 第四步:单页面UI布局实现
App.controller('controller1', ['$scope', function($scope) {
$scope.maindata=[];//实现逻辑:
}]);
- 第五步:调用缓存内容渲染页面
App.directive('directiveName', {
scope:{item:'=directiveName'},
templateUrl: 'templateId.html',
link: function($scope, iElm) {
var o = $templateCache.get("template/multiTemplate.tpl.html");
iElm.find("#tpl-list").append($.parseHTML(o)), t(a)(i);//内容渲染:
}
});
$templateCache.get('templateId.html')
- 第六步:指令实现功能点
App.directive('directiveName', {//功能1
scope:false,
templateUrl: 'templateId.html',
link: function($scope, iElm) {
iElm.find("#tpl-list").on("click", function() {
<--code-->
});
}
});
懒加载oclazyload
http://dreamapple.leanapp.cn/gitbook/oclazyload-doc/api/conf.html
依赖注入
var objCtrl = function($scope, $timeout, $interval){
// do something
}
//给objCtrl函数增加一个$inject属性,它是一个数组,定义了需要被注入的对象
objCtrl.$inject = ['$scope', '$interval', '$timeout'];
Angularjs方法
API 方法 | 描述 |
---|---|
Config(configFn) | 使用这个方法来注册一些当模块加载时需要做的工作 |
Constant(name,object) | 这个发生在第一次,因此你能够声明所有应用范围内的常量, 让他们在所有的配置中可用 (这列表中的第一个方法) ,实例化方法(来这里的所有方法,像控制器,服务等等) |
Controller(name,constructor) | 我们已经看到了它的许多示例;它建立了一个基本可用的控制器 |
Directive(name,directiveFactory) | 这个允许你在应用中创建标识符 |
Run(initializationFn) | 当你需要在注入器建立后执行一些工作,恰好在应用对用户可用前,你可以使用这个方法 |
Value(name,object) | 允许跨应用注入值 |
Service(name,serviceFactory) | , Factory 和 Service 间的区别就是 Factory 调用函数传递进去然后返回结果 |
Factory(name,factoryFn) | 每当我们有一个类或对象,在它们初始化之前需要大量的逻辑和参数时,就可以调用Factory API |
Provider(name,providerFn) | 这是它们当中最复杂的(显然,最可配置的) 。Provider 结合了 Factory 和 Service,以及在注入系统完全就位之前, 抛出配置 Provider 函数的配置信息 |
Angularjs执行顺序
Provider
无论何时只要有人调用了 greeter 对象的实例,AngularJS 内部就会调用$get 函数
myApp.provider('greeter', function() {
var salutation = 'Hello';
this.setSalutation = function(s) {
salutation = s;
}
function Greeter(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}
this.$get = function(a) {
return new Greeter(a);
};
});
scope . $on emit
scope.$on('planetDestroyed', function(event, galaxy, planet) {
// Custom event, so what planet was destroyed
scope.alertNearbyPlanets(galaxy, planet);
});
scope.$on('selfDestructSystem', function(event, targetSystem) {
if (scope.mySystem === targetSystem) {
scope.selfDestruct(); // Go Ka-boom!!
}
});
API 方法 | 描述 |
---|---|
Event.targetScope | 发出或者传播原始事件的作用域 |
Event.currentScope | 当前处理事件的作用域 |
Event.name | 事件名称 |
Event.stopPropagation() | 阻止事件进一步传播的函数(这个只有在$emit 的事件时才可用) |
Event.preventDefault() | 只是设置了defalutPrevented 为 true |
Event.defalutPrevented | 如果 preventDefalut 调用了就是 true |
$cookie
function SearchController($scope, $cookieStore) {
$scope.search = function(text) {
// Do the search here
…
// Get the past results, or initialize an empty array if nothing found
var pastSearches = $cookieStore.get('myapp.past.searches') || [];
if (pastSearches.length > 5) {
pastSearches = pastSearches.splice(0);
}
pastSearches.push(text);
$cookieStore.put('myapp.past.searches', pastSearches);
}
};
HTML指令
- * div转输入框*
<div contentEditable="true"></div>
directive
- restrict
restrict: ‘EACM’
E:元素,A:属性,C:样式类,M:注释类
html:
<hello>
hello标签里存在的内容
</hello>
js:
mymodule.directive('hello', function() {
return {
restrict: 'E',
template: '<div>Hi there <span ng-transclude>这里的内容不会显示</span></div>',
transclude: true//transclude为true把hello标签已有的内容替换到ng-transclude的span标签中并显示出来
};
});
- directive调用自身数据
<head>
<script>
angular.module("exampleApp", [])
.directive("resetTotals", function () {
return {
scope: {},
controller:function ($scope, $element, $attrs) {
$scope.data=[{name:'one'},{name:'two'}];
},
template: "<div ng-repeat='(key, value) in data'>{{value.name}}</div>",
link: function (scope, element, attrs, ctrl) {
}
}
});
</script>
</head>
<body ng-app="exampleApp">
<div reset-totals></div>
</body>
等同于:
<head>
<script type="text/ng-template" id="resetTemplate">
<div ng-repeat='(key, value) in data'>{{value.name}}</div>
</script>
<script>
angular.module("exampleApp", [])
.directive("resetTotals", function () {
return {
scope: {},
controller:function ($scope, $element, $attrs) {
$scope.data=[{name:'one'},{name:'two'}];
},
template: document.querySelector("#resetTemplate").outerText,
link: function (scope, element, attrs, ctrl) {
}
}
});
</script>
</head>
<body ng-app="exampleApp">
<div reset-totals></div>
</body>
- directive调用controller数据
<head>
<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope) {
$scope.products = [{ name: "Apples", price: 1.20, quantity: 2 },
{ name: "Bananas", price: 2.42, quantity: 3 },
{ name: "Pears", price: 2.02, quantity: 1 }];
})
.directive("resetTotals", function () {
return {
scope: {data:"=productTable"},
template: "<div ng-repeat='(key, value) in data'>{{value.name}}</div>",
link: function (scope, element, attrs, ctrl) {
}
}
});
</script>
</head>
<body ng-app="exampleApp">
<div ng-controller="defaultCtrl">
<div reset-totals product-table="products"></div>
</div>
- directive调用另一directive数据
<head>
<script>
angular.module("exampleApp", [])
.directive("productTable", function () {
return {
scope: {},
controller: function ($scope, $element, $attrs) {
$scope.data=[{name:'one'},{name:'two'}];
}
}
})
.directive("resetTotals", function () {
return {
/*scope: {},*/不能创建属于自己的scope否则报错!
require: "^productTable",//引用的directive名
template: "<div ng-repeat='(key, value) in data'>{{value.name}}</div>",
link: function (scope, element, attrs, ctrl) {
}
}
});
</script>
</head>
<body ng-app="exampleApp">
<div>
<div reset-totals product-table></div>//需要在此处或者上层标签引入依赖的指令
</div>
- directive调用自身和controller数据
<head>
<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope) {
$scope.products = [{ name: "Apples", price: 1.20, quantity: 2 },
{ name: "Bananas", price: 2.42, quantity: 3 },
{ name: "Pears", price: 2.02, quantity: 1 }];
})
.directive("resetTotals", function () {
return {
scope: {data2:"=resetData"},//把controller的数据拉到自己的作用域下,并绑定!
controller:function ($scope, $element, $attrs) {
$scope.data1=[{name:'one'},{name:'two'}];
},
template: "<div ng-repeat='(key, value) in data1'>{{value.name}}</div><div ng-repeat='(key, value) in data2'>{{value.name}}</div>",
link: function (scope, element, attrs, ctrl) {
}
}
});
</script>
</head>
<body ng-app="exampleApp">
<div ng-controller="defaultCtrl">
<div reset-totals reset-data="products"></div>
</div>
- directive通过另一directive调用controller数据
<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope) {
$scope.products = [{ name: "Apples", price: 1.20, quantity: 2 },
{ name: "Bananas", price: 2.42, quantity: 3 },
{ name: "Pears", price: 2.02, quantity: 1 }];
})
.directive("productTable", function () {
return {
scope: {ctrldata:"=productTable"},
controller: function ($scope, $element, $attrs) {
$scope.data=[{name:'one'},{name:'two'}];
}
}
})
.directive("resetTotals", function () {
return {
/*scope: {},*/
require: "^productTable",//引用的directive名
template: "<div ng-repeat='(key, value) in data'>{{value.name}}</div><div ng-repeat='(key, value) in ctrldata'>{{value.name}}</div>",
link: function (scope, element, attrs, ctrl) {
}
}
});
</script>
</head>
<body ng-app="exampleApp">
<div ng-controller="defaultCtrl">//productTable若放在此处则仅调用productTable私有数据
<div reset-totals product-table="products"></div>//需放在统一标签上才能调用controller数据
</div>
</body>
- directive调用controller数据和调用另一directive的私有函数
<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope) {
$scope.products = [{ name: "Apples", price: 1.20, quantity: 2 },
{ name: "Bananas", price: 2.42, quantity: 3 },
{ name: "Pears", price: 2.02, quantity: 1 }];
})
.directive("productTable", function () {
return {
scope: {ctrldata:"=productTable"},
controller: function ($scope, $element, $attrs) {
$scope.data=[{name:'one'},{name:'two'}];
this.updateTotal = function () {
console.log('调用函数');
}
}
}
})
.directive("resetTotals", function () {
return {
scope: { data: "=productData", propname: "@propertyName" },
require: "^productTable",//引用的directive名
template: "<div ng-repeat='(key, value) in data'>{{value.name}}{{propname}}</div><div ng-repeat='(key, value) in ctrldata2'>{{value.name}}</div>",
link: function (scope, element, attrs, ctrl) {
ctrl.updateTotal();
}
}
});
</script>
</head>
<body ng-app="exampleApp">
<div ng-controller="defaultCtrl" product-table="products">
<div reset-totals product-data="products" property-name="quantity"></div>
</div>
</body>
- scope
<script type="text/ng-template" id="scopeTemplate">
<div class="panel-body">
<p>Data Value: <input ng-model="local" /></p>
</div>
</script>
.directive("scopeDemo", function () {
return {
template: function () {
return angular.element(
document.querySelector("#scopeTemplate")).html();//获取模板
},
scope: {
local1: "=name1",//双向绑定
//local1为模板中的代名词,name1为指令中的代名词,指令则指向controller($scope.data = {name: "Adam"})中对应的变量(name1="data.name"),建立连接关系!
local2: "@name2",单向绑定
cityFn: "&city" 获取controller中的函数!
}
}
})
.controller("scopeCtrl", function ($scope) {
$scope.data = {
name: "Adam",
defaultCity: "London"
};
$scope.getCity = function (name) {
return name == "Adam" ? $scope.data.defaultCity : "Unknown";
}
});
</script>
</head>
<body ng-controller="scopeCtrl">
<div class="panel panel-default">
<div class="panel-body">
Direct Binding: <input ng-model="data.name" />
</div>
<div class="panel-body" scope-demo
city="getCity(data.name)" nameprop="data.name"></div>
</div>
</body>
- angular.element方法汇总
directive:
require: ['ngModel'],
ngModelCtrl.$setViewValue(isActive ? $scope.$eval(iAttrs.tabChange) : $scope.$eval(iAttrs.tabChange));
addClass()-为每个匹配的元素添加指定的样式类名
after()-在匹配元素集合中的每个元素后面插入参数所指定的内容,作为其兄弟节点
append()-在每个匹配元素里面的末尾处插入参数内容
attr() - 获取匹配的元素集合中的第一个元素的属性的值
bind() - 为一个元素绑定一个事件处理程序
children() - 获得匹配元素集合中每个元素的子元素,选择器选择性筛选
clone()-创建一个匹配的元素集合的深度拷贝副本
contents()-获得匹配元素集合中每个元素的子元素,包括文字和注释节点
css() - 获取匹配元素集合中的第一个元素的样式属性的值
data()-在匹配元素上存储任意相关数据
detach()-从DOM中去掉所有匹配的元素
empty()-从DOM中移除集合中匹配元素的所有子节点
eq()-减少匹配元素的集合为指定的索引的哪一个元素
find() - 通过一个选择器,jQuery对象,或元素过滤,得到当前匹配的元素集合中每个元素的后代
hasClass()-确定任何一个匹配元素是否有被分配给定的(样式)类,例:iElm.hasClass($scope.activeClass);
html()-获取集合中第一个匹配元素的HTML内容
next() - 取得匹配的元素集合中每一个元素紧邻的后面同辈元素的元素集合。如果提供一个选择器,那么只有紧跟着的兄弟元素满足选择器时,才会返回此元素
on() - 在选定的元素上绑定一个或多个事件处理函数
off() - 移除一个事件处理函数
one() - 为元素的事件添加处理函数。处理函数在每个元素上每种事件类型最多执行一次
parent() - 取得匹配元素集合中,每个元素的父元素,可以提供一个可选的选择器
prepend()-将参数内容插入到每个匹配元素的前面(元素内部)
prop()-获取匹配的元素集中第一个元素的属性(property)值
ready()-当DOM准备就绪时,指定一个函数来执行
remove()-将匹配元素集合从DOM中删除。(同时移除元素上的事件及 jQuery 数据。)
removeAttr()-为匹配的元素集合中的每个元素中移除一个属性(attribute)
removeClass()-移除集合中每个匹配元素上一个,多个或全部样式
removeData()-在元素上移除绑定的数据
replaceWith()-用提供的内容替换集合中所有匹配的元素并且返回被删除元素的集合
text()-得到匹配元素集合中每个元素的合并文本,包括他们的后代
toggleClass()-在匹配的元素集合中的每个元素上添加或删除一个或多个样式类,取决于这个样式类是否存在或值切换属性。即:如果存在(不存在)就删除(添加)一个类.例:element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));
triggerHandler() -为一个事件执行附加到元素的所有处理程序
unbind() - 从元素上删除一个以前附加事件处理程序
val()-获取匹配的元素集合中第一个元素的当前值
wrap()-在每个匹配的元素外层包上一个html元素
封装jQuery插件
<input datepicker ng-model="currentDate" select="updateMyText(date)"></input>
angular.module('myApp.directives', [])
.directive('datepicker', function() {
return {
// Enforce the angularJS default of restricting the directive to
// attributes only
restrict: 'A',
// Always use along with an ng-model
require: '?ngModel',
scope: {
// This method needs to be defined and
// passed in to the directive from the view controller
select: '&' // Bind the select function we refer to the
// right scope
},
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return;
var optionsObj = {};
optionsObj.dateFormat = 'mm/dd/yy';
var updateModel = function(dateTxt) {
scope.$apply(function() {
// Call the internal AngularJS helper to
// update the two-way binding
ngModel.$setViewValue(dateTxt);
});
};
optionsObj.onSelect = function(dateTxt, picker) {
updateModel(dateTxt);
if (scope.select) {
scope.$apply(function() {
scope.select({
date: dateTxt
});
});
}
};
ngModel.$render = function() {
// Use the AngularJS internal 'binding-specific' variable
element.datepicker('setDate', ngModel.$viewValue || '');
};
element.datepicker(optionsObj);
}
};
});
$templateCache service内存加载
如果之前使用过Bootstrap 插件的ng版,即angular-ui,就会了解到这种方式的具体应用。模板本质上是字符串,把字符串直接写入内存,加载时直接从内存获取,速度会更快,有两种方式显式启用内存加载。
- * 通过使用 $templateCache service来实现*
angular.module('myApp', [])
.controller('myCtrl', ['$scope','$templateCache', function($scope,$templateCache){
var tmp = '<h4>lovestory</h4>'
+ '<p>这是直接调用$templateCache服务获取模板文件的方式</p>'
+ '<a href="http://www.baidu.com">服务启用templateCache方式</a>';
$templateCache.put('lovestory.html',tmp);
}])
$templateCache 服务put方法负责向内存写入模板内容。
angular.module("views/diaryList.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("views/diaryList.html", '*******'
}]);
这部分代码等效于
<script type="text/ng-template" id="views/diaryList.html">
***********
</script>
$templateCache 服务get方法获取模板内容。
.directive("eqdTemplate", ["$compile", "$templateCache", function(t, e) {
return {
restrict: "E",
templateUrl: "create/left/template/template.tpl.html",
replace: !0,
scope: !0,
controller: "TplCtrl",
link: function(i, a) {
i.$on("printDetail.get", function(n, l) {
var r = l.type;
if (9 == r) {
a.attr("eqd-multi-template", "");
var o = e.get("create/left/template/multiTemplate.tpl.html");
a.find("#tpl-list").append($.parseHTML(o)), t(a)(i)
}
})
}
}
}])
方法 | 功能 |
---|---|
put | 向内存写入模板内容 |
get | 从内存获取模板内容 |
remove | 传入key值,删除对应模板内容 |
removeAll | 删除所有模板内容 |
destroy | 解除key-value对应关系,但不释放内存 |
info | 模板缓存对象的信息 |
-通过 script 标签引入
<script type="text/ng-template" id="lovestory.html">
<h4>lovestory</h4>
<p>这是script标签获取模板文件的方式</p>
<a href="http://www.baidu.com">标签启用templateCache方式</a>
</script>
这里需要注意, type=”text/ng-template” 是指明这是ng模板,id属性是指实际使用模板时的一个引用,标签之间的内容才是实际的模板内容。而且,需要注意,id绝对不是URL,这个 script 标签绝对不会发出HTTP请求,具体讨论见最后。
实际应用模板时候,使用 ID 属性,即可从内存中获取对应数据。
<div ng-include="'lovestory.html'" class="well"></div>
使用 ng-include 的时候,应该注意,id相当于一个字符串,不是 ng-expression ,所以不要忘了加单引号。
- AJAX加载
上述的内存加载,相当于一个预定义模板,定义在 client-side ,不会与服务器有任何交互,适合变化频率低的模板。
当NG在内存中找不到对应模板时,就会启用AJAX请求,去拉取对应模板。假设项目入口文件地址为 http://127.0.0.1/index.html ;
<div ng-include="'lovestory.html'" class="well"></div>
在指令中同样可以使用,templateUrl对应值
angular.module('myApp', [])
.directive('templateDemo', ['$log', function($log){
return {
restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
templateUrl: 'butterfly.html',
replace: true,
link: function($scope, iElm, iAttrs, controller) {}
}
}])
内存中没有对应模板时,AJAX请求地址为 http://127.0.0.1/lovestory.html , 请求成功后将对应内容写入 $templateCache ,在页面不进行刷新,不手动删除的情况下,写入的内容不会丢失。而且,务必记住,AJAX是有缓存控制的。。。