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 中的 MVC 模式
Apr 11 Javascript
js的Prototype属性解释及常用方法
May 08 Javascript
Javascript Objects详解
Sep 04 Javascript
javascript结合CSS实现苹果开关按钮特效
Apr 07 Javascript
JavaScript 模块化编程(笔记)
Apr 08 Javascript
JQuery入门基础小实例(1)
Sep 17 Javascript
Select2.js下拉框使用小结
Oct 24 Javascript
js实现延迟加载的几种方法
Apr 24 Javascript
vue实现在表格里,取每行的id的方法
Mar 09 Javascript
Node.js + express实现上传大文件的方法分析【图片、文本文件】
Mar 14 Javascript
如何自动化部署项目?折腾服务器之旅~
Apr 16 Javascript
highcharts.js数据绑定方式代码实例
Nov 13 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
PHP对象转换为数组函数(递归方法)
2012/02/04 PHP
PHP生成图片验证码、点击切换实例
2014/06/25 PHP
php实现购物车功能(上)
2020/07/23 PHP
php json_encode与json_decode详解及实例
2016/12/13 PHP
移动设备web开发首选框架:zeptojs介绍
2015/01/29 Javascript
基于jQuery通过jQuery.form.js插件实现异步上传
2015/12/13 Javascript
JS查找字符串中出现次数最多的字符
2016/09/05 Javascript
微信小程序page的生命周期和音频播放及监听实例详解
2017/04/07 Javascript
vue.js评论发布信息可插入QQ表情功能
2017/08/08 Javascript
bootstrap switch开关组件使用方法详解
2017/08/22 Javascript
Angular实现预加载延迟模块的示例
2017/10/12 Javascript
浅谈Vue SPA 首屏加载优化实践
2017/12/15 Javascript
解决vue2.0 element-ui中el-upload的before-upload方法返回false时submit()不生效问题
2018/08/24 Javascript
iview同时验证多个表单问题总结
2018/09/29 Javascript
VeeValidate 的使用场景以及配置详解
2019/01/11 Javascript
在 Vue.js中优雅地使用全局事件的方法
2019/02/01 Javascript
Vue路由之JWT身份认证的实现方法
2019/08/26 Javascript
Vue搭建后台系统需要注意的问题
2019/11/08 Javascript
js实现上传按钮并显示缩略图小轮子
2020/05/04 Javascript
[01:29]2014DOTA2展望TI 剑指西雅图DK战队专访
2014/06/30 DOTA
[42:34]VP vs VG 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python写的一个文本编辑器
2014/01/23 Python
python安装Scrapy图文教程
2017/08/14 Python
python K近邻算法的kd树实现
2018/09/06 Python
python多任务及返回值的处理方法
2019/01/22 Python
python的pytest框架之命令行参数详解(上)
2019/06/27 Python
python爬虫scrapy图书分类实例讲解
2020/11/23 Python
anaconda升级sklearn版本的实现方法
2021/02/22 Python
HTML最新标准HTML5总结(必看)
2016/06/13 HTML / CSS
购买大码女装:Lane Bryant
2016/09/07 全球购物
美国环保妈妈、儿童和婴儿用品购物网站:The Tot
2019/11/24 全球购物
青年文明号口号
2014/06/17 职场文书
2015年元旦演讲稿
2014/09/12 职场文书
2014年检验科工作总结
2014/11/22 职场文书
Spring实现内置监听器
2021/07/09 Java/Android
JavaScript组合继承详解
2021/11/07 Javascript