Note07--指令

1. 目录结构:

这里写图片描述
这里写图片描述

2. Restrict:匹配模式
    a. 四个选项:AEMC

这里写图片描述

        i. A:attribute
        ii. E:element
        iii. M:comment
            1) 书写时,两端需要加空格;
            2) e.g. <!-- directive:hello -->
        iv. C:class

这里写图片描述

    b. 推荐使用AE模式,少用CM方式,因为CM会引起混淆或者麻烦;

这里写图片描述

3. Templatecache
    a. 当元素被多次重复使用时,使用templatecache缓存元素

这里写图片描述

    b. $templateCache.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <hello></hello>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="$templateCache.js"></script>
</html>
    c. $templateCache.js
var myModule = angular.module("MyModule", []);

//注射器加载完所有模块时,此方法执行一次
myModule.run(function($templateCache){
    $templateCache.put("hello.html","<div>Hello everyone!!!!!!</div>");
});

myModule.directive("hello", function($templateCache) {
    return {
        restrict: 'AECM',
        template: $templateCache.get("hello.html"),
        replace: true
    }
});
4. Replace:替换指令标签,同时也替换掉子元素
    a. Replace.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <hello>
            <div>这里是指令内部的内容。</div>
        </hello>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="replace.js"></script>
</html>
    b. Replace.js
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
    return {
        restrict:"AE",
        template:"<div>Hello everyone!</div>",
        replace:true
    } 
});
5. Transclude:子元素不替换;非常重要!
    a. Transclude.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <hello>
            <div>这里是指令内部的内容。</div>
        </hello>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="transclude.js"></script>
</html>
    b. Transclude.js
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
    return {
        restrict:"AE",
        transclude:true,
        template:"<div>Hello everyone!<div ng-transclude></div></div>"
    } 
});
6. 指令执行机制:compile与link
    a. Ng-app只能出现一次;
    b. 编写指令是可以自定义compile,一般不会自定义compile;
        i. 自定义compile,需要调用默认的compile,否则,默认的compile的行为就会被覆盖掉;
    c. link:一般用来操作DOM、绑定事件监听器;

这里写图片描述

7. 指令与控制器之间的交互
    a. 通过自定义属性,然后调用scope.$apply() 方法
    b. Directive&Controller.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div ng-controller="MyCtrl">
            <loader howToLoad="loadData()">滑动加载</loader>
        </div>
        <div ng-controller="MyCtrl2">
            <loader howToLoad="loadData2()">滑动加载</loader>
        </div>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="Directive&Controller.js"></script>
</html>
    c. Directive&Controller.js
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
    $scope.loadData=function(){
        console.log("加载数据中...");
    }
}]);
myModule.controller('MyCtrl2', ['$scope', function($scope){
    $scope.loadData2=function(){
        console.log("加载数据中...22222");
    }
}]);
myModule.directive("loader", function() {
    return {
        restrict:"AE",
        link:function(scope,element,attrs){
            element.bind('mouseenter', function(event) {
                //scope.loadData();
                // scope.$apply("loadData()");
                // 注意这里的坑,howToLoad会被转换成小写的howtoload
                scope.$apply(attrs.howtoload);
            });
        }
    } 
});
8. 指令之间的交互
    a. Directive&Directive.html
<!doctype html>
<html ng-app="MyModule">

<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="Directive&Directive.js"></script>
</head>

<body>
    <div class="row">
        <div class="col-md-3">
            <superman strength>动感超人---力量</superman>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3">
            <superman strength speed>动感超人2---力量+敏捷</superman>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3">
            <superman strength speed light>动感超人3---力量+敏捷+发光</superman>
        </div>
    </div>
</body>

</html>
    b. Directive&Directive.js
var myModule = angular.module("MyModule", []);
myModule.directive("superman", function() {
    return {
        scope: {},
        restrict: 'AE',
        // 指令内部的controller,和外部的controller有区别
        controller: function($scope) {
            $scope.abilities = [];
            this.addStrength = function() {
                $scope.abilities.push("strength");
            };
            this.addSpeed = function() {
                $scope.abilities.push("speed");
            };
            this.addLight = function() {
                $scope.abilities.push("light");
            };
        },
        link: function(scope, element, attrs) {
            element.addClass('btn btn-primary');
            element.bind("mouseenter", function() {
                console.log(scope.abilities);
            });
        }
    }
});
myModule.directive("strength", function() {
    return {
        require: '^superman',
        link: function(scope, element, attrs, supermanCtrl) {
            supermanCtrl.addStrength();
        }
    }
});
myModule.directive("speed", function() {
    return {
        require: '^superman',
        link: function(scope, element, attrs, supermanCtrl) {
            supermanCtrl.addSpeed();
        }
    }
});
myModule.directive("light", function() {
    return {
        require: '^superman',
        link: function(scope, element, attrs, supermanCtrl) {
            supermanCtrl.addLight();
        }
    }
});
    c. directive中的require表示依赖与Superman指令,写了require之后,link函数就可以写第四个参数superctrl。angularJS执行时,会把SupermanCtrl注入到当前指令中,之后就可以调用Superman暴露出来的方法;(superCtrl是形参,参数名无所谓)
    d. 逻辑代码什么时候写在指令内部controller里面?什么时候写在link里面?
        i. 如果想让指令暴露一些方法给外部调用,则写在controller里面;
        ii. link用来处理指令内部的一些事务,比如事件,绑定数据等;
9. 独立scope
    a. 为指令添加scope即可实现;
    b. e.g.
        i. isolateScope.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
    </head>
    <body>
        <hello></hello>
        <hello></hello>
        <hello></hello>
        <hello></hello>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="IsolateScope.js"></script>
</html>
        ii. isolateScope.js
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
    return {
        restrict: 'AE',
        scope:{},
        template: '<div><input type="text" ng-model="userName"/>{{userName}}</div>',
        replace: true
    }
});
    c. 绑定策略

这里写图片描述

    d. @方式:传递的是字符串,不是对象
        i. ScopeAt.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
    </head>
    <body>
        <div ng-controller="MyCtrl">
            <drink flavor="{{ctrlFlavor}}"></drink>
        </div>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="ScopeAt.js"></script>
</html>
        ii. ScopeAt.js
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
    $scope.ctrlFlavor="百威";
}])
myModule.directive("drink", function() {
    return {
        restrict:'AE',
        scope:{
            flavor:'@'
        },
        template:"<div>{{flavor}}</div>"
        // ,
        // link:function(scope,element,attrs){
        //  scope.flavor=attrs.flavor;
        // }
    }
});
        通过定义scope就可以避免定义link函数;
    e. =方式:双向绑定
        i. e.g.
            1) ScopeEquals.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
    </head>
    <body>
        <div ng-controller="MyCtrl">
            Ctrl:
            <br>
            <input type="text" ng-model="ctrlFlavor">
            <br>
            Directive:
            <br>
            <drink flavor="ctrlFlavor"></drink>
        </div>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="ScopeEqual.js"></script>
</html>
            2) ScopeEquals.js
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
    $scope.ctrlFlavor="百威";
}])
myModule.directive("drink", function() {
    return {
        restrict:'AE',
        scope:{
            flavor:'='
        },
        template:'<input type="text" ng-model="flavor"/>'
    }
});
    f. &方式:传递一个父scope的函数
        i. e.g.
            1) ScopeAnd.html
<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
    </head>
    <body>
        <div ng-controller="MyCtrl">
            <greeting greet="sayHello(name)"></greeting>
            <greeting greet="sayHello(name)"></greeting>
            <greeting greet="sayHello(name)"></greeting>
        </div>
    </body>
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="ScopeAnd.js"></script>
</html>
            2) ScopeAnd.js
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
    $scope.sayHello=function(name){
        alert("Hello "+name);
    }
}])
myModule.directive("greeting", function() {
    return {
        restrict:'AE',
        scope:{
            greet:'&'
        },
        template:'<input type="text" ng-model="userName" /><br/>'+
                 '<button class="btn btn-default" ng-click="greet({name:userName})">Greeting</button><br/>'
    }
});
10. AngularJS内置指令
    a. form表单

这里写图片描述

        i. e.g.
            1) formAdv1.html
<!doctype html>
<html ng-app>
    <head>
        <script src="framework/angular-1.3.0.14/angular.js"></script>
        <script src="FormAdv1.js"></script>
    </head>
    <body>
        <div ng-controller="Controller">
            <form name="form" class="css-form" novalidate>
                Name:
                <input type="text" ng-model="user.name" name="uName" required /><br/>
                E-mail:
                <input type="email" ng-model="user.email" name="uEmail" required /><br/>
                <div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">
                    Invalid:
                    <span ng-show="form.uEmail.$error.required">Tell us your email.</span>
                    <span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
                </div>
                Gender:<br/>
                <input type="radio" ng-model="user.gender" value="male" />
                male
                <input type="radio" ng-model="user.gender" value="female" />
                female<br/>
                <input type="checkbox" ng-model="user.agree" name="userAgree" required />
                I agree:
                <input ng-show="user.agree" type="text" ng-model="user.agreeSign" required />
                <div ng-show="!user.agree || !user.agreeSign">
                    Please agree and sign.
                </div>
                <br/>
                <button ng-click="reset()" ng-disabled="isUnchanged(user)">
                    RESET
                </button>
                <button ng-click="update(user)" ng-disabled="form.$invalid || isUnchanged(user)">
                    SAVE
                </button>
            </form>
        </div>
    </body>
</html>
            2) FormAdv1.js
function Controller($scope) {
    $scope.master = {};

    $scope.update = function(user) {
        $scope.master = angular.copy(user);
    };

    $scope.reset = function() {
        $scope.user = angular.copy($scope.master);
    };

    $scope.isUnchanged = function(user) {
        return angular.equals(user, $scope.master);
    };

    $scope.reset();
}
        ii. 自定义输入项
            1) 避免一些不可预见的行为
            2) e.g.
                a) FormCustom.html
<!doctype html>
<html ng-app="form-example2">
    <head>
        <link href="../bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
        <script src="framework/angular-1.3.0.14/angular.js"></script>
        <script src="FormCustom.js"></script>
        <style type="text/css">
            div[contentEditable] {
                cursor: pointer;
                background-color: #D0D0D0;
            }
        </style>
    </head>
    <body>
        <div>
            <div contentEditable="true" ng-model="content" title="Click to edit">Some</div>
            <pre>model = {{content}}</pre>
        </div>
    </body>
</html>
                b) FormCustom.js
angular.module('form-example2', []).directive('contenteditable', function() {
    return {
        require : 'ngModel',
        link : function(scope, elm, attrs, ctrl) {
            // view -> model
            elm.bind('keyup', function() {
                scope.$apply(function() {
                    ctrl.$setViewValue(elm.text());
                });
            });

            // model -> view
            ctrl.$render = function() {
                elm.html(ctrl.$viewValue);
            };

            // load init value from DOM
            ctrl.$setViewValue(elm.html());
        }
    };
});
    b. 各种事件:ngBlur; ngClick;等等
11. 自定义指令
    a. e.g. 点击展开或者消失
        i. ExpandSimple.html
<html ng-app='expanderModule'>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <link rel="stylesheet" type="text/css" href="ExpanderSimple.css"/>
        <script src="framework/angular-1.3.0.14/angular.js"></script>
        <script src="ExpanderSimple.js"></script>
    </head>
    <body>
        <div ng-controller='SomeController'>
            <expander class='expander' expander-title='title'>
                {{text}}
            </expander>
        </div>
    </body>
</html>
        ii. ExpandSimple.js
var expanderModule=angular.module('expanderModule', []);
expanderModule.directive('expander', function() {
    return {
        restrict : 'EA',
        replace : true,
        transclude : true,
        scope : {
            title : '=expanderTitle'
        },
        template : '<div>'
                 + '<div class="title" ng-click="toggle()">{{title}}</div>'
                 + '<div class="body" ng-show="showMe" ng-transclude></div>'
                 + '</div>',
        link : function(scope, element, attrs) {
            scope.showMe = false;
            scope.toggle = function() {
                scope.showMe = !scope.showMe;
            }
        }
    }
});
expanderModule.controller('SomeController',function($scope) {
    $scope.title = '点击展开';
    $scope.text = '这里是内部的内容。';
});
        iii. ExpandSimple.css
.expander {
border: 1px solid black;
    width: 250px;
}

.expander>.title {
    background-color: black;
    color: white;
    padding: .1em .3em;
    cursor: pointer;
}

.expander>.body {
    padding: .1em .3em;
}
    b. e.g. 显示多个元素内容
        i. Accordion.html
<html ng-app="expanderModule">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <link rel="stylesheet" type="text/css" href="Accordion.css"/>
        <script src="framework/angular-1.3.0.14/angular.js"></script>
        <script src="Accordion.js"></script>
    </head>
    <body ng-controller='SomeController' >
        <accordion>
            <expander class='expander' ng-repeat='expander in expanders' expander-title='expander.title'>
                {{expander.text}}
            </expander>
        </accordion>
    </body>
</html>
        ii. Accordion.js
var expModule=angular.module('expanderModule',[])
expModule.directive('accordion', function() {
    return {
        restrict : 'EA',
        replace : true,
        transclude : true,
        template : '<div ng-transclude></div>',
        controller : function() {
            var expanders = [];
            this.gotOpened = function(selectedExpander) {
                angular.forEach(expanders, function(expander) {
                    if (selectedExpander != expander) {
                        expander.showMe = false;
                    }
                });
            }
            this.addExpander = function(expander) {
                expanders.push(expander);
            }
        }
    }
});

expModule.directive('expander', function() {
    return {
        restrict : 'EA',
        replace : true,
        transclude : true,
        require : '^?accordion',
        scope : {
            title : '=expanderTitle'
        },
        template : '<div>'
                  + '<div class="title" ng-click="toggle()">{{title}}</div>'
                  + '<div class="body" ng-show="showMe" ng-transclude></div>'
                  + '</div>',
        link : function(scope, element, attrs, accordionController) {
            scope.showMe = false;
            accordionController.addExpander(scope);
            scope.toggle = function toggle() {
                scope.showMe = !scope.showMe;
                accordionController.gotOpened(scope);
            }
        }
    }
});

expModule.controller("SomeController",function($scope) {
    $scope.expanders = [{
        title : 'Click me to expand',
        text : 'Hi there folks, I am the content that was hidden but is now shown.'
    }, {
        title : 'Click this',
        text : 'I am even better text than you have seen previously'
    }, {
        title : 'Test',
        text : 'test'
    }];
});
    c. E.g. 使用第三方指令库:angularUI
        i. Accordion-ngui.html
<!doctype html>
<html ng-app="MyModule">

<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="framework/bootstrap-3.0.0/css/bootstrap.css">
    <link rel="stylesheet" href="common.css">
    <script src="framework/angular-1.3.0.14/angular.js"></script>
    <script src="framework/ui-bootstrap-tpls-0.11.0.js"></script>
    <script src="Accordion-ngui.js"></script>
</head>

<body>
    <div class="container">
        <div class="row">
            <div class="col-md-12">
                <div ng-controller="AccordionDemoCtrl">
                    <p>
                        <button class="btn btn-default btn-md" ng-click="status.open = !status.open">Toggle last panel</button>
                        <button class="btn btn-default btn-md" ng-click="status.isFirstDisabled = ! status.isFirstDisabled">Enable / Disable first panel</button>
                    </p>

                    <label class="checkbox">
                        <input type="checkbox" ng-model="oneAtATime">Open only one at a time
                    </label>
                    <accordion close-others="oneAtATime">
                        <accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
                            This content is straight in the template.
                        </accordion-group>
                        <accordion-group heading="{{group.title}}" ng-repeat="group in groups">
                            {{group.content}}
                        </accordion-group>
                        <accordion-group heading="Dynamic Body Content">
                            <p>The body of the accordion group grows to fit the contents</p>
                            <button class="btn btn-default btn-md" ng-click="addItem()">Add Item</button>
                            <div ng-repeat="item in items">{{item}}</div>
                        </accordion-group>
                        <accordion-group is-open="status.open">
                            <accordion-heading>
                                I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
                            </accordion-heading>
                            This is just some content to illustrate fancy headings.
                        </accordion-group>
                    </accordion>
                </div>

            </div>
        </div>
    </div>

</body>

</html>
        ii. Accordion-ngui.js
var myModule = angular.module('MyModule', ['ui.bootstrap']);
myModule.controller('AccordionDemoCtrl', ['$scope',
    function($scope) {

        $scope.oneAtATime = true;

        $scope.groups = [{
            title: 'Dynamic Group Header - 1',
            content: 'Dynamic Group Body - 1'
        }, {
            title: 'Dynamic Group Header - 2',
            content: 'Dynamic Group Body - 2'
        }];

        $scope.items = ['Item 1', 'Item 2', 'Item 3'];

        $scope.addItem = function() {
            var newItemNo = $scope.items.length + 1;
            $scope.items.push('Item ' + newItemNo);
        };

        $scope.status = {
            isFirstOpen: true,
            isFirstDisabled: false
        };
    }
])
12. 常见系统的UI
    a. ERP类型系统:

这里写图片描述
这里写图片描述
i. http://miniui.com
b. 互联网/电商型系统必备UI组件
i. https://github.com/kissygalleryteam
ii. Angular-UI
iii. www.ngnice.com/showcase/
13. Directive设计思想来源于FLEX

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值