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 相关文章推荐
Jquery ajax传递复杂参数给WebService的实现代码
Aug 08 Javascript
基于jquery的时间段实现代码
Aug 02 Javascript
extjs3 combobox取value和text案例详解
Feb 06 Javascript
使用Raygun对Node.js应用进行错误处理的方法
Jun 23 Javascript
jQuery实现可用于博客的动态滑动菜单完整实例
Sep 17 Javascript
基于javascript实现图片懒加载
Jan 05 Javascript
JS实现的系统调色板完整实例
Dec 21 Javascript
AngularJs每天学习之总体介绍
Aug 07 Javascript
老生常谈JavaScript面向对象基础与this指向问题
Oct 16 Javascript
Node.js命令行/批处理中如何更改Linux用户密码浅析
Jul 22 Javascript
微信小程序非swiper组件实现的自定义伪3D轮播图效果示例
Dec 11 Javascript
vue.config.js中配置Vue的路径别名的方法
Feb 11 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基于base64解码图片与加密图片还原实例
2014/11/03 PHP
JQUERY CHECKBOX全选,取消全选,反选方法三
2008/08/30 Javascript
jquery 实现checkbox全选,反选,全不选等功能代码(奇数)
2012/10/24 Javascript
JS简单实现元素复制示例附图
2013/11/19 Javascript
jQuery中事件与动画的总结分享
2016/05/24 Javascript
jQuery如何跳转到另一个网页 就这么简单
2016/12/28 Javascript
使用Promise链式调用解决多个异步回调的问题
2017/01/15 Javascript
JS运动特效之任意值添加运动的方法分析
2018/01/24 Javascript
基于jQuery.i18n实现web前端的国际化
2018/05/04 jQuery
在小程序/mpvue中使用flyio发起网络请求的方法
2018/09/13 Javascript
vue中el-upload上传图片到七牛的示例代码
2018/10/19 Javascript
详解在不使用ssr的情况下解决Vue单页面SEO问题
2018/11/08 Javascript
angular 用Observable实现异步调用的方法
2018/12/27 Javascript
原生js实现无缝轮播图
2020/01/11 Javascript
详解Vue中的自定义指令
2020/12/07 Vue.js
Java中重定向输出流实现用文件记录程序日志
2015/06/12 Python
python动态网页批量爬取
2016/02/14 Python
Python实现单词翻译功能
2017/06/06 Python
浅谈利用numpy对矩阵进行归一化处理的方法
2018/07/11 Python
python实现嵌套列表平铺的两种方法
2018/11/08 Python
对Python3中bytes和HexStr之间的转换详解
2018/12/04 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
python简单验证码识别的实现方法
2019/05/10 Python
Python3 itchat实现微信定时发送群消息的实例代码
2019/07/12 Python
Python 中使用 PyMySQL模块操作数据库的方法
2019/11/10 Python
Python多线程多进程实例对比解析
2020/03/12 Python
python读取excel进行遍历/xlrd模块操作
2020/07/12 Python
Python模拟键盘输入自动登录TGP
2020/11/27 Python
pycharm配置安装autopep8自动规范代码的实现
2021/03/02 Python
Html5游戏开发之乒乓Ping Pong游戏示例(三)
2013/01/21 HTML / CSS
幼教毕业生自我鉴定
2014/01/12 职场文书
团队口号大全
2014/06/06 职场文书
2014年小学生教师节演讲稿范文
2014/09/10 职场文书
地下停车场租赁协议范本
2014/10/07 职场文书
优秀共产党员事迹材料
2014/12/18 职场文书
党建工作汇报材料
2014/12/24 职场文书