2

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

想法是保持核心应用程序的清洁,而不是为特定的客户需求混合代码。

所以我们提出了 Web 组件,并坚持使用 Stencil JS。

我们面临的第一个问题是我们的 Web 组件还需要使用 jquery、bootstrap js 和一些第三方 js。

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

现在我有两个问题

1) 每个组件都包含 jQuery、bootstrap js 等 JS 库是否是一种好习惯,因为在我看来这不是一个好主意 2) 我们如何将 jQuery 例如包含到 Web 组件中。

我尝试了很多方法,最后一种是在模板 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>

`;

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

欢迎对此提出任何意见,我们将不胜感激:)

4

4 回答 4

1

对于大多数 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>
        ];
    }
}
于 2019-10-26T20:38:21.327 回答
1

对我来说,这听起来像是你有点弯曲了 Stencil 和 Web 组件的用途。我从来没有这样做过这种痛苦,但要回答你的问题:这取决于你想要达到的目标。例如,当您在 Light-dom 中导入 Jquery 时,您可以在 shadow-dom 内本地使用 Jquery。

索引.html

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

我的组件.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 访问。这就是为什么没有找到#test 而#test2 是的原因。

但有趣的是,我还能够在 index.html 中的这个#test2 div 容器中加载一个文件。只需使用 web 组件内部的 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>;
  }

比你可以在 web 组件中使用 this.element 来访问 div。但总的来说,您也可以尝试在组件装饰器中使用作用域标志。比您通常可以使用 light dom 中的所有内容,因为没有那么硬的隔离:

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

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

于 2019-10-26T21:13:00.653 回答
0

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

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

比您创建另一个使用“按钮”作为基础的 Web 组件“下拉列表”。

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

比您创建一个存在下拉列表的 Header 组件。

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 倍最酷的按钮,但它只会加载一次。这就是为什么像这样嵌套 Web 组件绝对是编码糖。比您拥有一个非常强大的库,您可以在所有客户项目中使用它。当您编写测试时 - 每个客户应用程序也都经过测试,因为它们具有相同的基础。

于 2019-10-26T21:48:13.573 回答
0

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

如果 jQuery 已经被添加到 light DOM 中,或者没有,必须在 web 组件中进行检查。在某些情况下,当我们再次加载 jQuery 时,它会重置 light DOM 中的事件,从而在 Light DOM 中创建问题。您可以使用 console.log($) 并尝试并捕获以检查其是否以其他方式加载。

如果您为 jQuery 安装“类型”,$ 也将起作用。

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

document.getElementById 

在库文件中。

内部阴影 DOM

this.el.shadowroot

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

于 2021-08-08T08:23:22.220 回答