Javascript 为什么Angular中基于jQuery令牌的集成不起作用?
我正在尝试将jQuery作为服务集成到Angular 6应用程序中,我遵循了以下文章: 唯一的区别是,我的解决方案使用InjectionToken,而不是自Angular 4以来就被弃用的OpaqueToken 好,现在谈谈代码本身 在jQuery服务中,如果问题的根本原因似乎发生了,jqueryFactory将返回未定义的: AppModule:app.module.ts AppComponent:app.component.ts 及其相关模板:app.component.html 此处提供了此应用程序的示例: [编辑] 正如user184994 github.com/StackBlitz/core/issues/407所指出的,潜在的问题似乎更多地是关于StackBlitz的 codesanbox上提供了一个工作示例:**编辑** 我发现,通过将CDN链接的script标记移动到head标记中,剩下的代码就可以工作了。查看更多信息 **原始答案**Javascript 为什么Angular中基于jQuery令牌的集成不起作用?,javascript,jquery,angular,Javascript,Jquery,Angular,我正在尝试将jQuery作为服务集成到Angular 6应用程序中,我遵循了以下文章: 唯一的区别是,我的解决方案使用InjectionToken,而不是自Angular 4以来就被弃用的OpaqueToken 好,现在谈谈代码本身 在jQuery服务中,如果问题的根本原因似乎发生了,jqueryFactory将返回未定义的: AppModule:app.module.ts AppComponent:app.component.ts 及其相关模板:app.component.html 此处提供了
部分问题是工厂可能在页面完全加载之前创建,即在窗口['jQuery']存在之前 为了避免这种情况,您可以使用useValue而不是useFactory,并让您的服务充当一个工厂。我的意思是:
import { InjectionToken } from '@angular/core';
export const JQUERY_TOKEN = new InjectionToken('jQuery');
export function jqueryFactory() {
return getJquery();
}
function getJquery() {
return window['jQuery'];
}
export const JQUERY_SERVICE = { provide: JQUERY_TOKEN, useValue: jqueryFactory };
然后在组件中,您可以初始化$,如下所示:
export class AppComponent implements OnInit {
constructor(@Inject(JQUERY_TOKEN) private $factory: any) { }
public paragraphCount = 0;
public $: any;
public ngOnInit() {
this.$ = this.$factory();
this.paragraphCount = this.$('p').length;
}
}
有几件事需要指出:
我认为Stackblitz不会查看您的Angular.json文件,所以我只是在index.html中添加了一个指向jquery CDN的链接。在Stackblitz之外,你不应该这样做
我已经将lifecycle函数改为ngOnInit,否则您将看到在已经运行更改检测之后值更改的问题
部分问题是工厂可能在页面完全加载之前创建,即在窗口['jQuery']存在之前。你有什么理由想在服务中使用它吗?@user184994我认为当涉及到单元测试时,依赖性可以在需要时被模仿。这是有道理的。您可以随时更改服务,使其具有功能。哪一个依次返回窗口['jQuery']?这样的话,它只会在你们们正在阅读的时候从窗口读取ready@user184994这正是我所想的about@user184994似乎jQuery甚至没有正确导入…=/windows对象中没有任何内容,即使加载了所有内容。我将在github上向Stackblitz提交问题通知单。@EhouarnPerret看起来他们已经知道@user184994 true=/正在签出codesandbox并查看它是否支持它。似乎使用codesandbox可以解决问题:谢谢您的帮助!
import { Component, Inject, AfterViewInit } from '@angular/core';
import { JQUERY_TOKEN } from './jquery.service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit {
constructor(@Inject(JQUERY_TOKEN) private $: any) { }
public paragraphCount = 0;
public ngAfterViewInit(): void {
this.paragraphCount = this.$('p').length;
}
}
<h1>HelloW!</h1>
<p>
Seems there is {{ paragraphCount }} paragraph in this component template.
</p>
"scripts": [
"./node_modules/jquery/dist/jquery.min.js"
]
import { InjectionToken } from '@angular/core';
export const JQUERY_TOKEN = new InjectionToken('jQuery');
export function jqueryFactory() {
return getJquery();
}
function getJquery() {
return window['jQuery'];
}
export const JQUERY_SERVICE = { provide: JQUERY_TOKEN, useValue: jqueryFactory };
export class AppComponent implements OnInit {
constructor(@Inject(JQUERY_TOKEN) private $factory: any) { }
public paragraphCount = 0;
public $: any;
public ngOnInit() {
this.$ = this.$factory();
this.paragraphCount = this.$('p').length;
}
}