AngularJS Dropdown指令相关的总结

Dropdown组件

自己封装的一个简单的dropdown的组件

.ui-dropdown {
    position:relative;
    display:inline-block;
    *display:inline;
    *zoom:1;
    width:162px;
    border-radius:3px;
    text-align:left;
    font:12px/28px tahoma,arial,Hiragino Sans GB,WenQuanYi Micro Hei,'\5FAE\8F6F\96C5\9ED1','\5B8B\4F53',sans-serif;
    vertical-align:top
}
.ui-dropdown-bd {
    display:none;
    top:31px;
    left:0;
    min-width:calc(100% - 2px);
    max-height:346px;
    overflow-y:auto;
    overflow-x:hidden;
    _overflow:auto;
    position:absolute;
    padding-bottom:8px;
    background-color:#fff;
    border:1px solid #848484;
    border-radius:0 0 3px 3px;
    -webkit-box-shadow:0 0 0 2px #f7f7f7;
    box-shadow:0 0 0 2px #f7f7f7
}
.ui-dropdown-bd-right {
    left:auto;
    right:0
}
.ui-dropdown-bd .selected a,.ui-dropdown-bd .selected a:hover,.ui-dropdown-bd .selected a:active {
    background-color:#f10180;
    color:#fff
}
.ui-dropdown-bd a {
    display:block;
    padding:0 10px;
    text-overflow:ellipsis;
    white-space:nowrap;
    overflow:hidden;
    color:#333;
    text-decoration:none;
    *zoom:1
}
.ui-dropdown-bd a:hover {
    color:#666;
    text-decoration:none;
    background-color:#ededed
}
.ui-dropdown-bd a:active {
    background-color:#f10180;
    color:#fff
}
.ui-dropdown-hd {
    position:relative;
    z-index:2;
    padding:0 10px;
    border:1px solid #b3b3b3;
    border-radius:3px;
    background-color:#fff;
    -webkit-user-select:none;
    -moz-user-select:none;
    -ms-user-select:none;
    user-select:none;
    cursor:pointer;
    *zoom:1
}
.ui-dropdown-hd:hover {
    border-color:#949494
}
.ui-dropdown-hd:hover .vipFont {
    color:#949494
}
.ui-dropdown-hd .vipFont {
    position:absolute;
    right:7px;
    color:#b3b3b3;
    -webkit-transition:-webkit-transform .2s;
    transition:transform .2s;
    line-height:1
}
.ui-dropdown-hd .i-arrow-down {
    top:7px
}
.ui-dropdown-hd .i-arrow-up {
    visibility:hidden;
    -webkit-transform:rotate(-180deg);
    -ms-transform:rotate(-180deg);
    transform:rotate(-180deg);
    top:6px
}
.ui-dropdown-current {
    display:block;
    zoom:1;
    color:#999;
    line-height:30px;
    text-decoration:none;
    font-size:14px;
    margin-right:10px;
    text-overflow:ellipsis;
    white-space:nowrap;
    overflow:hidden
}
.ui-dropdown-current:hover {
    color:#999;
    text-decoration:none
}
.ui-dropdown-tips {
    padding:12px 0 4px 10px;
    line-height:20px;
    color:#ed1616
}
.ui-dropdown .ui-dropdown-menu .ui-dropdown-loading {
    float:none;
    width:auto;
    padding-top:10px;
    line-height:80px;
    text-align:center;
    font-size:14px;
    color:#333
}
.ui-dropdown .ui-dropdown-menu .ui-dropdown-loading .ii-loading-pink-16x16,.ui-dropdown .ui-dropdown-menu .ui-dropdown-loading .ii-loading-pink-24x24,.ui-dropdown .ui-dropdown-menu .ui-dropdown-loading .ii-loading-pink-32x32 {
    vertical-align:middle;
    margin-right:12px
}
.ui-dropdown .ui-dropdown-menu .ui-dropdown-loading .text {
    display:inline-block;
    vertical-align:middle
}
.ui-dropdown-col-2,.ui-dropdown-col-3,.ui-dropdown-col-4 {
    width:115px
}
.z-ui-dropdown-open .ui-dropdown-col-2 .ui-dropdown-hd,.z-ui-dropdown-open .ui-dropdown-col-3 .ui-dropdown-hd,.z-ui-dropdown-open .ui-dropdown-col-4 .ui-dropdown-hd {
    border-bottom:0;
    padding-bottom:1px
}
.ui-dropdown-col-2 .ui-dropdown-bd,.ui-dropdown-col-3 .ui-dropdown-bd,.ui-dropdown-col-4 .ui-dropdown-bd {
    padding-top:8px
}
.ui-dropdown-col-2 .ui-dropdown-tips,.ui-dropdown-col-3 .ui-dropdown-tips,.ui-dropdown-col-4 .ui-dropdown-tips {
    padding-top:0
}
.ui-dropdown-col-2 .ui-dropdown-menu,.ui-dropdown-col-3 .ui-dropdown-menu,.ui-dropdown-col-4 .ui-dropdown-menu {
    padding:0 5px
}
.ui-dropdown-col-2 .ui-dropdown-menu li,.ui-dropdown-col-3 .ui-dropdown-menu li,.ui-dropdown-col-4 .ui-dropdown-menu li {
    float:left;
    _overflow:hidden
}
.ui-dropdown-col-2 .ui-dropdown-menu li a,.ui-dropdown-col-3 .ui-dropdown-menu li a,.ui-dropdown-col-4 .ui-dropdown-menu li a {
    _width:83px;
    padding:0 0 0 5px;
    margin:0 5px 2px
}
.ui-dropdown-col-2 .ui-dropdown-bd {
    width:190px
}
.ui-dropdown-col-2 .ui-dropdown-menu li {
    width:50%
}
.ui-dropdown-col-3 .ui-dropdown-bd {
    width:280px
}
.ui-dropdown-col-3 .ui-dropdown-menu li {
    width:33%
}
.ui-dropdown-col-4 .ui-dropdown-bd {
    width:370px
}
.ui-dropdown-col-4 .ui-dropdown-menu li {
    width:25%
}
.ui-dropdown-float {
    line-height:26px;
    width:120px
}
.ui-dropdown-float:hover,.ui-dropdown-float-hover {
    z-index:100
}
.ui-dropdown-float:hover .ui-dropdown-hd .vipFont,.ui-dropdown-float-hover .ui-dropdown-hd .vipFont {
    color:#848484;
    line-height:1
}
.ui-dropdown-float:hover .ui-dropdown-hd .i-arrow-up,.ui-dropdown-float-hover .ui-dropdown-hd .i-arrow-up {
    visibility:visible;
    -webkit-transform:rotate(0deg);
    -ms-transform:rotate(0deg);
    transform:rotate(0deg)
}
.ui-dropdown-float:hover .ui-dropdown-hd .i-arrow-down,.ui-dropdown-float-hover .ui-dropdown-hd .i-arrow-down {
    visibility:hidden;
    -webkit-transform:rotate(180deg);
    -ms-transform:rotate(180deg);
    transform:rotate(180deg)
}
.ui-dropdown-float:hover .ui-dropdown-bd,.ui-dropdown-float-hover .ui-dropdown-bd {
    display:block
}
.ui-dropdown-float:hover .ui-dropdown-current,.ui-dropdown-float-hover .ui-dropdown-current {
    color:#333
}
.ui-dropdown-float .ui-dropdown-current {
    display:inline-block;
    padding-right:16px;
    margin-right:0;
    color:#666;
    font-size:12px
}
.ui-dropdown-float .ui-dropdown-current:hover {
    color:#333
}
.ui-dropdown-float .ui-dropdown-hd {
    border:0 none;
    background:0
}
.ui-dropdown-float .ui-dropdown-hd .vipFont {
    right:auto;
    margin-left:-16px
}
.ui-dropdown-float .ui-dropdown-bd {
    top:0;
    max-height:312px;
    padding-top:30px;
    border-radius:0;
    border-color:#cbcaca
}
.ui-dropdown-float .ui-dropdown-bd a {
    color:#666
}
.ui-dropdown-float .ui-dropdown-bd a:hover,.ui-dropdown-float .ui-dropdown-bd a:active {
    background:0;
    color:#f10180
}
.ui-dropdown-float .ui-dropdown-bd .selected a,.ui-dropdown-float .ui-dropdown-bd .selected a:hover,.ui-dropdown-float .ui-dropdown-bd .selected a:active {
    background:0;
    color:#f10180
}
.ui-dropdown-float .ui-dropdown-menu .ui-dropdown-loading {
    line-height:50px;
    font-size:12px
}
.z-ui-dropdown-selected .ui-dropdown-current,.z-ui-dropdown-selected .ui-dropdown-current:hover {
    color:#333
}
.z-ui-dropdown-disable .ui-dropdown-hd {
    background-color:#f0efef;
    color:#999;
    cursor:not-allowed
}
.z-ui-dropdown-disable .ui-dropdown-hd:hover .vipFont {
    color:#b3b3b3
}
.z-ui-dropdown-disable .ui-dropdown-current,.z-ui-dropdown-disable .ui-dropdown-current:hover {
    color:#999;
    cursor:not-allowed
}
.z-ui-dropdown-open {
    z-index:100;
    -webkit-box-shadow:0 0 0 2px rgba(153,153,153,.08);
    box-shadow:0 0 0 2px rgba(153,153,153,.08)
}
.z-ui-dropdown-open .ui-dropdown-hd {
    border-radius:3px 3px 0 0;
    border-color:#848484;
    border-bottom-color:#dcdada
}
.z-ui-dropdown-open .ui-dropdown-hd .vipFont {
    color:#848484
}
.z-ui-dropdown-open .ui-dropdown-hd .i-arrow-up {
    visibility:visible;
    -webkit-transform:rotate(0deg);
    -ms-transform:rotate(0deg);
    transform:rotate(0deg)
}
.z-ui-dropdown-open .ui-dropdown-hd .i-arrow-down {
    visibility:hidden;
    -webkit-transform:rotate(180deg);
    -ms-transform:rotate(180deg);
    transform:rotate(180deg)
}
.z-ui-dropdown-open .ui-dropdown-bd {
    display:block
}
function BindDropdownEvent(elements, callback) {

    $('.ui-dropdown-hd', elements).unbind().click(function() {

        var element = $(this),
            uiDropdown = element.parent('.ui-dropdown');
        if (element.hasClass('z-ui-dropdown-disable')) {
            return false;
        }

        if (uiDropdown.hasClass('z-ui-dropdown-open')) {
            uiDropdown.removeClass('z-ui-dropdown-open');
        } else {
            $('.ui-dropdown').not(uiDropdown).removeClass('z-ui-dropdown-open');
            $('.multi-dropdown').not(uiDropdown).removeClass('z-ui-dropdown-open');
            uiDropdown.addClass('z-ui-dropdown-open');
            $(document).one('click', function() {
                uiDropdown.removeClass('z-ui-dropdown-open');
                return false;
            });
        }
        return false;
    });

    $('.ui-dropdown-bd', elements).unbind().each(function() {
        var element = $(this),
            uiDropdown = element.parent('.ui-dropdown'),
            liList = element.find('li'),
            uiDropdownCurrent = uiDropdown.find('.ui-dropdown-current');
        liList.click(function() {
            var subElement = $(this),
                item = subElement.find('a');
            liList.removeClass('selected');
            subElement.addClass('selected');

            var selectValue = item.attr('value');
            uiDropdownCurrent.attr('value', selectValue).text(item.text());
            uiDropdown.removeClass('z-ui-dropdown-open');
            $.isFunction(callback) && callback(item.text(), selectValue);

        });
    });
}

/**
     * Dropdown单选下拉框指令的实现
     * name : 区分不同的下拉框组件,字符串形式
     * ngModel : 单选下拉框绑定的值,默认是选中项的key值
     * dataList : 下拉框下拉选项列表,数组形式,数组元素对象包含key 以及value。key作为向后台交互的值,value作为前端控件显示的值
     * empty : 布尔属性值,当赋值为true的时候,对下拉框组件进行充值,下拉框中的值显示的是placeholder的值"请选择"
     * TODO : 多层级联下拉框的实现方法      ------     当下拉框列表接受点击事件时,广播带有组件name值为参数的selectUpdate的事件,用户可以捕获事件,根据时间的参数做出相应的响应。
     *        下拉框未选为空的状态
     *        下拉框相应双向数据绑定的model,当model变化时,对应的下拉框组件可以显示对应的选项
     */

    app.directive('dropdown',function(){
        return {
            restrict : 'EA',
            replace: true,
            template : '
'+ '
'+ '
'+ '请选择 '+ '
'+ '
'+ ''+ '
'+ '
'+ '
', scope :{ name : '@', ngModel : "=", datalist : "=", empty : "=" }, link : function(scope,iElement,iAttrs){ debugger var $elem = $(iElement); var dependents = scope.dependents ? scope.dependents.split(',') : false; var parentScope = scope.$parent; scope.name = scope.name || 'multi-select-' + Math.floor(Math.random() * 900000 + 100000); scope.$watch('empty',function(newValue, oldValue, scope){ debugger if(newValue != oldValue){ if( newValue == true){ $elem.find('.ui-dropdown').removeClass("z-ui-dropdown-selected"); $elem.find(".ui-dropdown-current").text('请选择'); } } }) scope.$watch('ngModel',function(newValue,oldValue,scope){ console.log('----------enter watch-------------'); debugger if(newValue != oldValue){ scope.$root.$broadcast('selectUpdate', { // 将变动的菜单的name属性广播出去,便于依赖于它的菜单进行识别 name: scope.name }); for(var item in scope.datalist){ if(scope.datalist[item].key === newValue){ $elem.find(".ui-dropdown-current").text(scope.datalist[item].value); } } } }) scope.dropdown = function(){ $elem.find('.ui-dropdown').toggleClass("z-ui-dropdown-open"); } scope.select = function(){ // "z-ui-dropdown-selected" debugger $elem.find(".ui-dropdown").addClass("z-ui-dropdown-selected"); scope.empty = false; scope.ngModel = scope.datalist[this.$index].key; // iAttrs["ngModel"] = "0"+this.$index; // $elem.find(".ui-dropdown-current").text(scope.datalist[this.$index].value); // scope.datafunc(); } } } })

在页面中使用

 
                                                    

级联事件的响应


 $scope.$on('selectUpdate',function(e,data){
            //TODO:
            debugger
            // console.log(data);
            if(data.name == "risktypes-select"){
                if($scope.formData.riskType == ''){
                    $scope.markReasons2 = [{key : '', value:"全部"}];
                    $scope.formData.markReason = '';
                    return ;
                }
                $scope.formData.markReason = '';
                util.ajax({
                    "url": "XXXX",
                    "type": "post",
                    $http: $http,
                    contentType: "application/x-www-form-urlencoded; charset=utf-8",
                    data: {
                        riskType: $scope.formData.riskType
                    },
                    success: function(res) {                
                        if (!res) {
                            return _showMessage("对不起您没有权限", "信息错误");
                        }else if(res.success == false) {
                            return _showMessage("用户信息不匹配(未查到相关数据!)", "信息错误")
                        }else {     
                            $scope.reasonListSeleted = res.results._defaultResult;
                            debugger
                                    $scope.markReasons2 = [{key : '', value:"全部"}];
                                for (var i = 0; i < $scope.reasonListSeleted.length; i++) {
                                    $scope.markReasons2.push({
                                        key : 
                                        $scope.reasonListSeleted[i].reasonId,
                                        value : 
                                        $scope.reasonListSeleted[i].reasonDesc
                                    });
                                }
                        };
                    }
                });
            }
        })

相关注意点

  • 指令绑定参数时,最好不要是基本数据类型
    指令在进行值绑定的时候,传入的值最好是非基本类型。譬如绑定一个字符串类型riskTypengModel上,ngModel需要双向数据绑定。

这样的绑定会出现一定的问题
最好在controller中传入的参数的对象的属性,如下


在这个示例中datalist绑定的数据是数组类型,并非是简单数据类型,所以直接绑定即可。

扩展

后期又对下拉框进行优化,支持disable,搜索筛选选项等功能。

    app.directive('searchdropdown',['$document','$filter','$timeout',function($document,$filter,$timeout){
        return {
            restrict : 'EA',
            replace: true,
            template : '
'+ '
'+ '
'+ ''+ '请选择 '+ '
'+ '
'+ ''+ '
'+ '
'+ '
', scope :{ ngModel : "=", datalist : "=", disabled : "=", searchable : "=" }, controller : function($scope){ $scope.name = $scope.name || 'dropdown-' + Math.floor(Math.random() * 900000 + 100000); $scope.searching = false; $scope.myComparator = function (expected, actual) { return angular.equals(expected.toLowerCase(), actual.toLowerCase()); } }, link : function(scope,iElement,iAttrs){ var $elem = $(iElement); for(var item in scope.datalist){ if(scope.datalist[item].value === scope.ngModel){ $elem.find(".ui-dropdown-current").text(scope.datalist[item].text); $elem.find(".ui-dropdown").addClass("z-ui-dropdown-selected"); } } if(scope.disabled == true){ $elem.find(".ui-dropdown").addClass("z-ui-dropdown-disable"); } $elem.find('.ui-dropdown-search').bind('focus',function(event){ console.log('ui-dropdown-search is on focus'); $elem.find('.ui-dropdown').addClass("z-ui-dropdown-open"); event.stopPropagation(); }) // $elem.find(".ui-dropdown-hd").bind('blur',function(){ // alert('blur'); // }) // $elem.find('.ui-dropdown-search').bind('blur',function(event){ // console.log('ui-dropdown-search is on blur'); // scope.$apply(function(){ // scope.searching = false; // }) // }) scope.dropdown = function(){ console.log("ui-dropdown trigger dropdown event"); if(scope.disabled) return ; $elem.find('.ui-dropdown').toggleClass("z-ui-dropdown-open"); if($elem.find('.ui-dropdown').hasClass("z-ui-dropdown-open")){ console.log("---------" + scope.name +"------bind $document event -----------"); // 对于这种问题,jQuery的解决方案是使用事件绑定的命名空间。即在事件名称后添加 .something 来区分自己这部分行为逻辑范围。 $(document).bind("click."+scope.name, function(event) { console.log("-------go into $document click"+scope.name+"-------"); var judge = $(event.target).closest($elem).length > 0; // if(!$elem.find('.ui-dropdown').hasClass("z-ui-dropdown-open")){ // console.log("---------" + scope.name +"------unbind $document event -----------"); // $(document).unbind("click."+scope.name); // } if(!judge){ if(scope.searchable && scope.searching) { scope.$apply(function(){ scope.searching = false; }) } $elem.find(".ui-dropdown").removeClass("z-ui-dropdown-open"); $(document).unbind("click."+scope.name); } }); }else{ console.log("---------" + scope.name +"------unbind $document event -----------"); $(document).unbind("click."+scope.name); } if(scope.searchable){ scope.searching = !scope.searching; // if(scope.searching){ scope.searchData = scope.ngModel; var timer = $timeout( function() { $elem.find('.ui-dropdown-search').focus(); console.log( "Timeout executed", Date.now() ); },100); scope.$on("$destroy",function( event ) { $timeout.cancel( timer ); }); // } } } scope.select = function($event){ $elem.find(".ui-dropdown").addClass("z-ui-dropdown-selected"); var temp = $filter('filter')(scope.datalist,scope.searchData); console.log(temp); scope.ngModel = temp[this.$index].value; $elem.find(".ui-dropdown-current").text(temp[this.$index].text) $elem.find(".ui-dropdown").removeClass("z-ui-dropdown-open"); scope.searching = false; console.log(scope.searching); } scope.$watch('ngModel',function(newValue,oldValue,scope){ var isHitted = false; if(newValue != oldValue){ for(var item in scope.datalist){ if(scope.datalist[item].value === newValue){ $elem.find(".ui-dropdown-current").text(scope.datalist[item].text); $elem.find(".ui-dropdown").addClass("z-ui-dropdown-selected"); isHitted = true; } } if(!isHitted){ $elem.find(".ui-dropdown-current").text('请选择'); $elem.find(".ui-dropdown").removeClass("z-ui-dropdown-selected"); } } }) // $(document).bind("click."+scope.name, function(event) { // console.log("-------go into $document click-------"); // var judge = $(event.target).closest($elem).length > 0; // if(!judge){ // if(scope.searchable && scope.searching) { // scope.$apply(function(){ // scope.searching = false; // }) // } // $elem.find(".ui-dropdown").removeClass("z-ui-dropdown-open"); // } // }); // $document.bind("click", function(event) { // var judge = $(event.target).closest($elem).length > 0; // if(!judge){ // if(scope.searchable && scope.searching) { // // $elem.find('.ui-dropdown-search').blur(); // // console.log('manually trigger blur'); // scope.$apply(function(){ // scope.searching = false; // }) // } // $elem.find(".ui-dropdown").removeClass("z-ui-dropdown-open"); // } // }); // $(document).one("click", function(event) { // var judge = $(event.target).closest($elem).length > 0; // if(!judge){ // if(scope.searchable && scope.searching) { // // $elem.find('.ui-dropdown-search').blur(); // // console.log('manually trigger blur'); // scope.$apply(function(){ // scope.searching = false; // }) // } // $elem.find(".ui-dropdown").removeClass("z-ui-dropdown-open"); // } // }); } } }])
AngularJS Dropdown指令相关的总结_第1张图片
simple-select.gif
AngularJS Dropdown指令相关的总结_第2张图片
search-select.gif
disbaled.png

AngularJS中实现无限级联动菜单

AngularJS中实现无限级联动菜单

directive('multiLevelSelect', ['$parse', '$timeout', function ($parse, $timeout) {
 
    // 利用闭包,保存父级scope中的所有多级联动菜单,便于取值
    var selects = {};
 
    return {
 
        restrict: 'CA',
 
        scope: {
            // 用于依赖声明时指定父级标签
            name: '@name',
 
            // 依赖数组,逗号分割
            dependents: '@dependents',
 
            // 提供具体option值的函数,在父级change时被调用,允许同步/异步的返回结果
            // 无论同步还是异步,数据应该是[{text: 'text', value: 'value'},]的结构
            source: '=source',
 
            // 是否支持控制选项,如果是,空值的标签是什么
            empty: '@empty',
 
            // 用于parse解析获取model值(而非viewValue值)
            modelName: '@ngModel'
        },
 
        template: ''
            // 使用ng-show而非ng-if,原因上文已经提到
            + ''
            // 使用朴素的ng-repeat
            + '',
 
        require: 'ngModel',
 
        link: function (scope, elem, attr, model) {
 
            var dependents = scope.dependents ? scope.dependents.split(',') : false;
            var parentScope = scope.$parent;
            scope.name = scope.name || 'multi-select-' + Math.floor(Math.random() * 900000 + 100000);
 
            // 将当前菜单的getValue函数封装起来,放在闭包中的selects对象中方便调用
            selects[scope.name] = {
                getValue: function () {
                    return $parse(scope.modelName)(parentScope);
                }
            };
 
            // 保存初始值,原因上文已经提到
            var initValue = selects[scope.name].getValue();
 
            var inited = !initValue;
            model.$setViewValue('');
 
            // 父级标签变化时被调用的回调函数
            function onParentChange() {
                var values = {};
                // 获取所有依赖的菜单的当前值
                if (dependents) {
                    $.each(dependents, function (index, dependent) {
                        values[dependent] = selects[dependent].getValue();
                    });
                }
 
                // 利用闭包判断io造成的异步过期
                (function (thenValues) {
 
                    // 调用source函数,取新的option数据
                    var returned = scope.source ? scope.source(values) : false;
 
                    // 利用多层闭包,将同步结果包装为有then方法的对象
                    !returned || (returned = returned.then ? returned : {
                        then: (function (data) {
                            return function (callback) {
                                callback.call(window, data);
                            };
                        })(returned)
                    }).then(function (items) {
 
                        // 防止由异步造成的过期
                        for (var name in thenValues) {
                            if (thenValues[name] !== selects[name].getValue()) {
                                return;
                            }
                        }
 
                        scope.items = items;
 
                        $timeout(function () {
 
                            // 防止由同步(严格的说也是异步,注意事件队列)造成的过期
                            if (scope.items !== items) return;
 
                            // 如果有空值,选择空值,否则选择第一个选项
                            if (scope.empty) {
                                model.$setViewValue('');
                            } else {
                                model.$setViewValue(scope.items[0].value);
                            }
 
                            // 判断恢复初始值的条件是否成熟
                            var initValueIncluded = !inited && (function () {
                                for (var i = 0; i < scope.items.length; i++) {
                                    if (scope.items[i].value === initValue) {
                                        return true;
                                    }
                                }
                                return false;
                            })();
 
                            // 恢复初始值
                            if (initValueIncluded) {
                                inited = true;
                                model.$setViewValue(initValue);
                            }
 
                            model.$render();
 
                        });
                    });
 
                })(values);
 
                 
            }
 
            // 是否有依赖,如果没有,直接触发onParentChange以还原初始值
            !dependents ? onParentChange() : scope.$on('selectUpdate', function (e, data) {
                if ($.inArray(data.name, dependents) >= 0) {
                    onParentChange();
                }
            });
 
            // 对当前值进行监听,发生变化时对其进行广播
            parentScope.$watch(scope.modelName, function (newValue, oldValue) {
                if (newValue || '' !== oldValue || '') {
                    scope.$root.$broadcast('selectUpdate', {
                        // 将变动的菜单的name属性广播出去,便于依赖于它的菜单进行识别
                        name: scope.name
                    });
                }
            });
 
        }
    };
}]);

angularJS中组件复用和封装

https://www.zybuluo.com/lxjwlt/note/331587

http://www.jb51.net/article/58229.htm

http://www.tuicool.com/articles/QfyMna

http://www.tuicool.com/articles/fqiI73M

你可能感兴趣的:(AngularJS Dropdown指令相关的总结)