代码之家  ›  专栏  ›  技术社区  ›  Kangzeroo

没有iFrame的Javascript小部件是如何制作的?

  •  6
  • Kangzeroo  · 技术社区  · 7 年前

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

    我意识到iFrame对于嵌入式JS小部件来说是次优的,所有最好的嵌入式应用程序都在导入。来自文件存储的js文件。在线搜索了几个小时后,我还没有找到一个关于如何制作那些连接到的JS文件并呈现小部件的说明/教程。你是如何制作这些纯javascript应用程序的,它们叫什么?(我认为不是web组件,因为有小部件已经有很长时间了)。

    抱歉,如果这个问题有点不着边际。直到我自己尝试实现它,我才知道这是一件事。有人能告诉我如何开始制作JS web小部件的正确方向吗?非常感谢。(也许ReactJS到VanillaJS转换器会非常酷)

    2 回复  |  直到 7 年前
        1
  •  20
  •   zelusp    5 年前

    纯Javascript应用程序称为SPA(单页应用程序),它们可以完全控制文档(页面)。但既然你问起嵌入一个小部件的问题,我不认为这就是这个问题的所在(网上有很多关于SPA的信息)。

    我本来打算建议您使用Web组件来实现这一点——现在有很多Polyfill可以在几乎所有浏览器上实现这一点——但由于您的问题提到您想知道没有它是如何实现的,因此我将在下面详细介绍我的一种方法。

    当创建纯JS小部件时,您需要确保您知道a)您不能控制全局空间,b)它需要很好地处理页面的其余部分。此外,由于您没有使用Web组件(并且正在寻找纯javascript(没有libs)),因此您还必须“手动”初始化小部件,然后将其插入到所需位置的页面中,这是一种去极化方法,在这种方法中,您为您的小部件分配了一个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\u box”的DIV元素内部),您需要:

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

    因此,这是使用本机(web)平台创建小部件的基础:)

    创建可重用/可嵌入组件

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

    这些类型的单例可重用/可嵌入组件的另一个重要方面是,您的元素样式需要确保它们不会“泄漏”并影响页面的其余部分(需要与其他人友好相处)。我不会在这里详细介绍这个领域。(仅供参考:这也是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>
    

    希望这有帮助。

        2
  •  -1
  •   Supersharp    7 年前

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

    以下链接: Custom Elements v1 是对这项技术的一个很好的介绍。

    请参见下面的一个简单示例:

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