Angular1.x复杂指令实例详解


Posted in Javascript onMarch 01, 2017

本文实例讲述了Angular1.x复杂指令。分享给大家供大家参考,具体如下:

名称 描述
compile 指定一个编译函数
controller 为指令创建一个控制器函数
link 为指令指定链接函数
replace 指定模板内容是否替换指令所应用到的元素
require 声明对某个控制器的依赖
restrict 指定指令如何使用ACEM
scope 为指令创建一个新的作用域或者一个隔离的作用域
template 指定一个将被插入到HTML文档的模板
templateUrl 指定一个将被插入到HTML文档的外部模板
transclude 指定指令是否被用于包含任意内容

.directive('unorderedList', function () {
  return {
    link: function (scope, element, attrs) {
      var data = scope[attrs['unorderedList'] || attrs['listSource'] ];
      var propertyName = 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, len=data.length; i<len; i++){
          var itemElem = angular.element('<li>').text(scope.$eval(propertyName, data[i]));
          listElem.append(itemElem);
        }
      }
    },
    restrict:'EACM'
  };
});

如何使用指令

当作元素使用(E)

<unordered-list list-source="products" list-property="price | currency" />

当unordered-list当作元素使用,需要添加另外的属性代替unordered-list属性的作用。

var data = scope[attrs['unorderedList'] || attrs['listSource'] ];

当作属性使用(A)

<div unordered-list="products" list-property="price | currency"></div>

当作类的属性值使用(C)

<div class="unordered-list: products" list-property="price | currency"></div>

当作注释使用(M)

<!-- directive: unordered-list products -->

使用模板指令

.directive('unorderedList', function () {
  return {
    link: function (scope, element, attrs) {
      scope.data = scope[attrs['unorderedList']];
    },
    restrict: 'A',
    template:"<ul><li ng-repeat='item in data'>{{item.price | currency}}</li></ul>"
  };
});

使用函数作为模板

template属性除了使用字符串,也可以指定一个函数来生成模板化的内容。该函数传入两个函数(指令所应用到的元素以及属性集合)并返回将被插入到文档中的HTML代码片段。

<script type="text/javascript" id="listTemplate">
  <ul>
    <li ng-repeat="item in data">{{item.price | currency}}</li>
  </ul>
</script>
<script>
var myApp = angular.module('myApp', [])
  .controller('myCtrl', ["$scope", function ($scope) {
    $scope.products = [
      { name: "Apples", category: "Fruit", price: 1.20, expiry: 10 },
      { name: "Bananas", category: "Fruit", price: 2.42, expiry: 7 },
      { name: "Pears", category: "Fruit", price: 2.02, expiry: 6 }
    ];
  }])
    .directive('unorderedList', function () {
      return {
        link: function (scope, element, attrs) {
          scope.data = scope[attrs['unorderedList']];
        },
        restrict: 'A',
        template:function () {
          return angular.element(
              document.querySelector("#listTemplate")
          ).html();
        }
      };
    });
</script>

使用外部模板

itemTemplate.html

<p>This is the form the template file</p>
<ul>
  <li ng-repeat="item in data">{{item.price | currency}}</li>
</ul>
.directive('unorderedList', function () {
  return {
    link: function (scope, element, attrs) {
      scope.data = scope[attrs['unorderedList']];
    },
    restrict: 'A',
    templateUrl:"itemTemplate.html"
  };
});

通过函数选择一个外部模版

tableTemplate.html

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Price</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="item in data">
      <td>{{item.name}}</td>
      <td>{{item.price | currency}}</td>
    </tr>
  </tbody>
</table>
<div unordered-list="products" template="table" class="table table-striped">
  This is where the list will go
</div>
.directive('unorderedList', function () {
  return {
    link: function (scope, element, attrs) {
      scope.data = scope[attrs['unorderedList']];
    },
    restrict: 'A',
    templateUrl: function (elem, attrs) {
      return attrs['template'] == "table" ? "tableTemplate.html" : "itemTemplate.html";
    }
  };
});

table-striped样式并没有起作用,设置replace属性为true后的效果是模版内容将替换掉指令所应用到的div元素。

管理指令的作用域

为每个指令实例创建自己的作用域

设置scope属性为true将允许我们在同一个控制器里复用这个指令,可以避免指令共享数据值。

<div class="panel panel-default">
  <div class="panel-body" scope-demo></div>
  <div class="panel-body" scope-demo></div>
</div>
var myApp = angular.module('myApp', [])
.controller('myCtrl', ["$scope", function ($scope) {
  $scope.data = {name:"Staven"};
  $scope.city = "China"
}])
.directive('scopeDemo', function () {
  return {
    template: function () {
      return angular.element(document.querySelector("#scopeTemplate")).html();
    },
    scope:true
  };
});

data.name这个属性是在一个对象上定义的,意味着这个值将会在指令的哥哥实例之间所共享,而且所有相应的视图会同步更新。

city是直接在控制器的作用于上被直接赋值的,意味着这个值只在此指令的作用域上有效。

创建隔离的作用域

对于在一个对象上定义的属性,可能会被其他人改变。解决方法就是创建一个隔离的作用域,就是Angularjs为指令的每个实例创建一个独立的作用域的地方,但是这个作用域并不继承自控制器的作用域。当scope定义属性被设置为一个对象时,可创建一个隔离的作用域。隔离的作用域的最基本类型是用一个没有属性的对象表示。

.directive('scopeDemo', function () {
  return {
    template: function () {
      return angular.element(document.querySelector("#scopeTemplate")).html();
    },
    scope:{}
  };
});

当创建在不同情况下复用的指令时,隔离的作用域是一种重要的构件时。因为它防止了在控制器作用域和指令之间出现了意料外的交互。但是完全隔绝一个指令会使得难以输入和输出数据。

隔绝的作用域允许使用应用于指令旁边的元素上的属性将数据值绑定到控制器作用域上。

单向绑定@:

向以@为前缀的作用域对象上增添一个属性,以在一个隔离的作用力创建一个单向绑定。

<body ng-app="myApp" ng-controller="myCtrl">
  <div class="panel panel-default">
    <div class="panel-body">
      Direct Binding:<input ng-model="data.name" />
    </div>
    <div class="panel-body" scope-demo nameprop="{{data.name}}"></div>
  </div>
</body>
<script type="text/ng-template" id="scopeTemplate">
  <div class="panel-body">
    <p>Data Value:{{local}}</p>
  </div>
</script>
<script>
var myApp = angular.module('myApp', [])
.controller('myCtrl', ["$scope", function ($scope) {
  $scope.data = {name:"staven"};
}])
.directive('scopeDemo', function () {
  return {
    template: function () {
      return angular.element(document.querySelector("#scopeTemplate")).html();
    },
    scope:{
      local:"@nameprop"
    }
  };
});
</script>

local属性的值以@为前缀,制定了属性local的值应该从一个来自名为nameprop的特性的单向绑定来获得。

使用一个隔离的作用域使得指令不会继承控制器作用域中的数据。

双向绑定=:

向以=为前缀的作用域对象上增添一个属性,以在一个隔离的作用域里创建一个双向绑定。

在隔离作用于上的单向绑定总是被计算作字符串值,如果想访问一个数组,就必须使用双向绑定。

<div class="panel panel-default">
  <div class="panel-body">
    Direct Binding:<input ng-model="data.name" />
  </div>
  <div class="panel-body" scope-demo nameprop="data.name"></div>
</div>
<script type="text/ng-template" id="scopeTemplate">
  <div class="panel-body">
    <p>Data Value:<input ng-model="local" /></p>
  </div>
</script>
<script>
  scope:{
    local:"=nameprop"
  }
</script>

使用单向绑定时,提供了一个被"{{"和"}}"字符所包围的绑定表达式,但是angularjs需要知道在双向绑定中哪个属性需要被更新,所以不需要被"{{"和"}}"包围。

计算表达式&:

向以&为前缀的作用域对象上增添一个属性,在父作用域的上下文计算一个表达式。

<body ng-app="myApp" ng-controller="myCtrl">
<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>
<script type="text/ng-template" id="scopeTemplate">
  <div class="panel-body">
    <p>Name:{{local}}, City:{{cityFn()}}</p>
  </div>
</script>
<script>
var myApp = angular.module('myApp', [])
.controller('myCtrl', ["$scope", function ($scope) {
  $scope.data = {name:"staven",defaultCity:"hefei"};
  $scope.getCity = function (name) {
    console.log(1);
    return name == 'staven' ? $scope.data.defaultCity : "Unknown";
  }
}])
.directive('scopeDemo', function () {
  return {
    template: function () {
      return angular.element(document.querySelector("#scopeTemplate")).html();
    },
scope:{
  local:"=nameprop",
  cityFn:"&city"
}
  };
});
</script>

调用cityFn()时,使用了圆括号,要计算被这个特性所指定的表达式,这是必需的,即使当表达式本身就是一个函数调用时。

使用隔离作用域的数据来计算一个表达式

可以将来自代计算的隔离作用域的数据为控制器作用域表达式的一部分。

<div class="panel-body" scope-demo city="getCity(nameVal)" nameprop="data.name"></div>
<script type="text/ng-template" id="scopeTemplate">
  <div class="panel-body">
    <p>Name:{{local}}, City:{{cityFn({nameVal: local})}}</p>
  </div>
</script>

希望本文所述对大家AngularJS程序设计有所帮助。

Javascript 相关文章推荐
javascript 限制输入和粘贴(IE,firefox测试通过)
Nov 14 Javascript
Javascript hasOwnProperty 方法 &amp; in 关键字
Nov 26 Javascript
animate动画示例(泪奔的小孩)及stop和delay的使用
May 06 Javascript
基于JavaScript实现继承机制之原型链(prototype chaining)的详解
May 07 Javascript
jquery中常用的SET和GET$(”#msg”).html循环介绍
Oct 09 Javascript
JavaScript实现复制文章自动添加版权
Aug 02 Javascript
Bootstrap时间选择器datetimepicker和daterangepicker使用实例解析
Sep 17 Javascript
基于LayUI分页和LayUI laypage分页的使用示例
Aug 02 Javascript
新手必须知的Node.js 4个JavaScript基本概念
Sep 16 Javascript
细述Javascript的加法运算符的具体使用
Oct 18 Javascript
基于JS实现操作成功之后自动跳转页面
Sep 25 Javascript
vue组件中节流函数的失效的原因和解决方法
Dec 02 Vue.js
JS中使用 after 伪类清除浮动实例
Mar 01 #Javascript
Angular1.x自定义指令实例详解
Mar 01 #Javascript
轻松学习Javascript闭包
Mar 01 #Javascript
js图片延迟加载(Lazyload)三种实现方式
Mar 01 #Javascript
node.js实现回调的方法示例
Mar 01 #Javascript
JQ中$(window).load和$(document).ready区别与执行顺序
Mar 01 #Javascript
Angular2库初探
Mar 01 #Javascript
You might like
PhpMyAdmin中无法导入sql文件的解决办法
2010/01/08 PHP
php简单分页类实现方法
2015/02/26 PHP
php实现改变图片直接打开为下载的方法
2015/04/14 PHP
PHP面向对象之后期静态绑定功能介绍
2015/05/18 PHP
PHP实现长文章分页实例代码(附源码)
2016/02/03 PHP
PHP实现电商订单自动确认收货redis队列
2017/05/17 PHP
关于js中for in的缺陷浅析
2013/12/02 Javascript
jquery图片轮播特效代码分享
2020/04/20 Javascript
JS+CSS实现的漂亮渐变背景特效代码(6个渐变效果)
2016/03/25 Javascript
jQuery插件formValidator实现表单验证
2016/05/23 Javascript
jQuery.Uploadify插件实现带进度条的批量上传功能
2016/06/08 Javascript
jQuery新窗口打开外链接
2016/07/21 Javascript
JavaScript实现256色转灰度图
2017/02/22 Javascript
Vue使用枚举类型实现HTML下拉框步骤详解
2018/02/05 Javascript
解决Mac node版本升级失败的问题
2018/05/16 Javascript
对于Python中线程问题的简单讲解
2015/04/03 Python
django实现前后台交互实例
2017/08/07 Python
pandas 将索引值相加的方法
2018/11/15 Python
Python 文本文件内容批量抽取实例
2018/12/10 Python
django多对多表的创建,级联删除及手动创建第三张表
2019/07/25 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
2019/12/12 Python
python实现简单坦克大战
2020/03/27 Python
TensorFlow使用Graph的基本操作的实现
2020/04/22 Python
详解Html5中video标签那些属性和方法
2019/07/01 HTML / CSS
捷克母婴用品购物网站:Feedo.cz
2020/12/28 全球购物
Big Green Smile法国:领先的英国有机和天然产品在线商店
2021/01/02 全球购物
Columbia Sportswear法国官网:全球户外品牌
2020/09/25 全球购物
实现向右循环移位
2014/07/31 面试题
Internal修饰符有什么含义
2013/07/10 面试题
开学寄语大全
2014/04/08 职场文书
机关作风建设自查报告
2014/10/22 职场文书
公司捐书倡议书
2015/04/27 职场文书
重阳节简报
2015/07/20 职场文书
Django实现drf搜索过滤和排序过滤
2021/06/21 Python
Golang 对es的操作实例
2022/04/20 Golang
优化Mysql查询的示例
2022/04/26 MySQL