【问题标题】:How are Javascript widgets made without iFrames?如何在没有 iFrame 的情况下制作 Javascript 小部件?
【发布时间】:2018-03-11 13:31:54
【问题描述】:

我有一个聊天小部件,我想将它嵌入其他人的网站。它看起来就像对讲机和所有其他聊天弹出窗口。无论您滚动到哪里,我都想让聊天弹出窗口粘在屏幕的右下角。但是,当我将聊天应用程序作为 iframe 导入并给它position: fixed; bottom: 0px; right: 15px; 时,iframe 并没有到达我期望的位置。

我意识到 iframe 不是嵌入式 JS 小部件的最佳选择,所有最好的嵌入式应用程序都从文件存储中导入 .js 文件。在网上搜索了几个小时后,我还没有找到关于如何制作那些连接到 a 并呈现小部件的 JS 文件的解释/教程。您甚至如何制作其中一个纯 JavaScript 应用程序,它们叫什么? (我认为不是 Web 组件,因为小部件已经存在很长时间了)。

对不起,如果这个问题有点菜鸟。在我尝试自己实施之前,我从来不知道这是一件事。谁能指出我如何开始制作 JS Web 小部件的正确方向?谢谢! (也许 ReactJS 到 VanillaJS 的转换器会很酷)

【问题讨论】:

    标签: reactjs iframe widget web-component


    【解决方案1】:

    纯 Javascript 应用程序称为 SPA - 单页应用程序 - 他们可以完全控制文档(页面)。但既然你问的是嵌入一个小部件,我认为这不是这个问题的意义所在(有大量信息。在网络上的 SPA 上)。

    我打算建议您以后使用 Web 组件来执行此操作 - 现在有可用的 polyfill 可以在几乎所有浏览器上运行 - 但是由于您的问题提到您想知道没有它是如何完成的,所以我下面详细介绍我的一种方法。

    在创建纯 JS 小部件时,您需要确保知道 a) 您无法控制全局空间,b) 它需要与页面的其余部分配合得很好。此外,由于您没有使用 Web 组件(并且正在寻找纯 javascript(无库)),因此您还必须“手动”初始化小部件,然后将其插入到所需位置的页面中 - 与声明性方法,您为您的小部件分配了一个 HTML 标记名称,您只需将其添加到文档中,就会发生奇迹:)

    让我这样分解:

    小部件工厂

    这是一个简单的 Javascript 小部件工厂 - create() 返回一个带有小部件的 HTML 元素:

    const Widget = Object.create({
        create(chatId) {
            const wdg = document.createElement("div")
            wdg.classList.add("chat-box");
            wdg.innerHTML = `<h1>Chat: ${ chatId }</h1>`;
            // Load your chat data into UI
            return wdg;
        }
    });
    

    要使用上述方法创建一个新的小部件(HTML 元素),您可以:

    const myWidgetInstance = Widget.create("chat-12345");
    

    并将这个小部件插入到页面中的给定位置(例如,在 ID 为“chat_box”的 DIV 元素内部,您可以:

    document.getElementById("chat_box").appendChild(myWidgetInstance);
    

    所以这是使用本机(Web)平台创建小部件的基础知识:)

    创建可重用/可嵌入的组件

    交付可重用和可嵌入组件时的关键目标之一是确保您不依赖全局空间。因此,您的交付方法(更像您的构建过程)会将所有内容打包在一个 JavaScript IIFD 中,这也将为您的所有代码创建一个私有范围。

    这些类型的单例可重用/可嵌入组件的另一个重要方面是,您的元素样式需要确保它们不会“泄漏”出来并影响页面的其余部分(需要与其他人相处融洽)。我不会在这里详细介绍这方面的内容。 (仅供参考:这也是 Web 组件真正派上用场的领域)

    这是一个聊天组件的示例,您可以将其添加到页面中您希望它出现的任何位置。该组件以&lt;script&gt; 标签的形式交付,其中包含所有代码:

    <script>(function() {
        const Widget = Object.create({
            create(chatId) {
                const wdg = document.createElement("div");
                wdg.classList.add("chat-box");
                wdg.innerHTML = `<h1>Chat: ${ chatId }</h1>`;
                // Load your chat data into UI
                return wdg;
            }
        });
    
        const myWidgetInstance = Widget.create("chat-12345");
        const id = `chat-${ Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1) }`;
        document.write(`<div id="${ id }"></div>`);
        document.getElementById(id).appendChild(myWidgetInstance);
    })();</script>
    

    所以你可以在多个地方使用它,只需将这个脚本标签放在所需的位置:

    <body>
        <div>
            <h1>Chat 1</h1>
            <script>/* script tag show above */</script>
        </div>
        ...
        <div>
            <h1>Chat 2</h1>
            <script>/* script tag show above */</script>
        </div>
    </body>
    

    这只是如何完成的示例方法。您必须添加更多以支持将选项传递给每个小部件(例如聊天 id)、定义样式以及其他可能的改进,以提高运行时效率。

    另一种方法

    您可以添加一次“脚本”并等待页面的其余部分加载,然后在文档中搜索一组“已知”元素(例如,任何 CSS 类为 chat-box 的元素),然后在其中初始化一个小部件(jQuery 使这种方法很流行)。

    示例: 请注意如何在 DOM 元素中使用 data 属性来存储更多特定于您的小部件的数据。

    <div class="chat-box" data-chatid="123"></div>
    
    <script>(function() {
        const Widget = Object.create({
            create(chatId) {
                const wdg = document.createElement("div");
                wdg.classList.add("chat-box");
                wdg.innerHTML = `<h1>Chat: ${ chatId }</h1>`;
                // Load your chat data into UI
                return wdg;
            }
        });
        const initWhenReady = () => {
            removeEventListener("DOMContentLoaded", initWhenReady);
            Array.prototype.forEach.call(document.querySelectorAll(".chat-box"), ele => {
                const myWidgetInstance = Widget.create(ele.dataset.chatid);
                ele.appendChild(myWidgetInstance);
            });
        };
        addEventListener('DOMContentLoaded', initWhenReady);
    })();</script>
    

    希望这会有所帮助。

    【讨论】:

    • 很好的答案!这正是我一直在寻找并最终做到的。方法#2 我发现它是易用性和功能性的最佳组合。谢谢保罗! :)
    【解决方案2】:

    在没有第三方库的情况下创建 Javascript 小部件的最佳方法是创建自定义元素。

    以下链接:Custom Elements v1 很好地介绍了这项技术。

    请参阅下面的最小示例:

    class Chat extends HTMLElement {
        connectedCallback () {
            this.innerHTML = "<textarea>Hello</textarea>"    
        }
    }
    
    customElements.define( "chat-widget", Chat )
    <chat-widget>
    </chat-widget>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 2020-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多