Javascript 및 iFrame

29666 단어 htmltutorialjavascript
제목에서 내가 쓸 것은 JavascriptIframes인 것을 알고 있다.개발자나 블로그 작성자의 일상생활에서 Iframe를 당신의 사이트에 끼워 넣는 것은 매우 간단합니다.
예를 들어 유튜브 영상을 사이트에 삽입해야 한다면 간단하게 유튜브에서 코드를 복사해서 사이트에 붙일 수 있다.
<iframe width="560" height="315" src="https://www.youtube.com/embed/$SOME_ID" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
이것이 바로 내가 말한 단도직입적이다.
나는 이 점을 알고 몇 달 전에 평론 플러그인 Hyvor Talk 을 개발하기 시작했다.이것은 결코 간단하지 않다.본문에서 나는 원인을 설명할 것이다.이 플러그인을 만들 때 나는 많은 것을 배웠고 기교를 설계했다.나는 본문에서 이런 것들을 설명할 것이다.만약 플러그인을 개발하거나 Iframes (댓글 플러그인과 유사) 를 사용하여 다른 사이트에 불러오는 것을 개발할 계획이라면, 본고는 어떤 작업을 조직적으로 완성하는 방법을 이해하는 데 도움을 줄 것이다.이 밖에 나는 이런 제품을 개발할 때 직면할 수 있는 장애를 어떻게 극복하는지 설명할 것이다.
이 강좌에서, 플러그인을 만들고 있다면, 이 플러그인은 다른 사이트의iframe에 불러옵니다. (저는 이 다른 사이트의 소유자를'클라이언트'라고 합니다.)그 밖에 귀하의 사이트는 pluginx.com, 고객 사이트는 client.com입니다.

Iframes


우선 Iframe이 무엇인지 살펴보겠습니다.

The HTML Inline Frame element () represents a nested browsing context, embedding another HTML page into the current one - MDN


본고에서 저는 웹 사이트에 HTML 코드를 추가하는 것이 아니라 Javascript로 iFrame을 처리하는 방법을 중점적으로 소개하겠습니다.

왜 우리는 정말 자바스크립트가 필요합니까?


Javascript는 Iframe에 대한 더 많은 제어를 제공합니다.특히, iframe의 내용이 변경될 때, 자바스크립트를 사용하여 iframe의 크기를 자동으로 조정할 수 있습니다.이것은 iframe(당신의 사이트)와 사이트(다른 사람의 사이트) 간의 통신이 필요합니다.따라서 가장 좋은 방법은 클라이언트에게 <iframe> 코드를 제공하는 것이 아니라 클라이언트에게 자바스크립트 파일을 추가하는 것이다.
고객은 코드를 그의 사이트에 추가했다.코드는 <script> 태그와 <div> 태그 (iframe 용기) 를 포함합니다.
<html>
<head>
   ...
</head>
<body>
   ...
   <div id="pluginx-iframe-container"></div>
   <script src="https://pluginx.com/iframe-loader.js"></script>
</body>
현재, 우리는iframe 불러오는 프로그램을 작성할 수 있습니다.js, 도메인에 관리되는 HTML 페이지를 로드합니다.

Iframe 추가


이 작업에는 간단한 Javascript가 필요합니다.기억해야 할 것은 모든 변수를 local scope 에 저장하는 것입니다.이것은 코드를 self-invoking function 에 봉인하여 실현할 수 있다.이것은 JS 변수와 클라이언트 사이트의 JS 변수 사이의 충돌을 방지할 수 있다.만약 webpack 같은 귀속기를 사용한다면, 이것은 필수적인 것이 아닙니다. 왜냐하면 웹팩은 모든 변수를 국부적으로 하기 때문입니다.
(function() {

   var iframe = document.createElement("iframe");
   iframe.src = "https://pluginx.com/iframe"; // iframe content (HTML page)
   iframe.name = "pluginx-main-iframe"; // this is important

})(); 
잠시 후 나는 name 속성의 중요성을 설명할 것이다.고유 이름을 설정해야 합니다.
다음 속성을 추가하면 모든 브라우저에서 iframe을 볼 수 있습니다.
iframe.width = "100%";
iframe.allowTranparency = true;
iframe.tabIndex = 0;
iframe.scrolling = "no";
iframe.frameBorder = 0;

iframe.style.border = "none";
iframe.style.overflow = "hidden";
iframe.style.userSelect = "none";
iframe.style.height = "250px"; // set initial height
현재, 우리는 부가할 수 있다<iframe>.
var container = document.getElementById("pluginx-iframe-container");
container.appendChild(iframe);

문제 (동원 정책)


만약 두 사이트가 같은 구역에 있다면, 당신은 서로의 페이지 함수, 방문 변수 등을 간단하게 실행할 수 있습니다.하지만 Same Origin Policy에 따르면 불가능하다.브라우저는 부모 사이트가 iframe 창에 접근하는 함수와 변수를 제한합니다. 만약 이 두 함수와 변수가 같은 영역에 있지 않으면 반대로도 마찬가지입니다.처음에 나는 이것이 불필요한 안전 실현이라고 생각했다.그러나 지금은 이것이 사이트의 안전을 보호하는 가장 좋은 방법 중의 하나라는 것을 알게 되었다.왜?만약 당신의 고객이 자바스크립트를 사용하여 당신의 사이트를 방문할 수 있다면, 그들은 당신의 기능을 실행하고, 내용을 업데이트하고, 단추를 누르고, 좋아요를 추가하고, 사용자 데이터를 훔칠 수 있습니다.
several ways개국이 같은 원산지 정책을 회피했다.가장 좋은 방법은 HTML 5 Post 메시지 API입니다.

포스트 메시지 API


이 응용 프로그램의 개발을 완성하기 전에 Post Message API 이외의 다른 친구를 생각하지 마세요!window.postMessage() 방법은 창 대상 간의 원점 간 통신을 안전하게 활성화합니다.여기서, 우리는 그것을 사용하여 플러그인과 클라이언트 사이트 사이에서 통신할 수 있다.우리는 window.onmessage 이벤트를 통해postMessages를 들을 수 있다.이 문자열만 보낼 수 있습니다.
Hyvor Talk를 만들 때 이 통신을 포장하기 위한 간단한 클래스를 만들었습니다.나는 당신이 그것을 사용하는 것을 건의합니다. 왜냐하면 그것은 과정을 간소화했기 때문입니다.코드입니다.내가 나중에 설명할게.
/**
 * Creates a messenger between two windows
 *  which have two different domains
 */
class CrossMessenger {

    /**
     * 
     * @param {object} otherWindow - window object of the other
     * @param {string} targetDomain - domain of the other window
     * @param {object} eventHandlers - all the event names and handlers
     */
    constructor(otherWindow, targetDomain, eventHandlers = {}) {
        this.otherWindow = otherWindow;
        this.targetDomain = targetDomain;
        this.eventHandlers = eventHandlers;

        window.addEventListener("message", (e) => this.receive.call(this, e));
    }

    post(event, data) {

        try {
            // data obj should have event name
            var json = JSON.stringify({
                event,
                data
            });
            this.otherWindow.postMessage(json, this.targetDomain);

        } catch (e) {}
    }

    receive(e) {
        var json;
        try {
            json = JSON.parse(e.data ? e.data : "{}");
        } catch (e) {
            return;
        }
        var eventName = json.event,
            data = json.data;

        if (e.origin !== this.targetDomain)
            return;

        if (typeof this.eventHandlers[eventName] === "function") 
            this.eventHandlers[eventName](data);
    }

}
나는 ES6로 이 종류를 썼다.사용하지 않으면 Babel 를 사용하여 브라우저에서 지원하는 Javascript로 변환할 수 있습니다.
이 종류를 설명하기 전에, 스크립트 (iframeloader.js) 에서 사용합니다.

// handle each event from the iframe
var clientEventsHandler = {
    resize: (data) => {
        // resize the iframe
    }
};

messenger
var clientMsger = new CrossMessenger(iframe.contentWindow, "https://pluginx.com", eventHandlers)
iframe에 메시지를 보낼 때, 우리는 메시지를 수신하고 데이터에 반응해야 한다.clientEventsHandler 객체에는 이러한 함수가 포함됩니다.(이벤트 이름이 있는 키).
우리 교실로 돌아가자.
구조 함수는 세 개의 매개 변수가 필요하다.
  • 첫 번째는iframe 창입니다. 이 창에서 postMessage() 함수를 호출합니다.
  • 그리고 목표 구역은 귀하의 사이트의 구역입니다.이것은 우리가 e.origin
  • 을 사용하여 메시지를 전송하는 것을 검증할 수 있도록 한다
  • 마지막으로 이벤트 처리 프로그램입니다.잠시 후, 크기를 조정하는 것과 같은 흔한 이벤트 처리 프로그램을 만드는 방법을 보여 드리겠습니다.
  • 현재, 우리는 clientMsger.post(eventName, data) 을 사용하여 iframe에 메시지를 보낼 수 있다.여기서 데이터는 하나의 대상이 되어야 한다.JSON으로 변환되어 iframe로 전송됩니다.

    Iframe에서 메시지 수신


    현재 클라이언트 사이트에 추가된 Javascript 파일을 처리하고 있습니다.이제 iframe의 스크립트를 처리하기 시작합니다.우리는 iframe에서 같은 종류를 사용하여 메시지를 받아야 합니다.
    iframe 컨텐츠(HTML)
    <html>
      ... html stuffs
    
      <script src="script.js"></script>
    </html>
    
    script.js
    var iframeEventHandlers = {}; // some event handlers as the clientEventHandlers
    var clientDomain = ""; // How to find this???
    
    var iframeMsger = new CrossMessenger(window.parent, clientDomain, iframeEventHandlers)
    
    우리는 고객의 영역을 찾아야 한다.Iframe을 요청할 때 GET params를 설정하는 방법입니다.
    var domain = location.protocol + "//" + location.hostname;  
    iframe.src = "https://pluginx.com/iframe?domain=" + domain;
    
    그런 다음 백엔드 언어에서 이를 수신하고 변수 clientDomain 를 동적으로 설정할 수 있습니다.
    예를 들어 PHP의 경우
    var clientDomain = "<?= $_GET['domain'] ?>"; // make sure this is in the PHP page ;)
    
    이제 우리의 두 사절은 모두 완성되었다.당신이 필요로 할 수 있는 몇 가지 활동을 고려해 봅시다.

    이벤트


    1. 사이즈 조정


    기본적으로 iFrame은 자동으로 크기를 조정하지 않습니다.우리는 iframe의 높이를 명확하게 설정해야 한다.그렇지 않으면 iframe의 일부분을 표시하지 않습니다.따라서 크기 조정은 모든 iframe의 관건적인 부분이다.
    사이즈 조정은 우리가 상상한 것보다 훨씬 복잡하다.iframe 문서의 scrollHeight를 알아야 iframe의 크기를 조정할 수 있습니다.이것은 iframe를 통해서만 취소할 수 있습니다.
    다음은 iframe의 크기를 조정하는 중요한 시기입니다.
  • Iframe 로드 시
  • 클라이언트 브라우저의 시간 조정
  • iframe 내용의 높이가 바뀔 때.(예: 추가 요소)
  • 1번과 2번(로드 및 크기 조정)


    클라이언트 사이트(iframeloader.js)의 스크립트에서iframe의 onload 이벤트와 브라우저의 onresize 이벤트를 들을 수 있습니다.
    (function() {
    
       // setting iframe and appending
       iframe.onload = function() {
           requestResize();
           // do other onload tasks
       }
       window.addEventListener("resize", requestHeight);
    })();
    
    requestHeight() 기능
    이 함수는 단지 한 가지 일만 한다.iframe에서 iframe의 높이를 요청합니다.
    clientMsger.post("iframeHeightRequest");
    
    이것은 iframe에'iFrameResizer Request'라는 이벤트와 데이터가 없다는 메시지를 보냅니다.
    우리는 iframe에서 이 사건을 경청해야 한다.이벤트 이름과 프로세서를 iframeEventHandlersscript.js 에 추가합니다.
    var iframeEventHandlers = {
        iframeHeightRequest: () => {
            var docHeight = document.body.scrollHeight;
            iframeMsger.post("resize", { height: docHeight });
        }
    }
    
    현재, 우리는 클라이언트 스크립트에서 높이를 수신하고 iframe의 크기를 조정할 수 있습니다.
    var clientEventHandlers = {
        resize: () => {
            var height = data.height;
    
            var winScrollLeft = window.scrollX,
                windowScrollTop = window.scrollY;
    
                commentsIframe.style.visibility = "hidden";
                commentsIframe.style.height = 0;
    
                commentsIframe.style.visibility = "visible";
                commentsIframe.height = height + "px"; // + 10 to add little more height if needed
    
                // scroll to initial position
                window.scrollTo(winScrollLeft, windowScrollTop);
        }
    }
    
    이 과정은 사람을 곤혹스럽게 할 수도 있다.처음엔 나도 같은 느낌이었어.하지만 너는 그것에 빨리 적응할 수 있다.만약 당신이 곤혹스러워 한다면 잠시 쉬세요.(나는 이렇게 한 것으로 기억한다.)쉬고 나서 이 사진을 보세요.

    3번.(랙 높이가 변경된 경우)


    iframe에서 작업할 때 새 요소를 추가할 수 있습니다.이로 인해 높이가 변경될 수 있습니다.따라서 고도가 변화할 때마다 우리는iframe의 크기를 조정해야 한다.
    우리는 iframe에서 DOM 요소의 변화를 들어야 합니다.이것은 내가 인터넷에서 찾은 이 작업에 사용할 완벽한 함수입니다.
    var DOMObserver = (function(){
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    
        return function( obj, callback ){
            if( !obj || !obj.nodeType === 1 ) return; // validation
    
            if( MutationObserver ){
                // define a new observer
                var obs = new MutationObserver(function(mutations, observer){
                    callback(mutations);
                })
                // have the observer observe foo for changes in children
                obs.observe( obj, { childList:true, subtree:true });
            }
    
            else if( window.addEventListener ){
                obj.addEventListener('DOMNodeInserted', callback, false);
                obj.addEventListener('DOMNodeRemoved', callback, false);
            }
        }
    })();
    
    script.js에 추가한 다음 함수를 호출합니다.
    DOMObserver(document.body, iframeEventHandlers.iframeHeightRequest);
    
    노드를 추가하거나 삭제할 때마다 iframeEventHandlers.iframeHeightRequest 함수가 호출됩니다.Iframe은 크기를 조정합니다!
    크기를 조정하는 것 외에 이벤트를 추가하고iframe와 클라이언트 간에 메시지를 전달할 수 있습니다.
    플러그인이나 iframe에 불러오는 것을 만들고 있다면, 다음은 제 힌트입니다.
  • 창에 모든 데이터를 저장합니다.고객 사이트와 필요한 내용만 공유합니다.사용자 데이터와 같은 민감한 데이터를 영원히 공유하지 마라.
  • iframe에서 모든 AJAX 작업을 수행합니다.
  • 절대 사용하지 마십시오 CORS. 다른 사람이 당신의 사이트에 방문할 수 있도록 허락하십시오.postMessage API는 항상 사용됩니다.
  • 이 문서는 iFrame에서 자바스크립트를 사용하는 방법을 이해하는 데 도움을 줄 수 있기를 바랍니다.나는 내가 Hyvor Talk를 창작할 때 배운 것을 설명하기 위해 최선을 다했다.만약 내가 무엇을 놓쳤다면, 나는 장래에 그것을 추가할 것이다.그 밖에 이 글을 좋아한다면 공유하고 평론하세요.
    감사합니다.
    이 게시물은 Hyvor Group의 Web Developers Group 에 처음 게시되었습니다.

    좋은 웹페이지 즐겨찾기