각도 정의TypeScript 및 $inject 메커니즘을 사용하는 JS 디렉티브
최근에 TypeScript로 작업 중인 Angular 프로젝트 중 하나를 리팩터링하기 시작했습니다.컨트롤러를 정의하기 위해 TypeScript 클래스를 사용하는 것은 매우 편리하며 다음과 같은 기능을 통해 최소화된 JavaScript 파일을 사용할 수 있습니다.static $inject Array<string>
소유물.또한 클래스 정의에서 Angular 종속성을 분할하지 않고 매우 깨끗한 코드를 얻을 수 있습니다.
module app {
'use strict';
export class AppCtrl {
static $inject: Array < string > = ['$scope'];
constructor(private $scope) {
...
}
}
angular.module('myApp', [])
.controller('AppCtrl', AppCtrl);
}
지금 저는 지시적 정의에 대해 유사한 사례를 처리할 해결책을 찾고 있습니다.명령어를 함수로 정의할 수 있는 좋은 방법을 찾았습니다.
module directives {
export function myDirective(toaster): ng.IDirective {
return {
restrict: 'A',
require: ['ngModel'],
templateUrl: 'myDirective.html',
replace: true,
link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrls) =>
//use of $location service
...
}
};
}
angular.module('directives', [])
.directive('myDirective', ['toaster', myDirective]);
}
이 경우 디렉티브 정의에서 Angular 종속성을 정의해야 합니다.이 경우 정의와 TypeScript 클래스가 다른 파일에 있을 경우 오류가 발생하기 쉽습니다.typescript와 typescript를 사용하여 디렉티브를 정의하는 가장 좋은 방법은 무엇입니까?$inject
TypeScript 를 실장하기 위한 좋은 방법을 찾고 있었습니다.IDirectiveFactory
하지만 제가 찾은 솔루션에 만족하지 못했습니다.
클래스를 사용하여 ng에서 상속합니다.IDirective는 TypeScript를 사용하는 방법입니다.
class MyDirective implements ng.IDirective {
restrict = 'A';
require = 'ngModel';
templateUrl = 'myDirective.html';
replace = true;
constructor(private $location: ng.ILocationService, private toaster: ToasterService) {
}
link = (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrl: any) => {
console.log(this.$location);
console.log(this.toaster);
}
static factory(): ng.IDirectiveFactory {
const directive = ($location: ng.ILocationService, toaster: ToasterService) => new MyDirective($location, toaster);
directive.$inject = ['$location', 'toaster'];
return directive;
}
}
app.directive('mydirective', MyDirective.factory());
관련 답변: https://stackoverflow.com/a/29223360/990356
지시문에 대해 를 지정하고 거기에 의존관계만 주입하는 것을 선호합니다.
컨트롤러와 인터페이스가 갖추어진 상태에서 링크 기능의 네 번째 파라미터를 컨트롤러의 인터페이스에 강하게 입력해, 거기서부터의 이용을 즐깁니다.
링크 부분에서 디렉티브의 컨트롤러로 종속성에 대한 관심을 이동시키면 컨트롤러의 TypeScript를 활용할 수 있으며 디렉티브 정의 기능을 짧고 단순하게 유지할 수 있습니다( 디렉티브에 정적 공장 방식을 지정하고 구현해야 하는 디렉티브 클래스 접근 방식과는 다릅니다).
module app {
"use strict";
interface IMyDirectiveController {
// specify exposed controller methods and properties here
getUrl(): string;
}
class MyDirectiveController implements IMyDirectiveController {
static $inject = ['$location', 'toaster'];
constructor(private $location: ng.ILocationService, private toaster: ToasterService) {
// $location and toaster are now properties of the controller
}
getUrl(): string {
return this.$location.url(); // utilize $location to retrieve the URL
}
}
function myDirective(): ng.IDirective {
return {
restrict: 'A',
require: 'ngModel',
templateUrl: 'myDirective.html',
replace: true,
controller: MyDirectiveController,
controllerAs: 'vm',
link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attributes: ng.IAttributes, controller: IMyDirectiveController): void => {
let url = controller.getUrl();
element.text('Current URL: ' + url);
}
};
}
angular.module('myApp').
directive('myDirective', myDirective);
}
이 경우 방향 정의에서 각도 종속성을 정의해야 합니다. 정의와 typescript 클래스가 다른 파일에 있으면 오류가 발생하기 쉽습니다.
솔루션:
export function myDirective(toaster): ng.IDirective {
return {
restrict: 'A',
require: ['ngModel'],
templateUrl: 'myDirective.html',
replace: true,
link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrls) =>
//use of $location service
...
}
};
}
myDirective.$inject = ['toaster']; // THIS LINE
이 파티에는 조금 늦었다.하지만 여기 제가 사용하고 싶은 솔루션이 있습니다.저는 개인적으로 이게 더 깨끗한 것 같아요.
먼저 도우미 클래스를 정의하면 어디서든 사용할 수 있습니다.(도움말 기능을 조금만 바꾸면 실제로 어떤 용도로도 사용할 수 있습니다.config run 등에 사용할 수 있습니다.
module Helper{
"use strict";
export class DirectiveFactory {
static GetFactoryFor<T extends ng.IDirective>(classType: Function): ng.IDirectiveFactory {
var factory = (...args): T => {
var directive = <any> classType;
//return new directive(...args); //Typescript 1.6
return new (directive.bind(directive, ...args));
}
factory.$inject = classType.$inject;
return factory;
}
}
}
여기 메인 모듈이 있습니다.
module MainAppModule {
"use strict";
angular.module("App", ["Dependency"])
.directive(MyDirective.Name, Helper.DirectiveFactory.GetFactoryFor<MyDirective>(MyDirective));
//I would put the following part in its own file.
interface IDirectiveScope extends ng.IScope {
}
export class MyDirective implements ng.IDirective {
public restrict = "A";
public controllerAs = "vm";
public bindToController = true;
public scope = {
isoVal: "="
};
static Name = "myDirective";
static $inject = ["dependency"];
constructor(private dependency:any) { }
controller = () => {
};
link = (scope: IDirectiveScope, iElem: ng.IAugmentedJQuery, iAttrs: ng.IAttributes): void => {
};
}
}
이 기사에서는 거의 그것에 대해 다루고 있으며, tanguy_k의 답변은 기사에 제시된 예시와 거의 일치합니다.그것은 또한 왜 당신이 수업을 이런 식으로 쓰기를 원하는지에 대한 모든 동기부여도 가지고 있다.상속, 활자 검사, 그리고 다른 좋은 것들...
http://blog.aaronholmes.net/writing-angularjs-directives-as-typescript-classes/
저의 솔루션은 다음과 같습니다.
지시:
import {directive} from '../../decorators/directive';
@directive('$location', '$rootScope')
export class StoryBoxDirective implements ng.IDirective {
public templateUrl:string = 'src/module/story/view/story-box.html';
public restrict:string = 'EA';
public scope:Object = {
story: '='
};
public link:Function = (scope:ng.IScope, element:ng.IAugmentedJQuery, attrs:ng.IAttributes):void => {
// console.info(scope, element, attrs, this.$location);
scope.$watch('test', () => {
return null;
});
};
constructor(private $location:ng.ILocationService, private $rootScope:ng.IScope) {
// console.log('Dependency injection', $location, $rootScope);
}
}
모듈(지시문을 등록...):
import {App} from '../../App';
import {StoryBoxDirective} from './../story/StoryBoxDirective';
import {StoryService} from './../story/StoryService';
const module:ng.IModule = App.module('app.story', []);
module.service('storyService', StoryService);
module.directive('storyBox', <any>StoryBoxDirective);
데코레이터(디렉티브 오브젝트를 삽입하여 생성):
export function directive(...values:string[]):any {
return (target:Function) => {
const directive:Function = (...args:any[]):Object => {
return ((classConstructor:Function, args:any[], ctor:any):Object => {
ctor.prototype = classConstructor.prototype;
const child:Object = new ctor;
const result:Object = classConstructor.apply(child, args);
return typeof result === 'object' ? result : child;
})(target, args, () => {
return null;
});
};
directive.$inject = values;
return directive;
};
}
생각중이야module.directive(...)
,module.service(...)
파일 "클래스 파일")로 합니다.StoryBoxDirective.ts
아직 하지 않았다
완전한 동작 예는, https://github.com/b091/ts-skeleton 에서 확인할 수 있습니다.
디렉티브는, https://github.com/b091/ts-skeleton/blob/master/src/module/story/StoryBoxDirective.ts 를 참조해 주세요.
이 답변은 @Mobiletainment의 답변에 근거하고 있습니다.초보자도 조금 더 읽기 쉽고 이해하기 쉽도록 하기 위해 포함시켰을 뿐입니다.
module someModule {
function setup() {
//usage: <some-directive></some-directive>
angular.module('someApp').directive("someDirective", someDirective);
};
function someDirective(): ng.IDirective{
var someDirective = {
restrict: 'E',
templateUrl: '/somehtml.html',
controller: SomeDirectiveController,
controllerAs: 'vm',
scope: {},
link: SomeDirectiveLink,
};
return someDirective;
};
class SomeDirectiveController{
static $inject = ['$scope'];
constructor($scope) {
var dbugThis = true;
if(dbugThis){console.log("%ccalled SomeDirectiveController()","color:orange");}
};
};
class SomeDirectiveLink{
constructor(scope: ng.IScope, element: ng.IAugmentedJQuery, attributes: ng.IAttributes, controller){
var dbugThis = true;
if(dbugThis){console.log("%ccalled SomeDirectiveLink()","color:orange");}
}
};
setup();
}
다른 솔루션은 클래스를 만들고 정적 $inject 속성을 지정하여 새 연산자를 사용하여 클래스가 호출되는지 여부를 감지하는 것입니다.그렇지 않으면 새 연산자를 호출하여 디렉티브클래스의 인스턴스를 만듭니다.
다음은 예를 제시하겠습니다.
module my {
export class myDirective {
public restrict = 'A';
public require = ['ngModel'];
public templateUrl = 'myDirective.html';
public replace = true;
public static $inject = ['toaster'];
constructor(toaster) {
//detect if new operator was used:
if (!(this instanceof myDirective)) {
//create new instance of myDirective class:
return new (myDirective.bind.apply(myDirective, Array.prototype.concat.apply([null], arguments)));
}
}
public link(scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrls:any) {
}
}
}
답변의 모든 옵션은 2개의 엔티티(ng)라는 아이디어를 주었습니다.IDirective 및 Controller)는 컴포넌트를 설명하기에 너무 많습니다.그래서 간단한 래퍼 프로토타입을 만들었습니다.다음은 시제품 https://gist.github.com/b1ff/4621c20e5ea705a0f788의 요지입니다.
언급URL : https://stackoverflow.com/questions/26920055/define-angularjs-directive-using-typescript-and-inject-mechanism
'sourcetip' 카테고리의 다른 글
오류: 리스트가 맵 유형의 하위 유형이 아닙니다. (0) | 2023.03.19 |
---|---|
Typescript가 클래스 및 인터페이스를 공개하기 위해 키워드 export를 사용하는 이유는 무엇입니까? (0) | 2023.03.19 |
XAMPP를 사용한mysql에서 에러 2가 발생. (0) | 2023.03.19 |
테이블 프리픽스를 취득하다 (0) | 2023.03.19 |
HTTP 사용방법각도 설정JS가 맞습니까?구체적으로는 외부 API 호출에 대해서요? (0) | 2023.03.19 |