为了账号安全,请及时绑定邮箱和手机立即绑定

如何在不同网站间共享组件:一份简单指南

标签:
React.JS Vue.js

在创建网站应用时,遇到需要将组件移动到其他网站的任务很常见。通常这些组件是一些通用的按钮、底部导航、顶部导航等元素。

部件

例如,我们可以拿按钮组件作为一个例子,我们将它在组件间传递。它看起来会是这样的。

    <button class="button">点我</button>
    <style>
      .button {
        background-color: #4caf50;
        color: white;
        border: none;
        padding: 12px 24px;
        text-align: center;
        text-decoration: none;
        font-size: 16px;
        border-radius: 5px;
        cursor: pointer;
        transition: background-color 0.3s, transform 0.2s;
      }

      .button:hover {
        background-color: #45a049;
      }

      .button:active {
        transform: scale(0.95);
      }
    </style>

切换到全屏模式,退出全屏模式

网站上的结果会是这样:

按钮

现在,让我们拿两个站点来做例子,你需要让这两个站点共用同一个组件。假设这两个站点是 example1 和 example2。它们可以托管在不同的地方。一个站点可以从 GitHub 部署,另一个可以从本地服务器部署。

现在,主要的问题出现了:该怎么分?

几种分享的方法

我来简单说说常用的几种方法,从最简单到最实用的。

点击这里查看共享组件的图片

这两种方法大致如下。

1. 输出到文件并通过脚本连接方式

这种方法假设有一个函数可以返回HTML代码。而且,这个函数可以通过一个远程文件调用。这个文件放在哪儿都没关系,你只需要在那里引用它。

创建按钮的JavaScript文件

    // buttonModule.js
    (function (global) {
      // 定义一个 createButton 函数
      function createButton() {
        // 创建一个 <style> 元素并添加样式
        const style = document.createElement('style');
        style.textContent = `
          .button {
            background-color: #4caf50;
            color: white;
            border: none;
            padding: 12px 24px;
            text-align: center;
            text-decoration: none;
            font-size: 16px;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s, transform 0.2s;
          }
          .button:hover { /*鼠标悬停时的样式*/
            background-color: #45a049;
          }
          .button:active { /*鼠标点击时的样式*/
            transform: scale(0.95);
          }
        `;

        // 创建按钮元素
        const button = document.createElement('button');
        button.className = 'button';
        button.textContent = '点击我';

        // 返回包含样式和按钮的对象
        return { style, button };
      }

      // 将 createButton 函数暴露到全局作用域
      global.buttonModule = {
        createButton,
      };
    })(window);

全屏模式, 退出全屏

例子1/root/index.html
例子2/root/index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>按钮模块</title>
      <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://.../buttonModule.js"></script>
    </head>
    <body>
      <div id="wrapper"></div>
      <script>
        // 使用按钮模块:
        const { style, button } = buttonModule.createButton();
        const wrapper = document.getElementById("wrapper");
        wrapper.append(style); // 将样式附加到文档
        wrapper.append(button); // 将按钮添加到页面
      </script>
    </body>
    </html>

全屏,退出全屏

在这里,我们通过一个与我们两个站点都不相连的站点来连接模块。它也可能是同一个GitHub。

特点(优点):

  • 使用标准的 HTML <script> 标签即可轻松实现,无需额外设置。
  • 不需要现代工具或配置,如 Webpack 或 Vite。
  • 适合小型单页面应用或快速实验使用。
  • 极简的配置,加快开发过程。
  • 可无缝集成到已经依赖全局变量的现有项目中。

不足之处:

  • 如果有大量的组件,就会有上千个脚本,这使得这种方法只适合单一使用场景。
  • 向全局作用域添加变量或对象,增加了命名冲突的可能性。
  • 当使用多个脚本时,很难避免冲突。
  • 使得项目更难扩展或重构,从而增加复杂性。
  • 脚本依赖于正确的加载顺序,这需要手动管理。
  • 维护起来比较困难,也不符合当前的最佳实践。

2. 利用第三方库并将组件移到API中

为此方法,我们将使用类似于 HMPL 的模块。它能帮助您用简单的基于对象的模板连接服务器组件。首先,让我们将组件连接到服务器上。创建一个单独的 HTML 文件,并通过一个 API 请求来提供它。如下是 .html 文件的内容:

button.html

    <button class="button">点击按钮</button>
    <style>
      .button {
        background-color: #4caf50;
        color: white;
        border: none;
        padding: 12px 24px;
        text-align: center;
        text-decoration: none;
        font-size: 16px;
        border-radius: 5px;
        cursor: pointer;
        transition: background-color 0.3s, transform 0.2s;
      }

      .button:hover {
        background-color: #45a049;
      }

      .button:active {
        transform: scale(0.95);
      }
    </style>

全屏显示 退出全屏

之后,我们需要将这个文件转移到服务器上。后端用Node.js。我们将用express.js作为创建API的流行框架。首先,我们会设置一个路由来接收我们的组件。

buttonController.js

    const express = require("express");
    const expressRouter = express.Router();
    const path = require("path");

    const 按钮控制器 = (req, res) => {
      res.sendFile(path.join(__dirname, "../button.html"));
    };

    expressRouter.use("/getButton", 按钮控制器);

全屏,退出全屏

app.js(应用主文件)

    const express = require("express");
    const path = require("path");
    const bodyParser = require("body-parser");
    const cors = require("cors");
    const PORT = 8000;
    const app = express();
    const routes = require("./routes/buttonController");

    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cors({ origin: true, credentials: true }));

    app.set(express.static(path.join(__dirname, "src")));

    app.use("/api", routes);

    app.listen(PORT);

全屏模式:进入全屏 退出全屏

之后,我们将会有一个途径可以轻松取出这个组件。在网站上我们可以连接HMPL。它可以通过几种方式连接,我们来看看主要的几种方式:

通过脚本:

    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://unpkg.com/json5/dist/index.js"></script> <!-- 引入json5的库 -->
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://unpkg.com/hmpl-js/dist/hmpl.min.js"></script> <!-- 引入hmpl-js的库 -->

全屏 退出全屏

通过进口

    import hmpl from "hmpl-js";

全屏模式 退出全屏

我们使用方法一,因为index.html在我们的网站上默认是首页。

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>按钮组件</title>
      </head>
      <body>
        <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://unpkg.com/json5/dist/index.js"></script>
        <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://unpkg.com/hmpl-js/dist/hmpl.min.js"></script>
        <script>
          // 编译模板函数
          const templateFn = hmpl.compile(
            `<div id="wrapper">{{ src: "https://.../api/getButton" }}</div>`
          );
          // 获取模板函数返回的按钮包裹元素
          const btnWrapper = templateFn().response;
          // 将按钮包裹元素添加到文档主体中
          document.body.append(btnWrapper);
        </script>
      </body>
    </html>

全屏模式 退出全屏

在这里,我们差不多像第一种方法一样操作,但关键是现在你可以放心地重复使用这个组件。比如你可以这样操作:

// `btnWrapper1` 和 `btnWrapper2` 是从模板函数中获取的响应。
const btnWrapper1 = templateFn().response;
const btnWrapper2 = templateFn().response;

切换到全屏模式,退出全屏

此外,该模块还提供了许多其他功能,例如指示器(指标)、错误处理功能等。由于该模块基于 fetch,您可以有效自定义请求,并实现更多功能。

特点(优点):

  • 重用组件
  • 适合从小型应用到包含数千个组件的大型应用
  • 特别针对这种以服务器为中心,在客户端显示组件的方法,提供了大量的功能
  • 使用方式非常灵活

不足之处:

  • 连接两个脚本
  • 创建额外API

这种方法实际上是在客户端实现了类似SSR的思想,但缺少了爬虫能够访问的关键元素。不过,这种方法确实很酷,可以简化解决问题的过程。

结尾

视情况而定,你可以选择第一种方法或第二种方法。在第一种方法中,你完全掌控整个过程,但如果你需要处理多个组件,这种方法就不太适合,因为你得不断导入文件,这并不是很好。

谢谢大家的阅读,希望这篇文章对你们有帮助!

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消