如何解决Angular 11,js 在 angular
我一直在研究 angular 中的一个错误(不是称之为错误)。但是在 SPA 中,js 在路由到不同的组件后失去了它的作用域。我已经阅读了互联网上几乎所有可用的答案。让我用更简单的方式说明问题是什么。
- 作用域在我们路由到不同的元素后结束(我们使用的是外部 js)
- 由于我的 js 是相互连接的,所以它必须一次加载。所以通过 component.ts 方法加载特定的 js 是不可行的,因为它再次改变了 DOM 的范围并且其他功能停止工作。
所以如果有人遇到此类问题,让我们在这里讨论。
更新图片:
我的代码:Script-loader.ts
从'@angular/core'导入{可注射}; @Injectable({
providedIn: 'root' }) 导出类 ScriptLoaderService {
private scripts: any = {};
load(...scripts: string[]) {
this.scripts = scripts;
let promises: any[] = [];
scripts.forEach((script) => promises.push(this.loadScript(script)));
return Promise.all(promises);
}
loadScript(name: string) {
return new Promise((resolve,reject) => {
let script = (document.createElement('script') as any);
script.type = 'text/javascript';
script.src = name;
script.async = false;
script.defer = false;
if (script.readyState) { //IE
script.onreadystatechange = () => {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
script.onreadystatechange = null;
resolve({script: name,loaded: true,status: 'Loaded'});
}
};
} else { //Others
script.onload = () => {
resolve({script: name,status: 'Loaded'});
};
}
script.onerror = (error: any) => resolve({script: name,loaded: false,status: 'Loaded'});
document.getElementsByTagName('head')[0].appendChild(script);
});
}
} 块引用
blogs.component.ts
从 '@angular/core' 导入 { Component,OnInit,AfterViewInit }; 从 '../script-loader.service' 导入 { ScriptLoaderService }; 声明 var $: any;
@Component({ 选择器: 'app-blogs',templateUrl: './blogs.component.html',styleUrls: ['./blogs.component.css'] }) 导出类 BlogsComponent 实现 OnInit、AfterViewInit {
构造函数(私有脚本加载器:ScriptLoaderService){ }
ngAfterViewInit(): void { this.scriptloader.load( '资产/js/app.js','资产/数据/tipuedrop_content.js', '资产/js/global.js','assets/js/navbar-v1.js','资产/js/main.js','assets/js/widgets.js',
'assets/js/lightBox.js','assets/js/Feed.js',);
}
ngOnInit(): void { }
}
博客.module.ts
从'@angular/core'导入{NgModule};
从 "@angular/router" 导入 { Routes,RouterModule };进口 { BlogsComponent } 来自'./blogs.component';
const 路由:路由 = [ { 小路: ””, 组件:BlogsComponent } ];
@NgModule({ 进口:[RouterModule.forChild(routes)],出口: [RouterModule] }) 导出类 BlogsModule { }
videos.component.ts
从 '@angular/core' 导入 { Component,AfterViewInit };
从 '../script-loader.service' 导入 { ScriptLoaderService };
声明 var $: any; @Component({ 选择器: 'app-videos',
templateUrl: './videos.component.html',styleUrls:
['./videos.component.css'] }) 导出类 VideosComponent 实现
OnInit,AfterViewInit {
构造函数(私有脚本加载器:ScriptLoaderService){ }
ngAfterViewInit(): 无效 {
this.scriptloader.load(
'资产/js/app.js','assets/js/main.js',
'assets/js/widgets.js','assets/js/lightBox.js',);
}
ngOnInit(): void { }
}
videos.module.ts
从'@angular/core'导入{NgModule};
从 "@angular/router" 导入 { Routes,RouterModule };进口 { VideosComponent } 来自'./videos.component';
const 路由:路由 = [ { 小路: ””, 组件:视频组件 } ];
@NgModule({ 进口:[RouterModule.forChild(routes)],出口: [RouterModule] }) 导出类 VideosModule { }
App-routing.module.ts
从'@angular/core'导入{NgModule};进口{路由器模块,
路线}来自'@angular/router';导入 { 预加载策略,
PreloadAllModules } 来自“@angular/router”;导入 { 博客模块 }
来自'./blogs/blogs.module';导入 { FeedModule } from
'./Feed/Feed.module';导入 { HangoutModule } from
'./hangout/hangout.module';导入 { HomeModule } from
'./home/home.module';导入 { VideosModule } from
'./videos/videos.module';
const 路线:路线 = [
{ 路径:“饲料”, loadChildren: "./Feed/Feed.module#FeedModule" },{ 路径:“阅读”, loadChildren: "./blogs/blogs.module#BlogsModule" },{ 路径:“观看”, loadChildren: "./videos/videos.module#VideosModule" },{ 路径:'家', loadChildren:"./home/home.module#HomeModule" },{ 路径:“环聊”, loadChildren:"./hangout/hangout.module#HangoutModule" }
];
@NgModule({ 导入:[RouterModule.forRoot(routes,{ preloadingStrategy: PreloadAllModule })],导出: [RouterModule] }) 导出类 AppRoutingModule { }
现在当我从博客路由到视频时发生了什么。它再次添加了以前的所有js。我不知道这是否是一个好习惯。这是 DOM HEAD 来显示正在发生的事情
解决方法
您可以将您的 JS
库甚至您的 CSS
文件添加到 angular.json
文件中以用于更大范围的用途(全局):
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json","version": 1,"newProjectRoot": "projects","projects": {
"mehdi-daustany": {
"root": "","sourceRoot": "src","projectType": "application","architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser","assets": [
"src/assets","src/favicon.png"
],"styles": [
"src/public-styles.css"
],"scripts": [
"node_modules/jquery/dist/jquery.min.js","node_modules/@microsoft/signalr/dist/browser/signalr.min.js","src/assets/common/js/components/util.js"
]
} ...
将这些编译为文件的文件导入到您的 DOM 中,命名为:scripts.js
和 styles.js
。
因此,请按您的项目逻辑序列导入它们。
其他方式。
您可以在组件的 ngOnInit()
或 ngAfterViewInit()
上加载脚本,我更喜欢 ngAfterViewInit()
,但如何:
首先,创建一个名为 .ts
的 "script-loader.service.ts"
文件或您想要的任何文件。
将以下代码粘贴进去。
import { Injectable } from '@angular/core';
@Injectable()
export class ScriptLoaderService {
private scripts: any = {};
load(...scripts: string[]) {
this.scripts = scripts;
let promises: any[] = [];
scripts.forEach((script) => promises.push(this.loadScript(script)));
return Promise.all(promises);
}
loadScript(name: string) {
return new Promise((resolve,reject) => {
let script = (document.createElement('script') as any);
script.type = 'text/javascript';
script.src = name;
if (script.readyState) { //IE
script.onreadystatechange = () => {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
script.onreadystatechange = null;
resolve({script: name,loaded: true,status: 'Loaded'});
}
};
} else { //Others
script.onload = () => {
resolve({script: name,status: 'Loaded'});
};
}
script.onerror = (error: any) => resolve({script: name,loaded: false,status: 'Loaded'});
document.getElementsByTagName('head')[0].appendChild(script);
});
}
}
然后,在顶层模块中提供此服务,例如 app.module.ts
import { NgModule } from '@angular/core';
import { ScriptLoaderService } from './script-loader.service';
@NgModule({
imports: [
],providers: [
ScriptLoaderService
],declarations: [
],exports: [
]
})
export class AppModule { }
现在是时候使用这个服务了,假设你想在ngAfterViewInit()
初始化方法中使用它,所以你必须在你的目标组件中实现AfterViewInit
;例如:
import { Component,AfterViewInit } from '@angular/core';
import { ScriptLoaderService } from '@shared/utils/script-loader.service';
@Component({
templateUrl: './your.component.html'
})
export class YourComponent implements AfterViewInit {
constructor(
private scriptLoader: ScriptLoaderService) {
}
ngAfterViewInit() {
this.scriptLoader.load(
'assets/dist/jquery.min.js','assets/ckeditor/ckeditor.js'
);
}
}
通过这种方式,每次您的组件被 angular 路由器延迟加载时,都需要初始化脚本而无需硬刷新您的页面。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。