Angular开发Chrome扩展:如何在TypeScript函数中导入HTML文件
问题描述
我正在使用Angular开发Chrome扩展,目前遇到问题:无法在TypeScript文件的函数中导入HTML文件。
现有文件包括根目录的content-script.ts(页面刷新或扩展挂载时触发)、login.component.ts(含init()函数,被content-script.ts调用),以及login.component.html(需要插入到目标网站指定div的内容)。
现有代码示例
content-script.ts
import {LoginComponent} from './app/user/login.component' var loginComponent : LoginComponent = new LoginComponent(); loginComponent.init();
login.component.ts
@Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { init() => { let element = '此处需要获取login.component.html的内容' $('.my-website-class> div > div > .tempclass').last().after(element); } }
login.component.html
<div>Attach this login html file into the login component ts file</div>
需求
让init()函数里的element变量拿到login.component.html的内容,插入到目标网站指定div中。之前在AngularJS里是这么实现的:
var loginButtonTemplate = require('./login_button.html'); var scope = $rootScope.$new(); var loginButton = $compile(loginButtonTemplate)(scope); $('.my-website-class> div > div > .tempclass').last().after(loginButton);
想知道Angular里该怎么实现。
解决方案
方法一:用Angular动态组件编译(推荐,支持Angular指令/绑定)
这种方式能让你的组件正常触发Angular的变更检测,所有指令和数据绑定都会生效,完全符合Angular的开发规范。
- 修改
login.component.ts,注入必要的Angular服务,动态创建并挂载组件:
import { Component, OnInit, ComponentFactoryResolver, ApplicationRef, Injector, EmbeddedViewRef } from '@angular/core'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { constructor( private componentFactoryResolver: ComponentFactoryResolver, private appRef: ApplicationRef, private injector: Injector ) {} init() { // 创建组件工厂 const componentFactory = this.componentFactoryResolver.resolveComponentFactory(LoginComponent); // 生成组件实例 const componentRef = componentFactory.create(this.injector); // 将组件加入应用引用,触发变更检测 this.appRef.attachView(componentRef.hostView); // 获取组件对应的DOM元素 const domElement = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement; // 插入到目标网站指定位置(用原生JS替代jQuery,避免额外依赖) const target = document.querySelector('.my-website-class> div > div > .tempclass:last-child'); if (target) { target.after(domElement); } } }
- 模块配置(Angular 8及以下需要):
在app.module.ts里把LoginComponent加入entryComponents数组(Angular 9+启用Ivy后可省略这一步):
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { LoginComponent } from './app/user/login.component'; @NgModule({ declarations: [LoginComponent], imports: [BrowserModule], entryComponents: [LoginComponent], bootstrap: [] // Chrome扩展不需要默认启动的根组件 }) export class AppModule {}
方法二:直接导入HTML字符串(适合静态无绑定的HTML)
如果你的HTML里没有Angular指令或数据绑定,只是静态内容,可以直接导入HTML文件作为字符串使用,步骤如下:
- 修改
tsconfig.json,允许导入非TS文件:
{ "compilerOptions": { "resolveJsonModule": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true }, "include": ["src/**/*"] }
- 在
login.component.ts中直接导入HTML文件:
import loginTemplate from './login.component.html'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { init() { const target = document.querySelector('.my-website-class> div > div > .tempclass:last-child'); if (target) { // 直接插入HTML字符串 target.insertAdjacentHTML('afterend', loginTemplate); } } }
注意:这种方法下,HTML里的Angular指令(比如*ngIf、{{}}绑定)不会生效,因为没有经过Angular编译器处理。
内容的提问来源于stack exchange,提问作者Keshri Nanadan Shrivastava
相关产品推荐
相关产品推荐

