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数值转换的三种方式总结
Jul 31 Javascript
js判断浏览器类型及设备(移动页面开发)
Jul 30 Javascript
在jQuery中处理XML数据的大致方法
Aug 14 Javascript
JS基于面向对象实现的拖拽库实例
Sep 24 Javascript
有关Promises异步问题详解
Nov 13 Javascript
使用JS轻松实现ionic调用键盘搜索功能(超实用)
Sep 06 Javascript
AngularJs+Bootstrap实现漂亮的计算器
Aug 10 Javascript
微信小程序表单验证form提交错误提示效果
Jun 19 Javascript
element-ui 设置菜单栏展开的方法
Aug 22 Javascript
Vue一个案例引发的递归组件的使用详解
Nov 15 Javascript
layui表单提交到后台自动封装到实体类的方法
Sep 12 Javascript
javascript实现移动端触屏拖拽功能
Jul 29 Javascript
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
hadoop常见错误以及处理方法详解
2013/06/19 PHP
jquery 防止表单重复提交代码
2010/01/21 Javascript
超简单的jquery的AJAX用法
2010/05/10 Javascript
Three.js源码阅读笔记(物体是如何组织的)
2012/12/27 Javascript
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
javascript动态创建及删除元素的方法
2014/12/22 Javascript
JavaScript分秒倒计时器实现方法
2015/02/02 Javascript
Javascript基于对象三大特性(封装性、继承性、多态性)
2016/01/04 Javascript
jQuery ztree实现动态树形多选菜单
2016/08/12 Javascript
为jQuery-easyui的tab组件添加右键菜单功能的简单实例
2016/10/10 Javascript
JavaScript组成、引入、输出、运算符基础知识讲解
2016/12/08 Javascript
jQuery简单实现MD5加密的方法
2017/03/03 Javascript
Vue 2.0中生命周期与钩子函数的一些理解
2017/05/09 Javascript
Angular.js组件之input mask对input输入进行格式化详解
2017/07/10 Javascript
js Dom实现换肤效果
2017/10/21 Javascript
vue弹窗组件使用方法
2018/04/28 Javascript
jquery实现二级导航下拉菜单效果实例
2019/05/14 jQuery
Vue实现固定定位图标滑动隐藏效果
2019/05/30 Javascript
[01:02:17]2014 DOTA2华西杯精英邀请赛 5 24 DK VS VG
2014/05/26 DOTA
[03:18]【TI9纪实】社区大触GL与木木
2019/08/25 DOTA
[02:46]完美世界DOTA2联赛PWL DAY4集锦
2020/11/03 DOTA
Python 数据结构之队列的实现
2017/01/22 Python
python添加模块搜索路径方法
2017/09/11 Python
python 连接各类主流数据库的实例代码
2018/01/30 Python
Python 正则表达式爬虫使用案例解析
2019/09/23 Python
python批量将excel内容进行翻译写入功能
2019/10/10 Python
Python实现手机号自动判断男女性别(实例解析)
2019/12/22 Python
Python读取Excel数据并生成图表过程解析
2020/06/18 Python
使用keras实现非线性回归(两种加激活函数的方式)
2020/07/05 Python
Python:__eq__和__str__函数的使用示例
2020/09/26 Python
详解CSS3开启硬件加速的使用和坑
2017/08/21 HTML / CSS
酒店服务与管理毕业生求职信
2013/11/02 职场文书
2014年党员发展工作总结
2014/12/02 职场文书
幼儿园托班开学寄语(2016秋季)
2015/12/03 职场文书
Python文件的操作示例的详细讲解
2021/04/08 Python
matplotlib之pyplot模块实现添加子图subplot的使用
2021/04/25 Python