将 jQuery 和 bootstrap JS 与 stenciljs 组件一起使用

Using jQuery and bootstrap JS with stenciljs components

我们有使用 Angular 构建的应用程序,现在对于所有客户特定要求,我们希望使用 stencil js 构建 Web 组件。

想法是保持核心应用程序干净,而不是为特定的客户要求混入代码。

所以我们开始使用 Web 组件并坚持使用 Stencil JS。

我们面临的第一个问题是我们的网络组件将需要使用jquery、bootstrap js 以及一些第三方js。

我们希望将我们的组件构建为从外部封装,这意味着它们将处于阴影中 dom。

现在我有两个问题

1) 每个组件都包含 JS 库,如 jQuery、bootstrap js 等,这对我来说不是个好主意吗? 2) 我们如何将 jQuery 包含到 Web 组件中。

我尝试了很多方法,最后一个是在 stencil web 组件的构造函数中包含标签,但它不起作用。

export class TestComponent {

  @Prop() token: string;

  @State() test: string;
  @Element() private element: HTMLElement;

  constructor() {

    this.element.innerHTML = `
    <script src="../../assets/js/jquery.min.js"></script>

`;

所以问题是如何在阴影中的模板内置 Web 组件中使用 JS 第三方库 dom(阴影选项设置为 true)

欢迎就此发表任何意见,我们将不胜感激:)

对于大多数 Web 组件,我不会使用 jQuery,因为任何现代框架都不需要 dom 操作,大多数情况下您只需关注渲染功能。

我做了一个测试,在使用 npm i jquery:

添加 jquery 依赖后,这似乎工作正常
import { Component, h } from '@stencil/core';
import $ from "jquery";

@Component({
    tag: 'app-test'
})
export class AppTest {  
    render() {
        const version = $().jquery;
        return [
            <div>
                jQuery Version: {version}
            </div>
        ];
    }
}

对我来说,您似乎有点歪曲了 Stencil 和 Web 组件的用途。我做这件事从来没有这种痛苦,但要回答你的问题:这取决于你想要实现的目标。例如,当您在 Light-dom 中导入 Jquery 时,您可以在 shadow-dom 中原生使用 Jquery。

Index.html

<script src="/jquery.min.js"></script>
</head>
<body>
  <my-component></my-component>
  <div id="test2"></div>
</body>

我的-component.tsx

  testfunc(){
    console.log($().jquery);
    console.log($("#test"));
    console.log($("#test2"));
  }
  render() {
    return <div id="test">
            <button onclick={this.testfunc.bind(this)}>asd</button>
           </div>;
  }

testfunc 的结果在这里:

如您所见 - 您已经可以使用 Jquery,只需将其放入您的主应用程序即可。但是有一些限制,如您所见,您可以访问 light-dom 中的所有 DOM 元素,但可以访问 shadow-dom 中的 none 元素。这就是为什么找不到#test 而找到#test2 的原因。

但有趣的是,我还可以在 index.html 中的 #test2 div 容器中加载文件。只需使用网络组件内部的 jquery .load 函数即可。

$( "#test2" ).load( "/index.html" );

当您想使用 $ 选择器获取 Web 组件 (shadow-dom) 中的元素时,事情会变得有点复杂,但绝对没有理由这样做: Stencil 有它自己的 this.el.shadowRoot.querySelector() ,你可以在组件内部使用它,或者你可以直接将变量粘贴到 DOM 元素,如下所示:

  render() {
    return <div ref={el => this.element = el}>
            <button onclick={this.testfunc.bind(this)}>Press Button</button>
           </div>;
  }

您可以在网络组件中使用 this.element 来访问 div。 但通常你也可以尝试在组件装饰器中使用 scoped 标志。比你通常可以使用灯 dom 中的所有东西,因为没有这样的硬隔离:

    @Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true ---> instead of this
  scoped: true ---> try this
})

总结一下:我认为通常没有充分的理由在 Web 组件中使用这些库。但是,如果您真的需要 - 它始终取决于您的需求以及您想要/需要实现的目标。 Stencil 有一些非常有用和好的内置功能。

我会考虑以完全相反的方式使用 Stencil。在 Stencil 中创建您的通用内容,而不是在 Angular 中创建特定于客户的内容。例如,您从一个简单的 "button" 作为模板中的 Web 组件开始。

export class CoolestButton {
      render() {
        return <button class="coolest-button"></button>
      }
}

比您创建另一个使用 "button" 作为基础的网络组件 "dropdown"。

export class CoolestDropdown {
      ...
       someDropdownFunctions(){}
      ...
      render() {
        ...
        return [<coolest-button></coolest-button>, ...dropdownSpecific]
      }
}

比您创建一个包含下拉菜单的页眉组件。

export class CoolestHeader {
      render() {
        return [
<coolest-dropdown data="NavPoint1,NavPoint2,NavPoint3">Home</coolest-dropdown>, 
<coolest-dropdown data="About-us,Impress">Home</coolest-dropdown>
];
      }

Stencil 的惊人之处在于您可以使用最酷按钮的 10000 倍,但它只会加载一次。这就是为什么像这样嵌套网络组件绝对是编码糖分。比起您拥有一个非常强大的库,您可以在所有客户项目中使用它。当您编写测试时 - 每个客户应用程序也都经过测试,因为它们具有相同的基础。

jQuery 可以在 Shadow DOM 中使用,使用 stenciljs 不会有任何问题。

如果 jQuery 已经添加到灯光 DOM 是否必须在 Web 组件中进行检查。 在某些情况下,当我们再次加载 jQuery 时,它会重置 light DOM 中的事件,从而在 Light DOM 中造成问题。 您可以使用 console.log($) 并尝试捕获以检查其是否加载了其他明智的负载。

如果为 jQuery 安装 'types',

$ 也可以工作。

所以基本上只有当外部库尝试使用

访问DOM时才重要
document.getElementById 

在库文件中。

内阴影DOM

this.el.shadowroot

必须使用。关联的 css 也应该添加到 webcomponent 中。