2015-10-15 3 views
0

Мы сейчас переходим к Google Closure Compiler. Мы рефакторинг нашей старого кода базы поэтому его подгонка к этой статье: A radical new approach to developing AngularJS appsУгловая директива фабрики только называется один

директивы должна выглядеть следующим образом:

/** 
* @constructor 
*/ 
var Directive = function(version) { 
    this.version = version; 
    this.link = this.link.bind(this); 

    this.scope; 
    this.elem; 
    this.attrs; 
}; 

/** 
* Version directive factory. Entry point and used in `module.directive`. 
*/ 
Directive.factory = function(version) { 
    var dir = new Directive(version); 
    return { 
    link: dir.link 
    }; 
}; 

/** 
* Linking function. 
*/ 
Directive.prototype.link = function(scope, elem, attrs) { 
    this.scope = scope; 
    this.elem = elem; 
    this.attrs = attrs; 
    this.elem.text(this.version.get()); 
}; 

angular.module('app', []) 
    .directive('version', Directive.factory); 

Все работает отлично, пока мы не используем директиву несколько раз на сайте. Directive.factory будет вызываться только один раз. Таким образом, все директивы на сайтах имеют один и тот же объект Directive. Мы не понимаем, почему это происходит.

+0

Заводы, службы, значения и т. Д. Объявляются только один раз в жизненном цикле углового приложения ... Вы можете сделать этот «объект», скажем, сервисом ... и ввести его в свою директиву. Неужели этого недостаточно для того, чего вы хотите достичь? – deostroll

+0

Мы хотим использовать нашу директиву как конструктор. Я не знаю, как услуга нам поможет. – tschiela

+0

Вы имеете в виду, что каждая директива «версия» на странице должна отличаться от других, потому что она была определена с фабрикой? Этого не произойдет, так не получается. – estus

ответ

2

An Angular service is a singleton object created by a service factory. И поэтому объекты DDO - это одноэлементные массивы, созданные из объектов, возвращаемых directive factory functions (директивы оказываются службами под капотом). После того, как была вызвана фабричная функция (Directive.factory в вашем случае), ее результат кэшируется как служебный экземпляр versionDirective.

После того, как вы знаете, как именно Угловая treats compile and link functions, это может быть возможным трюк, как это:

Directive.factory = function(version) { 
    return { 
    compile: function() { 
     var dir = new Directive(version); 
     // by default there is no 'this' in link 
     return angular.bind(dir, dir.link); 
    } 
    }; 
}; 

И я рекомендовал бы против этого, если вы не знаете, что вы делаете очень хорошо. Это не поможет тестированию, а также не может быть изменено, или что-то еще, но будет злоупотреблять каркасом.

«Радикальный новый подход» может быть или не быть полезным, но он, конечно же, не подразумевает подобные вещи.

+0

Итак, вкратце: возможно написать контроллеры в качестве конструкторов. Услуги, фабрики и директивы не должны быть написаны как конструктор. – tschiela

+0

Да, именно так был разработан Angular. Они не смогут использовать конструкторы/классы. Хотя провайдеры услуг «службы» могут (они используют «это» в конструкторе). – estus

+0

Нет ничего плохого в написании сервисов, фабрик и директив в качестве конструкторов - вам просто нужно помнить, что они будут создаваться только один раз. Все будет использовать глобально общий экземпляр. –

1

Я изменил ваш пример, чтобы отразить тот факт, что конструктор Directive является одноэлементным, который является общим.

/** 
* @constructor 
*/ 
var Directive = function(version) { 
    this.version = version; 
}; 

/** 
* Version directive factory. Entry point and used in `module.directive`. 
*/ 
Directive.factory = function(version) { 
    return new Directive(version); 
}; 

/** 
* Linking function. 
*/ 
Directive.prototype.link = function(scope, elem, attrs) { 
    // this refers to the Directive singleton - it's shared between 
    // multiple invocations. 
    elem.text(this.version.get()); 
}; 

angular.module('app', []) 
    .directive('version', Directive.factory); 

Если вы хотите, поведение, которое вы изначально были нацелены на, вы можете изменить ваш метод ссылки построить объект:

/** 
* Linking function. 
*/ 
Directive.prototype.link = function(scope, elem, attrs) { 
    // This will be created everytime the template is cloned 
    var versionDirective = new VersionDirectiveLink(scope, elem, attrs); 
    versionDirective.setText(this.version.get()); 
}; 

Этот последний вариант создает объект каждый раз, когда шаблон клонирован. Таким образом, вы можете поддерживать более продвинутое поведение с помощью конструкторов.

+0

Обратите внимание, что 'this.version.get' означает лексическое значение, которое не определено (или равно окну) в ссылках. Это не может быть проблемой для классов с стрелой, но для es-5 это неприятно. Это одна из причин, почему функция ссылок не является лучшим местом для попыток OO. – estus

Смежные вопросы