首页 > 解决方案 > React 中的 Fancybox

问题描述

我正在尝试在我的 React 应用程序中包含 fancyBox。我在 index.html 文件中包含了 css 和 js

<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/fancybox/2.1.5/jquery.fancybox.min.css" media="screen">
<script src="//cdnjs.cloudflare.com/ajax/libs/fancybox/2.1.5/jquery.fancybox.min.js"></script>

然后,在我的组件中,我尝试使用它:

...

import "datatables.net-dt/js/dataTables.dataTables"
import "datatables.net-dt/css/jquery.dataTables.min.css"

const $ = require("jquery");
$.DataTable = require("datatables.net");
...


componentDidMount = async () => {
     $(() => {
         $('#myTable').DataTable({
             pageLength : 5,
             lengthMenu: [[5, 10, 50, -1], [5, 10, 50, 'All']]
         });
            
         $(".fancybox").fancybox({
             openEffect: "none",
             closeEffect: "none"
         });  
     });
}

...

render() {
   ...

   <div className="col-lg-3 col-md-4 col-xs-6 thumb">
    <a href="https://images.pexels.com/photos/62307/air-bubbles-diving-underwater-blow-62307.jpeg?auto=compress&cs=tinysrgb&h=650&w=940" className="fancybox" rel="ligthbox">
      <img src="https://images.pexels.com/photos/62307/air-bubbles-diving-underwater-blow-62307.jpeg?auto=compress&cs=tinysrgb&h=650&w=940" className="zoom img-fluid " alt />
    </a>
  </div>

  ...

它正在返回: TypeError: $(...).fancybox is not a function

标签: javascriptreactjsfancybox

解决方案


通过使用自定义 React Hooks 解决了这个问题。同样的逻辑也适用于 next.js

  • 自定义反应钩子:
import { useEffect } from "react";

// The page will pass in the third party libraries it needs to use
export default function useThirdPartyLib(pagescripts) {
  useEffect(() => {
    function prepareScripts(...scripts) {
      return scripts.reduce((accu, script, index) => {
        const scriptTag = document.createElement("script");
        scriptTag.src = `/js/${script}`;
        scriptTag.id = `${script.split(".")[0].trim()}_${index.toString()}`;
        scriptTag.async = false;
        accu.push(scriptTag);
        return accu;
      }, []);
    }

    // Mount all prepared scripts onto the body
    prepareScripts(...pagescripts).map((script) => {
      return document.body.appendChild(script);
    });

    // Do Clean ups
    return () => {
      prepareScripts(...pagescripts).map((script) => {
        const body = document.getElementsByTagName("BODY")[0];
        const targetTag = body.querySelector(`#${script.getAttribute("id")}`);
        return targetTag.parentNode.removeChild(targetTag);
      });
    };
  }, []);
}
  • 在使用 fancyBox 的组件内使用
import useThirdPartyLib from "../../../hooks/third-party-libs";

export default function SplashScreen() {
  useThirdPartyLib(["jquery.js", "plugins.js", "modal.js"]);
  return (
    <div style={{ display: "none" }} id="splash_screen">
      <a href="/covid-19-test" className="campaign-wrapper">
        <img
          src="/images/campaigns/campaign-1.png"
          width="731"
          height="731"
          alt="Campaign Pic"
        />
      </a>
    </div>
  );
}
  • 包含 jQuery fancybox 标记的 modal.js 文件
jQuery(function () {
  if ($("#splash_screen").length) {
    $.fancybox.open({
      src: "#splash_screen",
      type: "inline",
      btnTpl: {
        smallBtn:
          '<button type="button" data-fancybox-close class="fancybox-button fancybox-close-small my-close" title="{{CLOSE}}"><span class="close-text">Close this Window</span>' +
          '<span class="icon"><svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="0 0 28 28"><path d="M14 16l12-12-1-1-12 12-12-12-1 1 12 12-12 12 1 1 12-12 12 12 1-1z"/></svg></span>' +
          "</button>"
      }
    });
  } // EndIf
}); // Docx ready

推荐阅读