首页 > 解决方案 > 在 Angular 2 中使用 Jquery 函数调用

问题描述

我正在尝试在我的 Angular 2 应用程序上使用这个convForm jquery 插件。

我已将 jquery 和 convForm 成功安装到我的项目中,编辑 angular.json 文件。

插件示例中,它们具有回调函数,其 html 字段位于属性下:data-callback

我不明白如何在角度组件中使用这些回调函数,因为回调不使用打字稿调用函数。

转换-form.html

<div id="chat" class="conv-form-wrapper">
    <form action="/" method="post" class="hidden" onsubmit="event.preventDefault()">
         <input type="number" data-callback="amount"
              data-conv-question="What is the amount you like ?" name="amount"
              data-pattern="^[0-9]*$">
    </form>
 </div>

转换格式.ts

import { Component, OnInit } from '@angular/core';
declare let $: any;

@Component({
    selector: 'app-conv-form',
    templateUrl: './conv-form.component.html',
    styleUrls: ['./conv-form.component.scss']
})
export class ConvFormComponent implements OnInit {
    ngOnInit() {
          let convForm = $('#chat').convform({ selectInputStyle: 'disable' });
    }

    amount(stateWrapper, ready) {
    if(stateWrapper.current.answer.value.length > 0){
        ready();
    }
  }
}

呈现此问题时,我收到错误消息:

Uncaught TypeError: window[convState.current.input.callback] is not a function
at Object.onInputSubmit 

我如何像示例一样调用回调函数但有角度?

相当于:

<script>
    function google(stateWrapper, ready) {
        window.open("https://google.com");
        ready();
    }
</script>

标签: jqueryangularjquery-plugins

解决方案


jQuery 插件需要一个全局回调,即。一个是窗口对象。在示例中,它们声明的回调只是 a 中的顶级函数,<script>因此它们将显示在窗口上。您在 Angular 组件的类中声明的方法将位于每个组件实例上,因此无法全局使用,即。jQuery 插件不会看到它。

我真的反对混合使用 jQuery 和 Angular,因为这总是会导致很大的黑客攻击,但我想无论如何你都会这样做,所以这里有一个可能的解决方案。我没有任何 angular+jQuery 项目,所以无法测试解决方案,但我希望它有所帮助。

所以你必须将对你的组件实例的方法之一的引用放到窗口中,这样它就可以全局使用,但会指向你的组件实例。请参阅下面的扩展ngOnInit。还要注意bind要能够thisamount方法中使用哪个来访问角度组件。

另请注意,如果您ConvFormComponent在页面上多次显示,它们会干扰,可能只有最后一个回调会起作用。如果需要多个实例,则需要引入一种机制,使globalAmountCb每个ConvFormComponent实例都具有唯一性。

另外,请注意ngOnDestroy一旦组件被拆除,我删除了回调,您还应该从 jQuery convForm 中拆除/关闭/退出。

<div id="chat" class="conv-form-wrapper">
    <form action="/" method="post" class="hidden" onsubmit="event.preventDefault()">
         <input type="number" data-callback="globalAmountCb"
              data-conv-question="What is the amount you like ?" name="amount"
              data-pattern="^[0-9]*$">
    </form>
 </div>
import { Component, OnInit, OnDestroy } from '@angular/core';
declare let $: any;
declare window: any;

@Component({
    selector: 'app-conv-form',
    templateUrl: './conv-form.component.html',
    styleUrls: ['./conv-form.component.scss']
})
export class ConvFormComponent implements OnInit, OnDestroy {
    ngOnInit() {
        // note the `globalAmountCb` name in the template above too
        window.globalAmountCb = this.amount.bind(this).
        let convForm = $('#chat').convform({ selectInputStyle: 'disable' });
    }

    ngOnDestroy() {
        window.globalAmountCb = undefined;
        // also maybe tear down the `convForm` thing
    }

    amount(stateWrapper, ready) {
    if(stateWrapper.current.answer.value.length > 0){
        ready();
    }
  }
}

更新:澄清为什么和什么样的清理可能是必要的。

this.convForm当您离开此页面时,角度组件类将不再使用,并且很快就会被垃圾收集,因此您是否显式删除引用无关紧要。

但只有那些 DOM 元素会被移除,Angular 知道这些元素。Angular 只知道在组件模板中定义并由 Angular 渲染的 DOM,但它不知道您通过 jQuery 添加到 DOM 中的内容,因此它不会删除这些内容。如果幸运的话,jQuery 插件只在 angular 组件下添加了 DOM 元素,所以当组件被移除时,jQuery 插件的 DOM 元素也会被移除。

但可能是 jQuery 插件在 DOM 树的顶部添加了一些东西,可能在 angular 应用程序之外(对话框和其他弹出框通常像这样工作),并且在 angular 组件被销毁时不会被删除.

如果 jQuery 插件提供了某种清理机制来删除它们,你必须查看它。


推荐阅读