代码之家  ›  专栏  ›  技术社区  ›  Natalie Perret

为什么基于jQuery令牌的角度集成不起作用?

  •  0
  • Natalie Perret  · 技术社区  · 6 年前

    我正在尝试将jQuery作为一个服务集成到Angular 6应用程序中,并按照本文进行了操作: https://thecodegarden.net/jquery-in-angular-typescript-without-type-definition/#comment-2311

    唯一的区别是我的解决方案使用 InjectionToken 而不是 OpaqueToken 从Angular4开始就被弃用了。

    好了,现在谈谈代码本身。

    在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 };
    

    应用模块: 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 { }
    

    应用组件: 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

    [编辑]

    似乎潜在的问题更多的是关于stackblitz,正如user184994 github.com/stackblitz/core/issues/407所指出的

    codesanbox上提供了一个工作示例: https://codesandbox.io/s/3vmzyrj4w1

    1 回复  |  直到 6 年前
        1
  •  1
  •   user184994    6 年前

    ** 编辑 **

    我通过移动 script CDN链接的标记 head tag,剩下的代码就可以工作了见 this example 更多

    ** 原始答案 **

    部分问题是,工厂可能是在页面完全加载之前创建的,即在 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;
      }
    
    }
    

    Here is a working stackblitz

    有几点需要指出:

    • 我不认为stackblitz会查看您的angular.json文件,所以我刚刚在 index.html . 除了Stackblitz,你不应该这样做
    • 我已将生命周期功能更改为 ngOnInit 相反,否则在运行更改检测之后,您将看到有关值更改的问题