【问题标题】:How to use jQuery with javascript in angular 2如何在 Angular 2 中使用 jQuery 和 javascript
【发布时间】:2016-01-28 06:09:49
【问题描述】:
    import {Component, ElementRef, OnInit} from 'angular2/core';
    declare var jQuery:any;
    @Component({
      selector: 'jquery-integration',
      templateUrl: './components/jquery-integration/jquery-integration.html'
    })
    export class JqueryIntegration implements OnInit {
      elementRef: ElementRef;
      constructor(elementRef: ElementRef) {
        this.elementRef = elementRef;
      }
      ngOnInit() {
        jQuery(this.elementRef.nativeElement).draggable({
        containment:'#draggable-parent'
      });
    }
  }

jQuery 可以像上面那样在 Angular2 中与 TypeScript 一起使用吗?如何在 Angular2 中使用 jQuery 和 JavaScript?

【问题讨论】:

标签: jquery typescript angular


【解决方案1】:

在我看来:如果你做得对,如果你把它保持在最低限度,你应该这样做。

  1. 在项目中安装 jQuery Typings:tsd install jQuery
  2. 使用脚本标签(或其他加载器...)加载 jQuery
  3. 使用 Angular 2 指令封装任何 jQuery 插件

例子:

@Directive({
  selector: "[sm-dropdown]"
})
export class SMDropdown {
  constructor(el: ElementRef) {
    jQuery(el.nativeElement).dropdown();
  }
}

考虑一下这个 Plunker:

https://plnkr.co/edit/MMNWGh?p=preview

不要:

  • 不要将它用于 DOM 操作,有 Angular 方式...
  • 不要将它用于 AJAX 调用,有 Angular 方式...
  • 不要用它来做动画,ngAnimation 来了……

【讨论】:

  • 我很好奇你能扩展一下无 DOM 操作吗?我来自 angular 1 背景,但我知道控制器等中没有 DOM 操作,并且不做 angular 可以做的事情。然而,在 Angular 1 中,至少有一些合法的事情 Angular 无法做到,而您可以使用 jQuery。
  • 你有 Angular 指令可以添加样式、类等,比如 *ngStyle、*ngClass... 你可以用 *ngIf、*ngSwitch 显示和隐藏东西... 你可以用 native 控制 DOM Angular 的 Node.js 和 ElementRef 和 Rendered 类。 jQuery 经常重塑 DOM,我假设您想控制您的 html(用于绑定...)。最佳实践是,如果您需要包含 jQuery 库,则将其包装在 Directive 中(正如我之前写给您的那样)并将该指令附加到 html 中的元素上(Angular 样式)。在这种情况下,您将划分职责并使代码更具可读性。
  • 看起来非常好的方法。但我注意到一个问题。如果将此与 *ngFor 一起使用。最后一项不初始化 jquery 插件。在此指令中使用 ngAfterContentInit() 修复了问题
  • @VladoTesanovic 这个例子可以适用于其他 vanila js 插件吗?
【解决方案2】:

安装 JQuery typescript 库后,以这种方式引用它

///<reference path="../typings/jquery/jquery.d.ts" />

然后进行必要的导入

import {Component, AfterViewInit} from 'angular2/core';

现在编写类

@Component({
  selector: 'my-app',
  templateUrl: 'app/html/app.component.html'
})

export class AppComponent implements AfterViewInit {
  ngAfterViewInit() {
    // Your jQuery code goes here
    $('#here').text("HALLO! ^_^");
  }
}

【讨论】:

  • 嗨,我可以以任何其他方式添加 jquery.d.ts 的引用,例如使用“imports”而不是使用“///' ?请提出建议。
【解决方案3】:

我如何解决这个问题:

对于库不支持@types/,并且库需要在文档加载时加载(意味着库需要在文档的脚本标签中添加)

  1. 运行npm install jquery --save
  2. scriptsstylesangular-cli.json 中添加js/css 文件

    "scripts": ["../node_modules/path to file", "./assets/path to file"]

对于支持的库@types/,只需运行npm install @types/jquery --save-dev

要使用该库,请在注解@Directive@Component之前添加declare var jQuery: any;要使用该库

P/S:我在我的项目中使用angular-cliwebpack,可能与systemjs 不同

【讨论】:

  • declare var $: JQueryStatic 已经是jquery.d.ts 的最后一行了
  • 有些东西不见了,@types 安装所需的库是什么? tsconfig 中的类型在哪里?能否请您添加这些详细信息?
  • @Ayyash 如果库没有@types,只需通过npm install jquery --save 安装它们,在scriptsstyles 中添加js/css 文件angular-cli.json 就像"scripts":["../node_modules/path to file", "./assets/path to file" ]。在任何你想使用它的地方,只需在注解@Directive@Component之前添加declare var jQuery: any;
【解决方案4】:

你必须告诉你在哪里可以找到你的 jQuery typeScript 定义。这可以在一个 typings.d.ts 文件中完成,您可以在其中放置您的类型,如下所示:

///<reference path="../typings/jquery/jquery.d.ts" />

或者您可以通过节点安装类型并让您的配置自动加载它。这就是 angular-cli 所做的。

之后,要在 Angular2 中使用 jQuery,您必须了解基本机制。 Angular2 有它自己的 dom 表示,而 jQuery 操纵这个 dom。这就是为什么人们说“不要在 Angular2 中使用 jQuery”。这是不对的。 Angular2 为这个问题提供了解决方案。它称之为ControlValueAccessor。这样做的目的是在你的 jQuery 插件修改 DOM 时提醒 Angular,并在它修改 DOM 时让 Angular 通知你的插件。

让我通过一个日期选择器日历的例子来解释这一点。

import { Directive, ElementRef, OnInit, AfterViewInit, Input, forwardRef, OnDestroy } from '@angular/core';
import { Moment } from 'moment';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';


const DATE_PICKER_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => FnCalendarDirective),
  multi: true,

};

@Directive({
  selector: '[fn-calendar]',
  providers: [DATE_PICKER_VALUE_ACCESSOR],
})
export class FnCalendarDirective implements OnInit, AfterViewInit, ControlValueAccessor, OnDestroy {


  @Input() format: string = 'DD/MM/YYYY HH:mm';
  @Input() showClose: boolean = true;
  @Input() sideBySide: boolean = false;
  @Input() ngModel;

  private onTouched = () => { };
  private onChange: (value: string) => void = () => { };

  constructor(private el: ElementRef) {
  }

  ngOnInit() {

  }

  ngAfterViewInit() {
    $(this.el.nativeElement).datetimepicker({
      locale: 'fr',
      sideBySide: this.sideBySide,
      format: this.format,
      showClose: this.showClose,
      icons: {
        time: 'fa fa-clock-o',
        date: 'fa fa-calendar',
        up: 'fa fa-chevron-up',
        down: 'fa fa-chevron-down',
        previous: 'fa fa-chevron-left',
        next: 'fa fa-chevron-right',
        today: 'fa fa-bullseye',
        clear: 'fa fa-trash',
        close: 'fa fa-times'
      },
    }).on('dp.change', event => {
      let date: Moment = (<Moment>(<any>event).date);
      if (date) {
        let value = date.format(this.format);
        this.onChange(value);
      }
    });
    this.writeValue(this.ngModel);
  }

  writeValue(date: string) {
    $(this.el.nativeElement).datetimepicker().data('DateTimePicker').date(date);
  }

  registerOnChange(fn: any) {
    this.onChange = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouched = fn;
  }

  ngOnDestroy() {
    $(this.el.nativeElement).datetimepicker().data('DateTimePicker').destroy();
  }
}

这里重要的是 writeValue 方法,它让 Angular2 通知您的 jquery 插件正在产生更改。还有 registerOnChange,它可以让你通知 Angular2 你的插件对 DOM 进行了更改。

总之,使用 jQuery 的关键在于将 jQuery 插件封装在指令中,并实现一个 CustomValueAccesor 来处理插件和 Angular2 之间的通信。

要查找类型,您可以使用DefinitlyTyped GitHub,这是一个来自许多 js 库的类型定义的存储库。

  [1]: http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

【讨论】:

    【解决方案5】:

    你不应该不惜一切代价将 Angular 组件与 jQuery 捆绑在一起

    1. 加载带有&lt;script&gt;标签的jQuery。
    2. 添加 jQuery 文档就绪处理程序。
    $('文档').ready((函数($) { 返回函数(){ // DOM 准备好了,$ 是对 jQuery 的引用 // 是时候使用 $ 完成事情了 }; })(jQuery));

    优点

    • Angular 组件没有 jQuery 依赖。
    • 更容易测试、维护和重用此类组件。
    • jQuery 代码被隔离。

    但是,如果您需要在组件内部使用 jQuery,请使用服务或指令。

    如果您在加载部分视图时遇到问题,请使用文档节点上的 jQuery 事件处理程序和 jQuery 窗口加载处理程序。

    【讨论】:

      【解决方案6】:

      我们可以像下面这样使用:

      var jq=require('./jquery.min.js');
      .....
      export class AppComponent{
        ngOnInit(){
         jq();
         console.log($('body'))  // show:[body, prevObject: r.fn.init[1]]
                                 //ok!normal operation!
        }
      }
      

      【讨论】:

        【解决方案7】:

        最快最脏的方法:

        (<any>window).$('.alert')
        

        【讨论】:

          猜你喜欢
          • 2016-05-25
          • 2017-06-11
          • 1970-01-01
          • 1970-01-01
          • 2017-02-22
          • 2017-09-15
          • 2019-04-13
          • 2016-11-19
          • 2017-01-21
          相关资源
          最近更新 更多