iFrame에 HTML, CSS 및 JS 코드를 로드하는 방법
14884 단어 webdevjavascript
만약 JSFiddle, Codepen 또는 다른 도구를 사용한 적이 있다면, 이 문제는 당신에게 익숙합니다. 목표는 HTML, CSS, JS (문자열로 저장) 를 가져오고 코드를 불러오는 iframe를 만드는 것입니다.
이 문제는 쉬울 거예요. 하지만 아니에요. 적어도...내가 기다리고 있던 금표를 찾을 때까지.
하지만 이따가 자세히 소개해 드리겠습니다.그게 더 재미있기 때문에 우리는 작용하지 않는 모든 일부터 시작합시다.
시도 #1: srcdoc 사용
약간의 연구를 한 후에 나는iframes에
srcdoc
속성을 추가할 수 있다는 것을 감격스럽게 발견하였다.HTML 문자열이 전송되면 iframe에서 HTML 컨텐트를 로드합니다.
<iframe srcdoc="<p>This text will appear in the iframe!</p>"></iframe>
불행하게도 이런 방법에는 두 가지 주요 문제가 있다.1.srcdoc의 브라우저 지원은 좋지 않습니다
IE 또는 Edge를 지원하려면 다른 방법(또는 다각형 채우기)이 필요합니다.
2. CSS/JS에서 종료 가능
다음은 내가 srcdoc를 사용하여 실현한 대체적인 상황이다.
function setIframeContent(iframe, { html, css, js }) {
const source = `
<html>
<head><style>${css}</style></head>
<body>
${html}
<script>${js}</script>
</body>
</html>
`
iframe.srcdoc = source
}
문제는 무엇입니까?CSS나 JS를 작성할 때 코드에 각각 포함 </style>
또는 </script>
만 하면 HTML 영역으로 탈출할 수 있습니다.이 버그는 실제로 매우 흔하다.JSFIDLE 및 Codepen 모두 영향을 받습니다.
시도 #2: 서버 플라이백 없음
브라우저 지원 문제를 해결하기 위해
srcdoc
속성을 일반 src
속성으로 바꿉니다.이를 위해서는 코드뿐만 아니라 실제 URL을 전달해야 합니다.HTML, CSS, JS "GET"매개 변수를 수용하고 이전과 같은 유형의 페이지를 출력하는 페이지를 설정할 수 있지만, 이번에는 실제 URL에서 불러옵니다.
서버가 없는 구조를 사용하기에 가장 좋은 시기입니다. 왜냐하면 우리는 단지 한 가지 일을 완성할 수 있는 단점이 필요하기 때문입니다.다음은 내 시도입니다.
module.exports = (req, res) => {
// Code comes from GET params in URL
const { html = '', css = '', js = '' } = req.query
// Generate and send HTML page
return res.send(`
<html>
<head><style>${css}</style></head>
<body>
${html}
<script>${js}</script>
</body>
</html>
`)
}
이것은 거의 모든 브라우저에 적용되지만 그 자체의 문제도 있다.시도 #3: 서버 리턴 없음(redux)
우리의 첫 번째 리턴봉은 브라우저 지원 문제를 해결했지만, 여전히'탈출'문제는 처리해야 한다.
다행히도 우리가 코드를 전달하는 방식 때문에 사실상 해결할 수 있다.우리는 서버에 CSS와 JS를 삽입하는 페이지가 아니라 클라이언트에서 완성할 수 있습니다!클라이언트의 컴퓨터가 URL GET 매개변수에 여전히 액세스할 수 있기 때문입니다.
소스 코드가 좀 길지만 유효합니다.
module.exports = (req, res) => {
return res.send(`
<html>
<head>
<script type="text/javascript">
window.addEventListener('load', function() {
function getUrlParameter(name) {
name = name.replace(/[\\[]/, '\\\\[').replace(/[\\]]/, '\\\\]');
var regex = new RegExp('[\\\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\\+/g, ' '));
};
// Load JS from GET params (on client)
var js = getUrlParameter('js');
if (js) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.text = js;
document.body.appendChild(script);
}
// Load CSS from GET params (on client)
var css = getUrlParameter('css');
if (css) {
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
document.head.appendChild(style);
}
// Remove the currently running script tag
document.currentScript.parentNode.removeChild(document.currentScript);
});
</script>
</head>
<body>
${req.query.html || ''}
</body>
</html>
`)
}
현재 스크립트나 스타일에 무서운 HTML 문자가 포함되어 있으면 브라우저는 상기 스크립트/스타일을 문서에 삽입할 때 이 문자를 처리합니다.이 솔루션은...좋다기술적으로 말하자면, 이것은 실행 가능한 것이다.그러나 우리는 여전히 소프트 URL 길이 제한을 고려해야 한다.그 밖에 우리는 현재 일부 서버 측의 일을 처리하고 있으며, 클라이언트에서 발생해야 한다고 느낀다.
더 좋은 방법이 있을 거야.
솔루션: Blob URL
그동안 우리는 URL에서 데이터를 로드하는 시뮬레이션을 시도해 왔습니다.
얼룩
우리는
Blob
구조 함수를 사용하여 위조 파일을 만들 수 있다.디스크나 URL에서 로드된 실제 파일이 아닙니다. 메모리에만 저장됩니다.그러나 많은 면에서 그 기능은 실제로 불러온 파일과 같다.그리고 우리는
URL.createObjectURL(blob)
을 사용하여blob의 내용을 불러오는 URL을 만들 수 있습니다.다음은 실천 중인 작업 원리입니다.
const getBlobURL = (code, type) => {
const blob = new Blob([code], { type })
return URL.createObjectURL(blob)
}
console.log(getBlobURL('<p>My webpage</p>', 'text/html'))
// blob:https://dev.to/9ca05e31-05ea-48f8-838d-cc1ad0949ec8
컨트롤러에서 위의 코드를 실행해 보세요. 직접 보세요!URL이 기록됩니다.시작 blob:
비트를 포함하여 새 탭에 URL을 붙여넣으면 HTML이 포함된 페이지가 로드됩니다.주의
'text/html'
getBlobURL
에게 전달되었습니까?우리도 이 점을 바꿀 수 있다.CSS 또는 JS blob을 생성하는 것은 매우 쉽습니다. 각각 text/css
또는 text/javascript
만 통과하면 됩니다.blob URL의 또 다른 장점은 항상 존재하고 어떤 방식으로든 일반 URL에 접근할 수 있다는 것이다.이것은 우리가 사실상 하나의 단독 URL에서 CSS와 JS 파일을 불러올 수 있다는 것을 의미하기 때문에'전의'기술은 더 이상 문제가 아니다.
이것은 실천 중의 간단한 실현이다.
const getGeneratedPageURL = ({ html, css, js }) => {
const getBlobURL = (code, type) => {
const blob = new Blob([code], { type })
return URL.createObjectURL(blob)
}
const cssURL = getBlobURL(css, 'text/css')
const jsURL = getBlobURL(js, 'text/javascript')
const source = `
<html>
<head>
${css && `<link rel="stylesheet" type="text/css" href="${cssURL}" />`}
${js && `<script src="${jsURL}"></script>`}
</head>
<body>
${html || ''}
</body>
</html>
`
return getBlobURL(source, 'text/html')
}
const url = getGeneratedPageURL({
html: '<p>Hello, world!</p>',
css: 'p { color: blue; }',
js: 'console.log("hi")'
})
const iframe = document.querySelector('#iframe')
iframe.src = url
읊다, 읊조리다도덕
나는 언어와 싸우지 말라고 생각한다.
나는 내가 무엇을 하고 싶은지 안다. URL에서 데이터를 불러온다.나는 지금까지 해커가 아닌 방식을 찾아서 이 점을 해낼 생각을 해 본 적이 없다.
Reference
이 문제에 관하여(iFrame에 HTML, CSS 및 JS 코드를 로드하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(iFrame에 HTML, CSS 및 JS 코드를 로드하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)