SPA에서 외부 스크립트를 동적으로 로드하는 방법

16199 단어 Reactreact-hooks

무엇을 하는가



SPA에서 외부에서 읽는 스크립트의 코드<script>~~~</sccript>를 페이지에 의해 전환할 수 있을까를 조사했으므로 정리합니다.

↓ 이런 느낌입니다.

react-header 에서 타이틀을 변경하는 요령으로 동적으로 로드하려고 했습니다만, 발화시킬 수 없었기 때문에 다음과 같은 방법을 취했습니다.
사이트 전체에서 사용할 때는 글로벌하게 두면 됩니다만, 사용 개소가 한정되는 경우는 이러한 사용법을 해 봐도 좋을지도 생각합니다

구성



PageA와 PageB가 있으며, PageB에서만 외부 스크립트를 읽습니다.
(외부 스크립트는 alert.js라는 alert를 발행 할 js를 준비했습니다)
.
// htmlにrender
├── index.js
└── modules
       //↓react-routerで出しわけ
    ├── App.js
    | // ↓PageAのコンポーネント(外部スクリプトの読み込み無し)
    ├── PageA.js
    | // ↓PageBのコンポーネント(外部スクリプトの読み込みあり)
    ├── PageB.js
    | // ↓別コンポーネントで読み込んだ外部スクリプトを削除する関数
    ├── clearScript.js
    | // ↓scriptタグを動的に作成する関数
    └── loadDynamicScript.js


App.js



react-router로 나오는 것만을 기술하고 있습니다.

app.js
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

import PageA from "./PageA";
import PageB from "./PageB";

// React-Routerのルーティングのみ
const App = () => {
  return (
    <Router>
      <Switch>
        <Route path="/" exact>
          <PageA />
        </Route>
        <Route path="/B" exact>
          <PageB />
        </Route>
      </Switch>
    </Router>
  );
};

export default App;



PageA.js



PageA의 구성 요소 * 외부 스크립트를로드하지 않음

PageA.js
import React, { useEffect } from "react";
import { BrowserRouter as Router, useHistory } from "react-router-dom";

import { clearScript } from "./clearScript";

// 外部スクリプトの読み込み無し
const PageA = () => {
  const history = useHistory();

  // 別ページで外部スクリプトが読み込まれている場合削除する
  useEffect(() => {
    clearScript();
  }, []);

  return (
    <div>
      <p>this is PageA</p>
      <button onClick={() => history.push("/B")}>Next</button>
    </div>
  );
};

export default PageA;


PageB.js



PageB의 컴퍼넌트 *외부 스크립트의 로드 있음
이번에는 react-hooks를 사용했지만 componentWillMount로 호출하면 OK입니다!

PageB.js
import React, { useState, useEffect } from "react";
import { BrowserRouter as Router, useHistory } from "react-router-dom";

import { loadDynamicScript } from "./loadDynamicScript";

const PageB = () => {
  const [hasScript, setHasScript] = useState(false);

  // 外部スクリプトを動的に読み込む
  useEffect(() => {
    loadDynamicScript(() => {
      setHasScript(true);
    });
  }, [hasScript]);

  const history = useHistory();
  return (
    <div>
      {/* 外部スクリプトの読み込み完了後に表示 */}
      {hasScript ? (
        <div>
          <p>this is PageB</p>
          <button onClick={() => history.goBack()}>Go Back</button>
        </div>
      ) : (
        ""
      )}
    </div>
  );
};

export default PageB;


clearScript.js



다른 컴퍼넌트로 읽어들인 외부 스크립트를 삭제하는 함수입니다.
PageA로 전환하면 PageB에서 append된 스크립트 태그가 남아 있으므로 그쪽을 삭제합니다.

clearScript.js
// 作成したscriptタグを削除する
export const clearScript = () => {
  const externalScript = document.getElementsByClassName("externalScript");

  if (externalScript) {
    console.log(externalScript);
    while (externalScript.length) {
      externalScript.item(0).remove();
    }
  }
};


loadDynamicScript.js



외부 스크립트(<script></script> 태그)를 동적으로 만들고 <body></body> 안에 삽입할 함수를 만듭니다.

loadDynamicScript.js
export const loadDynamicScript = callback => {
  // スクリプトに付与するIDを指定
  const scriptId = "alert";
  const existingScript = document.getElementById(scriptId);

  // scriptががなければ新しく作成する
  if (!existingScript) {
    const script = document.createElement("script");
    script.id = scriptId;
    script.type = "text/javascript";
    // 外部スクリプトのURLはコチラに
    script.src = "./alert.js";
    // 削除するためのtargetとしてclassNameを付与
    script.className = "externalScript";
    // 作成したtagをappend
    document.body.appendChild(script);

    script.onload = () => {
      if (callback) callback();
    };
  }

  if (existingScript && callback) callback();
};


더 좋은 방법이 있다면? ? 라고 생각하면서 쓰고 있었습니다. .
뭔가 좋은 방법이 있으면 가르쳐 주고 싶습니다

참고 기사

좋은 웹페이지 즐겨찾기