zoukankan      html  css  js  c++  java
  • [译]angularjs directive design made easy

    原文: http://seanhess.github.io/2013/10/14/angularjs-directive-design.html

    AngularJS directives很酷

    AngularJS一个非常好的特色就是可以创建directives, 或者说是可重复利用的web components. 用了directive你可以创建新的HTML标签和属性. 

    Directive设计原则

    如果你想展示一个user列表, 你可以创建一个directive,这个directive读取$scope.users,并且打印出来:

    <user-list/>

    和ng-repeat比较, ng-repeat只处理重复. user-list和ng-repeat哪一个可以在多个地方使用呢? 如果你需要在两处不同的地方以不同的形式展示user列表呢?

    一个好的directive只做一件事情

    ng-repeat比user-list好, 因为它只做一件事情: 它只重复部件, 所以你可以在很多环境下重用他.不要让一个directive去处理所有的事情.

    一个好的directive不是为某一个应用特定的

    通常来说如果你的directive可以在一个完全不同的应用中使用,那么你这个指令应该设计得不错.

    如果展示bindings

    第一个要学的是directive如何处理binding: 使用一对花括号. 例如, 写一个directive展示一张照片和一段说明.

    directive设计的第一步就是选择一个好的属性的名字. 我用photo-src表示image的src, caption作为文本. 小心不要使用其他directive使用过的名字, 比如ng-src 除非你了解他们是怎么工作的.

    第二步, 决定支持attributes、classname或element. 在这个例子中我们使用phone作为一个element.

    <photo photo-src="{{photo.url}}" caption="Taken on: {{photo.date}}"/>
    

    注意到了没, 我并没有把整个photo对象给到这个directive. 这是一个好的设计, 这样这个directive可以和不同的数据结构数据对象一起工作.

    使用 attrs.$observe读取binding. 当binding改变后它会调用你的callback. 

    app.directive('photo', function() {
        return {
            // 指定作为element使用
            restrict: 'E',
    
            // 用下面的html替代<photo>
            template: '<figure><img/><figcaption/></figure>',
            replace: true,
    
            // 观察、操作DOM
            link: function($scope, element, attrs) {
                attrs.$observe('caption', function(value) {
                    element.find('figcaption').text(value)
                })
    
                // 属性名camel case
                attrs.$observe('photoSrc', function(value) {
                    element.find('img').attr('src', value)
                })
            }
        }
    }
    })
    

    如果你的component有自己的template, 你可以在一个isolate scope中处理上面所有的attrs.$observe.

    app.directive('photo', function() {
        return {
            restrict: 'E',
            templateUrl: 'photo.html',
            replace: true,
            // pass these two names from attrs into the template scope
            scope: {
                caption: '@',
                photoSrc: '@'
            }
        }
    })
    

      

    <!-- photo.html -->
    <figure>
        <img ng-src="{{photoSrc}}"/>
        <figcaption>{{caption}}</figcaption>
    </figure>
    

    如何读写数据

    有些directive需要写数据, 比如ng-model.

    现在写一个button toggle指令. 这个指令根据scope上面的一些布尔值设置toggle状态, 当被点击这个值发生改变.

    这里不使用大括号,而是使用表达式.

    <!-- 这里不使用大括号no double curly braces here -->
    <button toggle="preferences.showDetails">Show Details</button>
    

    首先我们在scope:里面使用= 这个设置是为了使得可以在我们的directive中使用scope.toggle.

    app.directive('toggle', function() {
        return {
            scope: {
                toggle: '=',
            },
            link: function($scope, element, attrs) {
    

    下一步我们使用scope.$watch, 当expression改变的时候调用callback. 当toggle改变的时候我们会添加或者删除active类.

    $scope.$watch("toggle", function(value) {
                    element.toggleClass('active', value) 
                })
    

    最后, 监听jQuery click事件,更新scope. 我们需要使用$scope.$apply 相应改变. 

    element.click(function() {
                    $scope.$apply(function() {
                        $scope.toggle = !$scope.toggle
                    })
                })
            }
        }
    })
    

    Demo

    如何暴露events

    有时你想让一个controller响应一个directive里面的事件, 比如ng-click. 创建一个scroll directive, 当用户scroll一个element的使用会调用一个function.

    <textarea scroll="onScroll(offset)">...</textarea>
    

    类似于toggle button, 我们映射scroll属性中的function到我们指令的scope.

    app.directive('scroll', function() {
        return {
            scope: {
                scroll: "&"
            },
            link: function($scope, element, attrs) {
    

    我们依然使用scope.$apply

    element.scroll(function() {
                    $scope.apply(function() {
                        var offset = element.scrollTop()
                        $scope.scroll({offset:offset})
                    })
                })
            }
        }
    })

    Demo

    如何包含HTML内容

    Directive默认可以有html内容.

    写一个modal组件: 一个有关闭按钮的弹出窗口

    <modal>
      <p>Some contents</p>
      <p>Put whatever you want in here</p>
    </modal>
    

    modal不止一个元素. 我们写一个template html, 我们在一个div中使用了一个特别的ng-transclude指令 他用来获取得到modal中的html内容.

    <div class="modal">
        <header>
            <button>Close</button>
            <h2>Modal</h2>
        </header>
        <div class="body" ng-transclude></div>
    </div>
    

    注意要设置 transclude: true:

    app.directive('modal', function() {
        return {
            restrict: 'E',
            templateUrl: 'modal.html',
            replace: true,
            transclude: true,
        }
    })
  • 相关阅读:
    写在开篇——过往总结
    线程池原理实现
    MD5加密工具类
    跨域及jsonp
    四种xml的解析方式
    浅析正则表达式—(原理篇)
    用JavaScript添加选择按钮的背景颜色和juqery添加选择按钮的背景色
    怎么用JavaScript实现tab切换
    vue.js2.0:如何搭建开发环境及构建项目
    vscode如何用浏览器预览运行html文件
  • 原文地址:https://www.cnblogs.com/irocker/p/angularjs-directive-design.html
Copyright © 2011-2022 走看看