angular.js - 多重自定义指令应该怎么写?
曾经蜡笔没有小新
曾经蜡笔没有小新 2017-05-15 17:03:52
0
2
672

是这样的,要创建一个登录用的东西,但卡在自定义指令上。
登录要求有一个账号输入框,一个密码输入框。

  1. 因为要兼容IE8,所以PLACEHOLDER属性不能直接用。需要使用自定义指令来完成。

  2. 账号可以是手机,也可以是邮箱,也可以是普通账号。

  3. 邮箱需要自动生成后缀,所以也需要自定义指令。可以设定是否需要在输入了@之后再显示邮箱提示。

  4. 账号需要可以自己验证,这又要引入自定义指令来写验证(从angular官网上看到的方法,自定义验证器)。

现在要使用多重自定义指令,来完成这个东西(如果大家有更好的办法,也可以不用这个,请告诉我,谢谢)。

我的想法是,先定义一个自定义指令,可以让它的PLACEHOLDER在需要的时候显示出来。然后在此基础上定义一个EMAIL指令,当输入账号的时候,自动给它加上各种域名的后缀,以供选择。最后再在这个基础上,定义一个PASSPORT指令,可以判断当前输入的内容是不是可用的账号(手机/邮箱/普通用户名)。

但是问题来了,如果要在同一个作用域中使用多个这种自定义指令的话,指令就必须是分离作用域,但是这三层的自定义指令,没办法都定分离作用域,会报错。如果要使各个此种指令分离的话,想到使用ng-repeat,但是ng-repeat生成的class又没办法在生成之后,自动编译成正常的指令……

我知道我说的有点儿乱,如果大家有别的好办法,请交流一下,谢谢。最后上代码……

主文件

<body ng-app="Main">

    <form novalidate name="LoginForm">
        <p ng-form class="dir-text-placeholder dir-text-email dir-text-passport" 
            ng-init="needAt=true; 
            name='user_passport'; 
            id='user_passport'; 
            placeholder='用户名/邮箱/手机';">
        </p>
    </form>

</body>
angular.module('Main', [])
    .directive('dirTextPlaceholder', [function () {
        return {
            restrict: 'C',
            priority:111,
            controller:function(){
                console.info('in textPlaceholder')
            },
            link: function (scope, iElement, iAttrs) {
                var input=iElement.find('input').eq(0);
                scope.$watch("value",function(newValue,oldValue){
                    if(!!newValue && !oldValue) 
                        input.addClass("chi-full").removeClass("chi-empty");
                    else if(!newValue && !!oldValue) 
                        input.addClass("chi-empty").removeClass("chi-full");
                });
            },
            templateUrl:"text-placeholder.html"
        };
    }])
    .directive('dirTextEmail', ['$compile','$timeout',function ($compile,$timeout) {
        var hosts='126.com|163.com|qq.com|sina.com|yeah.net'.split('|');
        return {
            restrict: 'C',
            priority:11,
            require: '?dirTextPlaceholder',
            controller:function(){
                console.info('in textEmail')
            },
            link: function (scope, iElement, iAttrs) {
                iElement.append("<ul></ul>")
                var input=iElement.find('input').eq(0),
                    ul=iElement.find('ul').eq(0),
                    li=angular.element('<li ng-repeat="email in emails | filter:host" ng-click="setEmail(email)">{{email}}</li>');
                $compile(li)(scope);
                ul.append(li);
                scope.$watch("value",function(newValue){
                    if(newValue===undefined) return false;
                    var indexAt=newValue.indexOf('@');
                    if(scope.needAt && !~indexAt) return false;
                    scope.host=newValue.substring(indexAt);
                    var passport=newValue.substring(0,indexAt);
                    var emails=[];
                    for(var n=0;n<hosts.length;n++) emails.push(passport+'@'+hosts[n]);
                    scope.emails=emails;
                    emails=null;
                    $timeout(function(){
                        if(ul.children().length==1 && ul.children().eq(0).html()==newValue)
                            ul.hide();
                        else ul.show();
                    });
                });
                scope.setEmail=function(email){
                    scope.value=email;
                }
            }
        };
    }])
    .directive('dirTextPassport', ['$rootScope',function ($rootScope) {
        return {
            restrict: 'C',
            priority:1,
            require: '?dirTextEmail',
            controller: function(){
                console.info('in textPassport')
            },
            link: function (scope, iElement, iAttrs) {
                var ptr=/^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}|(13\d|14[57]|15[^4,\D]|17[678]|18\d)\d{8}|170[059]\d{7}$/,
                    input=iElement.find('input').eq(0),
                    controller=angular.element(iElement).scope();
                console.log($rootScope)
                //写到这儿的时候,想起来,账号跟密码要放在同一个作用域下,
                //所以第一个指令不采用分离作用域是不行的,但是分离之后,
                //后续的跟它作用在同一DOM上的其它指令又不能再用分离作用域,我就不会了……
            }
        };
    }])

模板文件text-placeholder.html

<input type="{{type}}" name="{{name}}" id="{{id}}" ng-model="value" autocomplete="off">
<label for="{{id}}">{{placeholder}}</label>
曾经蜡笔没有小新
曾经蜡笔没有小新

모든 응답(2)
phpcn_u1582

이것은 IE8 자리 표시자 호환성을 위한 솔루션입니다.
개인적으로는 요구 사항을 충족하기 위한 지침을 작성하는 것을 권장하지 않습니다. 논리가 너무 혼란스럽습니다. 이는 Angle의 하이라이트가 명령어이고 명령어를 내보내야 한다는 의미는 아닙니다. 단지 로그인 인터페이스일 뿐이고, 검증 로직을 컨트롤러에 작성할 수 있습니다. 작성하라는 지시를 받으면 코드 양이 두 배 이상 늘어나 가독성이 좋지 않습니다.

过去多啦不再A梦

학교를 포기했어요^^^

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!