我正在尝试将jQuery作为服务集成到Angular 6应用程序中,我关注了这篇文章:https://thecodegarden.net/jquery-in-angular-typescript-without-type-definition/#comment-2311
唯一的区别是我的解决方案使用的是InjectionToken
而不是自Angular 4起已弃用的OpaqueToken
。
好,现在介绍一下代码本身。
jQuery服务,其中似乎发生了根本原因的问题,jqueryFactory
返回undefined
:
import { InjectionToken } from '@angular/core';
export const JQUERY_TOKEN = new InjectionToken('jQuery');
export function jqueryFactory() {
// return undefined...
return window['jQuery'];
}
export const JQUERY_SERVICE = { provide: JQUERY_TOKEN, useFactory: jqueryFactory };
AppModule:app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { JQUERY_SERVICE } from './jquery.service';
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [ JQUERY_SERVICE ]
})
export class AppModule { }
AppComponent:app.component.ts
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;
}
}
及其相关模板:app.component.html
<h1>HelloW!</h1>
<p>
Seems there is {{ paragraphCount }} paragraph in this component template.
</p>
最后但并非最不重要的angular.json
:
"scripts": [
"./node_modules/jquery/dist/jquery.min.js"
]
此处提供了此应用程序的示例:https://stackblitz.com/edit/angular2plus-jquery-token-based-eaxnzs
[编辑]
似乎根本的问题更多地是由user184994 github.com/stackblitz/core/issues/407指出的StackBlitz
可在codesanbox上找到一个工作示例:https://codesandbox.io/s/3vmzyrj4w1
答案 0 :(得分:1)
** 编辑 **
我发现,通过将CDN链接的// initial call
processItem($('.myList li:first'));
function processItem($li) {
if (!$li.length) {
return; // none left
}
var $next = $li.next();
if (condition) {
console.log('item with index: ' + $li.index() + ' is skipped');
// recursive call assumed here also
processItem($next);
} else {
$li.click();
setTimeout(function() { // Wait 1 second untill the popup is opended
popupWindow.animate({
scrollTop: $(this).height()
}, $(this).height() * 10, getData);
// get the data to post
// use promise returned from postData to start process next item
postData(data).then(function() {
processItem($next)
});
}, 1000);
}
}
function postData(data) {
// must return the ajax promise
return $.ajax({
type: 'POST',
// ...
// ...
});
}
标签移动到script
标签中,其余的代码将起作用。有关更多信息,请参见this example
** 原始答案 **
部分问题是工厂可能在页面完全加载之前即head
存在之前创建。
要解决此问题,您可以使用window['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之外,您不需要这样做index.html
,否则您将在更改检测已运行后看到有关值更改的问题