AngularJS 风谲云诡的指令
学习要点:
引子: 一、定义复杂的指令 <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default" ng-controller="defaultCtrl">
<div class="panel-heading">
<h3>Products</h3>
</div>
<div class="panel-body">
<!-- 指令当作元素 -->
<!-- <unorderlist list-source="products" list-property="price | currency"/> -->
<!-- 指令当作属性 -->
<div unorderlist="products" list-source="products" list-property="price | currency"></div>
</div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript"> angular.module("exampleApp",[]) .directive("unorderlist",function () { return { // link : 为指令指定连接函数 link: function (scope,element,attrs) { var data = scope[attrs["unorderlist"] || attrs["listSource"]]; var propertyExpression = attrs["listProperty"] || "price | currency"; if (angular.isArray(data)) { var listElem = angular.element("<ul>"); if (element[0].nodeName == "#comment") { element.parent().append(listElem); } else { element.append(listElem); } for (var i = 0; i < data.length; i++) { listElem.append(angular.element("<li>").text(scope.$eval(propertyExpression,data[i]))); } } },// restrict : 指定指令如何使用 ECMA 元素、类、注释和属性,类和注释一般不用 restrict : "ECMA" } }) .controller("defaultCtrl",function ($scope) { $scope.products = [ { name: "Apples",category: "Fruit",price: 1.20,expiry: 10 },{ name: "Bananas",price: 2.42,expiry: 7 },{ name: "Pears",price: 2.02,expiry: 6 } ]; }) </script>
</body>
</html>
定义的unorderlist指令返回一个水果列表,里面的逻辑我们在上一个已经详细讲解了【 AngularJS 优雅的自定义指令】 ,这里不再累赘 二、使用指令模板 angular.module("exampleApp",[])
.directive("unorderlist",function () {
return {
// link : 为指令指定连接函数
link: function (scope,attrs) {
// attrs['unorderlist'] 获取unorderlist属性值,这里为products
// 获取数据模型值,这里为scope.products,并且将其赋值给scope.data
scope.data = scope[attrs["unorderlist"] || attrs["listSource"]];
},// template : 指定一个将插入HTML的模板的指令
template : "<ul><li ng-repeat='item in data'>{{item.price | currency}}</li></ul>",类和注释一般不用
restrict : "EA"
}
})
2.使用函数作为模板 <!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar test</title> <meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css"> </head> <body> <dlv class="panel panel-default" ng-controller="defaultCtrl"> <div class="panel-heading"> <h3>Products</h3> </div> <div class="panel-body"> <!-- 指令当作元素 --> <!-- <unorderlist list-source="products" list-property="price | currency"/> --> <!-- 指令当作属性 --> <div unorderlist="products" list-source="products" list-property="price | currency"></div> </div> </dlv> <script type="text/javascript" src="js/angular.min.js"></script> <!-- 定义模板 --> <script type="text/template" id="tplList"> <ul> <li ng-repeat="item in data"> {{item.price | currency}} </li> </ul> </script> <script type="text/javascript"> angular.module("exampleApp",attrs) { // attrs['unorderlist'] 获取unorderlist属性值,这里为products // 获取数据模型值,这里为scope.products,并且将其赋值给scope.data scope.data = scope[attrs["unorderlist"] || attrs["listSource"]]; },// template : 指定一个将插入HTML的模板的指令 // 使用函数 template : function () { return angular.element(document.querySelector("#tplList")).html(); },类和注释一般不用 restrict : "EA" } }) .controller("defaultCtrl",expiry: 6 } ]; }) </script> </body> </html>
上述代码使用到了jqLite,我们应该尽量避免使用DOMAPI <table> <thead><th>Name</th><th>Price</th></thead> <tbody> <tr ng-repeat="item in data"> <td>{{item.name}}</td> <td>{{item.price | currency}}</td> </tr> </tbody> </table>
接下来,我们再定义一个外部模板文件,这里我们叫做itemTpl.html <p>This is the list from the template file</p> <ul> <li ng-repeat="item in data">{{item.price | currency}}</li> </ul>
第二步:我们来动态引用
4.替换元素 <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default" ng-controller="defaultCtrl">
<div class="panel-heading">
<h3>Products</h3>
</div>
<div class="panel-body">
<!-- 指令当作元素 -->
<!-- <unorderlist list-source="products" list-property="price | currency"/> -->
<!-- 指令当作属性 -->
<div unorderlist="products" template="table" class="table table-striped"></div>
</div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript"> angular.module("exampleApp",attrs) { return attrs["template"] == "table" ? "tableTpl.html" : "itemTpl.html"; },类和注释一般不用 restrict : "EA",// 指定模板元素是否替换指令所应用到的元素 replace : true,} }) .controller("defaultCtrl",expiry: 6 } ]; }) </script>
</body>
</html>
解析: 三、管理指令的作用域 先看看一个例子: <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default" ng-controller="scopeCtrl">
<div class="panel-heading">
<h3>Products</h3>
</div>
<div scope-dome></div>
<div scope-dome></div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript"> angular.module("exampleApp",[]) .directive("scopeDome",function () { return { // templateUrl : 指定一个将插入HTML的外部模板的指令 template : "<div class='panel-body'>Name: <input ng-model=name /></div>",} }) .controller("scopeCtrl",function ($scope) { }) </script>
</body>
</html>
1.建立多个控制器 <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default">
<div class="panel-heading">
<h3>Products</h3>
</div>
<div ng-controller="firstCtrl" scope-dome></div>
<div ng-controller="secondCtrl" scope-dome></div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript"> angular.module("exampleApp",} }) .controller("firstCtrl",function ($scope) { }) .controller("secondCtrl",function ($scope) { }) </script>
</body>
</html>
解析: 2.给每个指令实例创建自己的作用域 <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default">
<div class="panel-heading">
<h3>Products</h3>
</div>
<div ng-controller="firstCtrl" scope-dome></div>
<div ng-controller="secondCtrl" scope-dome></div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript"> angular.module("exampleApp",// scope : 为指令创建一个新的作用域或者是隔离的作用域 scope : true,} }) </script>
</body>
</html>
3.创建隔离作用域 <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default" ng-controller="scopeCtrl">
<div class="panel-heading">
<h3>Products</h3>
</div>
<div scope-dome></div>
<div scope-dome></div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <p>Name: <input ng-model="data.name" /></p> <p>City: <input ng-model="city" /></p> <p>Country: <input ng-model="country" /></p> </div> </script>
<script type="text/javascript"> angular.module("exampleApp",function () { return { // templateUrl : 指定一个将插入HTML的外部模板的指令 template : function () { return angular.element(document.querySelector("#scopeTemplate")).html(); },function ($scope) { // 共享 $scope.data = { name : "Tom"}; // 独立 $scope.city = "BeiJing"; }) </script>
</body>
</html>
这个例子中data.name共享,city独立 <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default" ng-controller="scopeCtrl">
<div class="panel-heading">
<h3>Products</h3>
</div>
<div scope-dome></div>
<div scope-dome></div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <p>Name: <input ng-model="data.name" /></p> <p>City: <input ng-model="city" /></p> <p>Country: <input ng-model="country" /></p> </div> </script>
<script type="text/javascript"> angular.module("exampleApp",// scope : 为指令创建一个新的作用域或者是隔离的作用域 scope : {},function ($scope) { $scope.data = { name : "Tom"}; $scope.city = "BeiJing"; }) </script>
</body>
</html>
这样,隔离控制器的指令元素不再受影响了 1.单向数据绑定 <!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar test</title> <meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css"> </head> <body> <dlv class="panel panel-default" ng-controller="scopeCtrl"> <div class="panel-heading"> <h3>Products</h3> </div> <!-- 本地作用域数据与scopeCtrl作用域数据绑定 --> <div scope-dome nameprop="{{data.name}}"></div> <div scope-dome nameprop="{{data.name}}"></div> </dlv> <script type="text/javascript" src="js/angular.min.js"></script> <script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <!-- 使用本地作用域数据 --> <p>Name: <input value="{{local}}" /></p> </div> </script> <script type="text/javascript"> angular.module("exampleApp",// scope : 为指令创建一个新的作用域或者是隔离的作用域 scope : { // 隔离的本地作用域 local : "@nameprop" },function ($scope) { $scope.data = { name : "Tom"}; $scope.city = "BeiJing"; }) </script> </body> </html>
在一开始两个输入框都获取了scopeCtrl作用域的data.name的值,但是两个输入框都是隔离作用域的,所有他们修改值时,不会影响其他的值 2.双向数据绑定 <!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar test</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<dlv class="panel panel-default" ng-controller="scopeCtrl">
<div class="panel-heading">
<h3>Products</h3>
</div>
<!-- 本地作用域数据与scopeCtrl作用域数据绑定 -->
<div scope-dome nameprop="data.name"></div>
<div scope-dome nameprop="data.name"></div>
</dlv>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <!-- 使用本地作用域数据 --> <p>Name: <input ng-model="local" /></p> </div> </script>
<script type="text/javascript"> angular.module("exampleApp",// scope : 为指令创建一个新的作用域或者是隔离的作用域 scope : { // 隔离的本地作用域 local : "=nameprop" },function ($scope) { $scope.data = { name : "Tom"}; $scope.city = "BeiJing"; }) </script>
</body>
</html>
一共做出了三处修改 3.使用函数表达式 <!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar test</title> <meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css"> </head> <body> <dlv class="panel panel-default" ng-controller="scopeCtrl"> <div class="panel-heading"> <h3>Products</h3> </div> <!-- 本地作用域数据与scopeCtrl作用域数据绑定 --> <div scope-dome nameprop="data.name" city="getCity(data.name)"></div> </dlv> <script type="text/javascript" src="js/angular.min.js"></script> <script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <!-- 使用本地作用域数据 --> <P>Name: {{local}},City : {{cityFn()}}</P> </div> </script> <script type="text/javascript"> angular.module("exampleApp",// scope : 为指令创建一个新的作用域或者是隔离的作用域 scope : { // 隔离的本地作用域 local : "=nameprop",cityFn : "&city" },function ($scope) { $scope.data = { name : "Tom"}; $scope.city = "BeiJing"; $scope.getCity = function (name) { console.log(name); return name == "Tom" ? $scope.city : "Unknow"; } }) </script> </body> </html>
4.直接用隔离作用域的数据来计算一个表达式 <!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar test</title> <meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css"> </head> <body> <dlv class="panel panel-default" ng-controller="scopeCtrl"> <div class="panel-heading"> <h3>Products</h3> </div> <!-- 本地作用域数据与scopeCtrl作用域数据绑定 --> <div scope-dome nameprop="data.name" city="getCity(nameValue)"></div> </dlv> <script type="text/javascript" src="js/angular.min.js"></script> <script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <!-- 使用隔离作用域的数据 --> <P>Name: {{local}},City : {{cityFn({nameValue : local})}}</P> </div> </script> <script type="text/javascript"> angular.module("exampleApp",function ($scope) { $scope.data = { name : "Tom"}; $scope.city = "BeiJing"; $scope.getCity = function (name) { console.log(name); return name == "Tom" ? $scope.city : "Unknow"; } }) </script> </body> </html>
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |