Angularjs 创建可复用组件实例代码


Posted in Javascript onOctober 09, 2016

AngularJS框架可以用Service和Directive降低开发复杂性。这个特性非常适合用于分离代码,创建可测试组件,然后将它们变成可重用组件。

Directive是一组独立的JavaScript、HTML和CSS,它们封装了一个特定的行为,它将成为将来创建的Web组件的组成部分,我们可以在各种应用中重用这些组件。在创建之后,我们可以直接通过一个HTML标签、自定义属性或CSS类、甚至可以是HTML注释,来执行一个Directive。

这一篇教程将介绍如何创建一个‘自定义步长选择' Directive,它可以作为一个可重用输入组件。本文不仅会介绍Directive的一般创建过程,还会介绍输入控件验证方法,以及如何使用ngModelController无缝整合任意表单,从而利用AngularJS表单的现有强大功能。

直接上代码:

html:

<!-- lang: html -->
<body ng-app="demo" ng-controller="DemoController">
  <form name="form" >
    Model value : <input type="text" size="3" ng-model="rating"><br>
    Min value: <input type="text" size="3" ng-model="minRating"><br>
    Max value: <input type="text" size="3"ng-model="maxRating"><br>
    Form has been modified : {{ form.$dirty }}<br>
    Form is valid : {{ form.$valid }}
    <hr><divmin="minRating"max="maxRating"ng-model="rating"rn-stepper></div></form></body>

js:

<!-- lang: js -->
angular.module(‘demo‘, [
  ‘revolunet.stepper‘
])

.controller(‘DemoController‘, function($scope) {
  $scope.rating = 42;   
  $scope.minRating = 40;
  $scope.maxRating = 50;
});

rn-stepper最简结构

<!-- lang: js -->
// we declare a module name for our projet, and its dependencies (none)
angular.module(‘revolunet.stepper‘, [])
// declare our naïve directive
.directive(‘rnStepper‘, function() {
  return {
    // can be used as attribute or element
    restrict: ‘AE‘,
    // which markup this directive generates
    template: ‘<button>-</button>‘ +
            ‘<div>0</div>‘ +
            ‘<button>+</button>‘
  };
});

现在directive rnStepper 已经有了一个简单的雏形了。

可以有如下两种试用方法:

<div rn-stepper> </div>
<rn-stepper> </rn-stepper>

demo: http://jsfiddle.net/revolunet/n4JHg/

添加内部动作

直接上代码:

<!-- lang: js -->
.directive(‘rnStepper‘, function() {
  return {
    restrict: ‘AE‘,

    // declare the directive scope as private (and empty)
    scope: {},

    // add behaviour to our buttons and use a variable value
    template:
        ‘<button ng-click="decrement()">-</button>‘ +
        ‘<div>{{value}}</div>‘ +
        ‘<button ng-click="increment()">+</button>‘,

    // this function is called on each rn-stepper instance initialisation
    // we just declare what we need in the above template
    link: function(scope, iElement, iAttrs) {
      scope.value = 0;
      scope.increment = function() {
        scope.value++;
      };
      scope.decrement = function() {
        scope.value--;
      };
    }
  };
});

我们在template中,分别给两个button添加了click事件响应,在link方法中实现了响应的方法。
这里的scope是一个private scope,其作用域仅限rnStepper这个directive。

demo: http://jsfiddle.net/revolunet/A92Aw/

与外部世界(外部作用域)的交互

直到上面为止,我们的rnStepper都是自己跟自己玩,并没有跟外部作用域进行一些交互。

下面我们将添加一个数据绑定,使rnStepper与外部世界建立联系。

直接上代码:

<!-- lang: js -->
scope: {
  value: ‘=ngModel‘
}

我们在scope中添加了一组键值对,这样,会自动建立内部变量value与外部属性ngModel的联系。
这里的=代表的意思是双向绑定(double data-binding)。

什么叫双向绑定?

即: 当value发生改变,那么ngModel也会发生改变,反之亦然。

在我们的这个demo中,看下面这行代码:

<!-- lang: js -->
<div rn-stepper ng-model="rating"></div>

这里的意思就是: directive rnStepper的内部变量value与外部scope中的rating建立了双向数据绑定。

demo: http://jsfiddle.net/revolunet/9e7Hy/

让我们组件更加友好

直接上代码:

<!-- lang: js -->
.directive(‘rnStepper‘, function() {
  return {
    // restrict and template attributes are the same as before.
    // we don‘t need anymore to bind the value to the external ngModel
    // as we require its controller and thus can access it directly
    scope: {},
    // the ‘require‘ property says we need a ngModel attribute in the declaration.
    // this require makes a 4th argument available in the link function below
    require: ‘ngModel‘,
    // the ngModelController attribute is an instance of an ngModelController
    // for our current ngModel.
    // if we had required multiple directives in the require attribute, this 4th
    // argument would give us an array of controllers.
    link: function(scope, iElement, iAttrs, ngModelController) {
      // we can now use our ngModelController builtin methods
      // that do the heavy-lifting for us

      // when model change, update our view (just update the div content)
      ngModelController.$render = function() {
        iElement.find(‘div‘).text(ngModelController.$viewValue);
      };

      // update the model then the view
      function updateModel(offset) {
        // call $parsers pipeline then update $modelValue
        ngModelController.$setViewValue(ngModelController.$viewValue + offset);
        // update the local view
        ngModelController.$render();
      }

      // update the value when user clicks the buttons
      scope.decrement = function() {
        updateModel(-1);
      };
      scope.increment = function() {
        updateModel(+1);
      };
    }
  };
});

这里,我不在需要内部变量value了。因为我们在link方法中已经拿到了ngModelController的引用,这里的ngModelController.$viewValue其实就是前面例子中的value。

但是我们又添加了另外一组键值对require: ‘ngModel‘。

我们使用了两个新的API:

ngModelController.$render: 在ngModel发生改变的时候框架自动调用,同步$modelValue和$viewValue, 即刷新页面。

ngModelController.$setViewValue: 当$viewValue发生改变时,通过此方法,同步更新$modelValue。
demo: http://jsfiddle.net/revolunet/s4gm6/

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
window.addeventjs事件驱动函数集合addEvent等
Feb 19 Javascript
javascript检测对象中是否存在某个属性判断方法小结
May 19 Javascript
js加载之使用DOM方法动态加载Javascript文件
Nov 08 Javascript
js判断滚动条是否已到页面最底部或顶部实例
Nov 20 Javascript
IE8中动态创建script标签onload无效的解决方法
Dec 22 Javascript
浅谈javascript中new操作符的原理
Jun 07 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
Aug 23 Javascript
微信小程序开发经验总结(推荐)
Jan 11 Javascript
bootstrap警告框示例代码分享
May 17 Javascript
JS仿QQ好友列表展开、收缩功能(第一篇)
Jul 07 Javascript
Angular项目从新建、打包到nginx部署全过程记录
Dec 09 Javascript
JavaScript的一些小技巧分享
Jan 06 Javascript
Boostrap实现的登录界面实例代码
Oct 09 #Javascript
深入理解bootstrap框架之第二章整体架构
Oct 09 #Javascript
javascript 判断是否是微信浏览器的方法
Oct 09 #Javascript
深入理解bootstrap框架之入门准备
Oct 09 #Javascript
微信小程序 http请求详细介绍
Oct 09 #Javascript
微信小程序 Flex布局详解
Oct 09 #Javascript
JavaScript实现Java中Map容器的方法
Oct 09 #Javascript
You might like
PHP 图片上传代码
2011/09/13 PHP
微信支付PHP SDK之微信公众号支付代码详解
2015/12/09 PHP
适合PHP初学者阅读的4本经典书籍
2016/09/23 PHP
如何判断php mysqli扩展类是否开启
2016/12/24 PHP
详谈symfony window下的安装 安装时候出现的问题以及解决方法
2017/09/28 PHP
php中对象引用和复制实例分析
2019/08/14 PHP
javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图
2013/01/09 Javascript
将json对象转换为字符串的方法
2014/02/20 Javascript
vue.js实现的经典计算器/科学计算器功能示例
2018/07/11 Javascript
深入理解Vue父子组件生命周期执行顺序及钩子函数
2018/08/12 Javascript
详解使用jest对vue项目进行单元测试
2018/09/07 Javascript
微信小程序分包加载代码实现方法详解
2019/09/23 Javascript
微信小程序自定义顶部组件customHeader的示例代码
2020/06/03 Javascript
[13:38]2015国际邀请赛中国战队出征仪式
2015/05/29 DOTA
[01:05:40]VG vs Newbee 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
Django的数据模型访问多对多键值的方法
2015/07/21 Python
在Python的Django框架的视图中使用Session的方法
2015/07/23 Python
Django框架实现的简单分页功能示例
2018/12/04 Python
在PyCharm导航区中打开多个Project的关闭方法
2019/01/17 Python
Django 内置权限扩展案例详解
2019/03/04 Python
python分别打包出32位和64位应用程序
2020/02/18 Python
python sklearn包——混淆矩阵、分类报告等自动生成方式
2020/02/28 Python
python用Tkinter做自己的中文代码编辑器
2020/09/07 Python
浅谈基于Canvas的手绘风格图形库Rough.js
2018/03/19 HTML / CSS
巴西最大的家电和百货零售商:Casas Bahia
2016/11/22 全球购物
固特异美国在线轮胎店:Goodyear Tire
2019/02/23 全球购物
乌克兰电子和家用电器商店:Foxtrot
2019/07/23 全球购物
美容院营销方案
2014/03/05 职场文书
副总经理党的群众路线教育实践活动个人对照检查材料思想汇报
2014/10/06 职场文书
党员个人年度总结
2015/02/14 职场文书
《珍珠鸟》教学反思
2016/02/16 职场文书
关于党风廉政建设宣传教育月的活动总结!
2019/08/08 职场文书
标会主持词应该怎么写?
2019/08/15 职场文书
MySQL中使用or、in与union all在查询命令下的效率对比
2021/05/26 MySQL
JavaScript高级程序设计之变量与作用域
2021/11/17 Javascript
JS前端轻量fabric.js系列物体基类
2022/08/05 Javascript