Kiểu internalhtml góc cạnh không hoạt động

Việc đưa HTML vào một thành phần bằng cách sử dụng Angular có thể được thực hiện bằng cách sử dụng thuộc tính “innerHTML” của vùng chứa (thường là “div” hoặc “p”). Tuy nhiên, có hai vấn đề với phương pháp này

  • Nếu thành phần xác định một số kiểu CSS (và sử dụng đóng gói chế độ xem mặc định), chúng sẽ không được áp dụng cho HTML được chèn
  • Nếu HTML chứa một số liên kết nội bộ, những liên kết này sẽ tải lại toàn bộ ứng dụng thay vì điều hướng bằng bộ định tuyến

Tôi đã phát triển ứng dụng Góc này để chứng minh những vấn đề này. Các phần chính của ứng dụng này là

  • Nó chứa ba thành phần được tải thông qua cấu hình bộ định tuyến (“/home”, “/hello” và “/bye”)
  • Thành phần “chính” được tải cho tuyến đường “/home” và chỉ cần đưa một số mã HTML vào “div”
  • Thành phần “hello” và “bye” chỉ hiển thị tên của họ và một liên kết quay lại để quay lại tuyến đường “/home”

Như bạn có thể thấy, HTML được sử dụng bởi thành phần chính sử dụng lớp CSS “đậm” được khai báo trong các kiểu của thành phần. Hơn nữa, nó chứa ba liên kết. hai cái bên trong (một tương đối và một tuyệt đối) và một cái bên ngoài

Cách thông thường để hiển thị HTML này trong thành phần là cách được sử dụng theo mặc định trong StackBlitz. thuộc tính “innerHTML”. Nếu bạn làm như vậy, kết quả là như sau

Sử dụng “HTML bên trong”

Như bạn có thể thấy, vấn đề đầu tiên là lớp “in đậm” không được áp dụng cho đoạn đầu tiên. Hơn nữa, nếu bạn nhấp vào hai liên kết đầu tiên, toàn bộ ứng dụng sẽ tải lại khi điều hướng trình duyệt được sử dụng thay vì bộ định tuyến Angular

Thay vào đó, hai vấn đề này có thể được giải quyết bằng cách sử dụng chỉ thị “html”

Bạn có thể kiểm tra điều đó bằng cách sử dụng nó thay vì “innerHTML” để xem kết quả sau

Sử dụng chỉ thị “html”

Như bạn có thể thấy lúc này, đoạn đầu tiên hiện được in đậm. Hơn nữa, nếu bạn nhấp vào liên kết, bộ định tuyến Angular sẽ khởi động và ứng dụng không tải lại (tất nhiên là ngoại trừ liên kết bên ngoài)

Toàn bộ logic của lệnh được xác định trong hook “ngOnChanges” để áp dụng nó ngay khi giá trị của đầu vào “html” thay đổi. Chúng tôi có thể đã sử dụng một trình thiết lập cho đầu vào “html” nhưng vì chỉ có một đầu vào nên nó không thay đổi nhiều

Điều đầu tiên chúng tôi làm là lấy id duy nhất của thành phần. Thật vậy, khi sử dụng đóng gói chế độ xem mặc định, các kiểu CSS thực sự được sửa đổi bằng một hậu tố để phạm vi chúng vào thành phần. Ví dụ: lớp CSS “đậm” thực sự được định nghĩa như thế này trong mã nguồn của trang

Đây là lý do tại sao sử dụng “innerHTML” sẽ không hoạt động đối với CSS. Thật vậy, đoạn được chèn sẽ không có thuộc tính “_ngcontent-lnp-c5” được áp dụng cho nó, vì vậy lớp sẽ không được áp dụng. Đây là lý do tại sao điều đầu tiên chúng ta làm trong lệnh là truy xuất tên của thuộc tính này cho phần tử mà lệnh được áp dụng và lưu nó vào biến “_uniqueId”

Sau đó, chúng ta chỉ cần cập nhật thuộc tính “innerHTML” của phần tử để chèn HTML. Lưu ý ở đây rằng chúng tôi không vệ sinh nó, vì vậy có thể có một số rủi ro khi tiêm, bạn có quyền quyết định. Tôi đã không kiểm tra nhưng tôi đoán rằng việc sử dụng công cụ khử trùng của Angular để bảo đảm chỉ thị sẽ không quá phức tạp

Bây giờ chúng ta có tên của thuộc tính, chúng ta truy xuất một tham chiếu đến tất cả các phần tử con của phần tử và thêm thuộc tính này vào chúng. Bằng cách này, đoạn văn bây giờ sẽ khớp với truy vấn CSS cho lớp “in đậm”

Điều này giải quyết vấn đề với CSS nhưng không giải quyết được vấn đề với các liên kết. Phần này được xử lý bởi điều kiện kiểm tra xem tên thẻ hậu duệ có phải là “A” hay không. Nếu đúng như vậy, chúng tôi lấy giá trị của thuộc tính “href” của nó. Lưu ý rằng chúng tôi không sử dụng hàm “getAttribute” vì điều này sẽ trả về giá trị thô. Điều tôi muốn nói là hàm “getAttribute” trả về một URL tương đối cho các liên kết tương đối trong khi thuộc tính “href” trả về một URL tuyệt đối cho tất cả các liên kết. Do đó, việc sử dụng thuộc tính thay vì thuộc tính đảm bảo rằng URL luôn tuyệt đối

Vì chúng tôi chỉ muốn sử dụng bộ định tuyến Angular cho các liên kết nội bộ, chúng tôi kiểm tra xem thuộc tính “href” có bắt đầu bằng nguồn gốc của trang không. Nếu vậy, chúng tôi xác định sự kiện “nhấp chuột” trên phần tử “a” để chuyển hướng người dùng bằng bộ định tuyến và ngăn hành vi mặc định để đảm bảo rằng trình duyệt sẽ không chuyển hướng người dùng đến URL sau đó

Lưu ý rằng chúng tôi tạo URL tương đối trước khi chuyển nó đến chức năng “điều hướng” của bộ định tuyến vì nó không hỗ trợ URL tuyệt đối

Giải pháp sau đây được áp dụng từ tràn ngăn xếp trong một sự cố tôi gặp phải. Điều này được thể hiện trong Ionic Framework, vì nó chủ yếu sử dụng Angular 2 nên nó sẽ hoạt động cho cả hai framework

Tôi đã thử gán kiểu cho một hình ảnh

SomeVar = ""

Các kiểu sẽ không hoạt động vì những lý do mà tôi không biết 😐 điều gì đó về Angular làm sạch tất cả HTML được thêm động. Đọc thêm tại đây

Giải pháp khá gọn gàng và đơn giản

Sử dụng một đường ống, Trong Ionic, bạn có thể dễ dàng tạo một đường ống mới bằng Ionic CLI

ionic g pipe safeHtml

Một thư mục mới được thêm vào trong thư mục gốc của bạn, trong safe-html của bạn. ts thêm đoạn mã sau để trông giống như thế này và đừng quên nhập DomSanitizer

import { Pipe, PipeTransform } from '@angular/core';
import {DomSanitizer} from "@angular/platform-browser";

/**
* Generated class for the SafeHtmlPipe pipe.
*
* See https://angular.io/api/core/Pipe for more info on Angular Pipes.
*/
@Pipe({
name: 'safeHtml',
})
export class SafeHtmlPipe implements PipeTransform {

constructor(private sanitizer:DomSanitizer){}

transform(html) {
return this.sanitizer.bypassSecurityTrustHtml(html);
}

}

Một điều nữa, hãy thêm đường ống của bạn vào ứng dụng/ứng dụng. mô-đun. ts dưới khai báo

@NgModule({
declarations: [
MyApp,
...
SafeHtmlPipe,
],

Và điều cuối cùng cần làm là chuyển đến tệp html nơi bạn đang sử dụng thẻ InternalHTML và thêm đường dẫn của bạn