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 相关文章推荐
js类中获取外部函数名的方法
Aug 19 Javascript
摘自启点的main.js
Apr 20 Javascript
JQuery Tips(3) 关于$()包装集内元素的改变
Dec 14 Javascript
javascript查找字符串中出现最多的字符和次数的小例子
Oct 29 Javascript
文本域中换行符的替换示例
Mar 04 Javascript
使用Node.js实现HTTP 206内容分片的教程
Jun 23 Javascript
easyui取消表单实时验证,提交时统一验证的简单实例
Nov 07 Javascript
JS对象是否拥有某属性如何判断
Feb 03 Javascript
Bootstrap Tree View简单而优雅的树结构组件实例解析
Jun 15 Javascript
jQuery实现标签子元素的添加和赋值方法
Feb 24 jQuery
关于vue3.0中的this.$router.replace({ path: '/'})刷新无效果问题
Jan 16 Javascript
vue使用watch监听属性变化
Apr 30 Vue.js
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
提问的智慧(2)
2006/10/09 PHP
PHP数组游标实现对数组的各种操作详解
2016/01/26 PHP
彪哥1.1(智能表格)提供下载
2006/09/07 Javascript
JavaScript面向对象之静态与非静态类
2010/02/03 Javascript
JavaScript 高级篇之DOM文档,简单封装及调用、动态添加、删除样式(六)
2012/04/07 Javascript
jQuery 获取兄弟元素的几种不错方法
2014/05/23 Javascript
Node.js中对通用模块的封装方法
2014/06/06 Javascript
Jquery $.getJSON 在IE下的缓存问题解决方法
2014/10/10 Javascript
js时间日期格式化封装函数
2014/12/02 Javascript
BootstrapTable与KnockoutJS相结合实现增删改查功能【一】
2016/05/10 Javascript
jQuery中的select操作详解
2016/11/29 Javascript
轻松理解Javascript变量的相关问题
2017/01/20 Javascript
canvas实现粒子时钟效果
2017/02/06 Javascript
微信小程序之批量上传并压缩图片的实例代码
2018/07/05 Javascript
vue-cli安装使用流程步骤详解
2018/11/08 Javascript
JS选取DOM元素常见操作方法实例分析
2018/12/10 Javascript
Javascript的this详解
2019/03/23 Javascript
Openlayers实现测量功能
2020/09/25 Javascript
[19:26]TNC vs EG (BO3)
2018/06/07 DOTA
[16:01]夜魇凡尔赛茶话会 第二期01:你比划我猜
2021/03/11 DOTA
python使用PyGame模块播放声音的方法
2015/05/20 Python
Python用Pillow(PIL)进行简单的图像操作方法
2017/07/07 Python
python如何重载模块实例解析
2018/01/25 Python
python pandas中DataFrame类型数据操作函数的方法
2018/04/08 Python
使用pandas中的DataFrame数据绘制柱状图的方法
2018/04/10 Python
python3.X 抓取火车票信息【修正版】
2018/06/19 Python
python logging 日志的级别调整方式
2020/02/21 Python
python GUI库图形界面开发之PyQt5输入对话框QInputDialog详细使用方法与实例
2020/02/27 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
英国领先的杂志订阅网站:Magazine.co.uk
2018/01/25 全球购物
意大利巧克力店:Chocolate Shop
2019/07/24 全球购物
水果连锁超市创业计划书
2014/01/24 职场文书
消防安全宣传口号
2014/06/10 职场文书
法制教育演讲稿
2014/09/10 职场文书
党干部专题民主生活会对照检查材料思想汇报
2014/10/06 职场文书
自主招生专家推荐信
2015/03/26 职场文书