reactjs - 如何在没有 iFrame 的情况下制作 Javascript 小部件?

标签 reactjs iframe widget web-component

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

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

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

最佳答案

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

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

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

让我这样分解:

小部件工厂

这是一个简单的 Javascript Widget 工厂 - 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);

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

创建可重用/可嵌入组件

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

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

这是一个聊天组件的示例,您可以将其添加到页面中您希望它出现的任何位置。该组件以 <script> 的形式交付。带有所有代码的标签:
<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 使这种方法很流行)。

例子:
注意 data属性可用于 DOM 元素来存储更多特定于您的小部件的数据。
<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>

希望这可以帮助。

关于reactjs - 如何在没有 iFrame 的情况下制作 Javascript 小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49220533/

相关文章:

javascript - super 表达式必须为 null 或函数,而不是未定义的 - reactjs

html - iframe 中的历史 pushState,影响 Chrome 中的父窗口布局?

android - Flutter:让 iFame 在 Android 设备上全屏显示

javascript - 为什么 "window.top.location"在 iframe 中工作?

java - 在自定义小部件中模板化成员字段?

javascript - ReferenceError - 未定义任何内容(React Js)

javascript - 类型错误 : Cannot read property 'map' of undefined using ReactJs

c++ - 在 QApplication MainWindow 上将 Qt3d View 渲染为小部件

c# - 在 Internet Explorer 7 中看不到小部件

javascript - 将项目数据传递给 react 模态