2016-06-01 12 views
25

Giả sử chúng tôi muốn sử dụng thành phần từ một số thư viện trong angular2 (ví dụ: material2). Chú thích thành phần trông giống như sau:Kiểu mở rộng/ghi đè của thành phần angular2 có thể sử dụng lại

@Component({ 
    moduleId: module.id, 
    selector: 'md-input', 
    templateUrl: 'input.html', 
    styleUrls: ['input.css'], 
    providers: [MD_INPUT_CONTROL_VALUE_ACCESSOR], 
    host: {'(click)' : 'focus()'} 
}) 

Thành phần này có biểu định kiểu "mặc định", "input.css". Nếu chúng ta sử dụng thành phần này trong ứng dụng của mình, chúng ta có thể muốn ghi đè/mở rộng một số kiểu, mà không cần sao chép và thao tác thành phần đó. làm như thế nào?

Giải pháp 1: Đặt Đóng gói để "ViewEncapsulation.None":
Đây không phải là thực sự là một giải pháp, chỉ là một cách giải quyết khác.

Giải pháp 2: Sử dụng ":: shadow" hoặc "/ sâu /" trong CSS:
trình cũng có, nhưng nó bị phản đối theo WebComponent spec.

Giải pháp 3: Sử dụng CSS toàn cầu và ghi đè CSS phần:
trình cũng có, nhưng nó vi phạm các khái niệm bóng DOM.

Giải pháp 4: Override trực tiếp trong các mẫu của thành phần cha mẹ:

Ví dụ:

<my-cmp [font-size]="100"></my-cmp> 

là không thực sự phù hợp nếu chúng ta làm được rất nhiều trọng.

Giải pháp 5: Ghi đè hoặc mở rộng "@Component" sắc nét với một stylesheet thêm bằng cách nào đó:
này có vẻ là giải pháp đúng chỉ (ít nhất là đối với tôi). Nhưng tôi không có ý tưởng làm thế nào để làm điều này ...

Bất kỳ lời khuyên nào về điều này? Có lẽ tôi đã nhận được một cái gì đó sai ... Cảm ơn.

Trả lời

9

Đối với giải pháp 5, bạn cần phải tạo phân lớp cho thành phần được nhắm mục tiêu, tạo trang trí tùy chỉnh xử lý/ghi đè siêu dữ liệu và đặt nó cho thành phần phụ hiện tại.

Đây là một mẫu:

@CustomComponent({ 
    styleUrls: ['css/style.css'] 
}) 
export class OverridenComponent extends SomeComponent { 
} 

Các CustomComponent trang trí sẽ trông như thế này:

export function CustomComponent(annotation: any) { 
    return function (target: Function) { 
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor; 
    var parentAnnotations = Reflect.getMetadata('annotations', parentTarget); 

    var parentAnnotation = parentAnnotations[0]; 
    Object.keys(parentAnnotation).forEach(key => { 
     if (!isPresent(parentAnnotation[key])) { 
     annotation[key] = parentAnnotation[key]; 
     } 
    }); 
    var metadata = new ComponentMetadata(annotation); 

    Reflect.defineMetadata('annotations', [ metadata ], target); 
    } 
} 

Xem câu hỏi này để biết thêm chi tiết:

6

Giải pháp 2: Sử dụng ":: shadow" hoặc "/ sâu /" trong CSS:

này chỉ áp dụng nếu bạn sử dụng ViewEncapsulation.Native.

Nếu bạn sử dụng ViewEncapsulation.Emulated (mặc định) thì Angular sử dụng giải thích riêng của nó là /deep/::shadow và không dùng nữa.

Nếu bạn sử dụng ViewEncapsulation.Native sau đó bạn hiện đang trên may mắn vì trình duyệt nguồn gốc ::shadow/deep/ sâu đang bị phản đối và góc vẫn chưa cung cấp bất kỳ hỗ trợ cho hỗ trợ themeing cho ViewEncapsulation.Native ví dụ như Polymer làm với (polyfilled) biến CSS và mixin.

+0

nhờ làm rõ này – patrickkeller

+1

Bạn nên biết rằng việc mở rộng trang trí sẽ không được hỗ trợ bởi các ẩn mẫu biên dịch và không được khuyến khích https://github.com/angular/angular/issue/7968 # issuecomment-223779992 –

7

Bắt đầu với Angular 2.3, chúng ta có thể sử dụng thành phần thừa kế. Để đạt được Giải pháp 5, chúng tôi có thể làm được điều này.

//This is our base component that we want to override 
@Component({ 
    selector: 'pagination', 
    templateUrl: './pagination.component.html', 
    styleUrls: ['./pagination.component.css'] 
}) 
export class PaginationComponent { 
} 


//This inherits from our base component and uses a different style sheet. 
@Component({ 
    selector: 'pagination2', 
    //This is sharing the template with the parent class. Note 
    //this needs to be included since templateUrl doesn't automatically 
    //inherit. 
    templateUrl: './pagination.component.html', 
    //This is using a unique css file 
    styleUrls: ['./pagination2.component.css'] 
}) 
export class PaginationComponent2 extends PaginationComponent { 
} 
Các vấn đề liên quan