HTML-in-HTML 포함: 반복
12331 단어 showdevjavascripttutorialhtml
이 기사에 대한 님의 의견:
HTML 내부에 HTML 포함 - React 구성 요소와 동일
수하일 카카르 ・ 8월 7일 ・ 2분 읽기
#html
#javascript
#webdev
#programming
FJones
•
이것은 htmlinclude.js의 (조잡한) 방법에 대한 웹 구성 요소의 매우 흥미로운 사용 사례로 저를 놀라게 합니다. 또한 이것이 상당히 많은 CSP 문제를 일으킬 것으로 보입니다. 예를 들어 포함된 파일에서 스크립트 태그나 외부 리소스를 로드하는 데 어려움을 겪을 것 같습니다.
도전처럼 들린다! 설계 목표는 다음과 같습니다.
htmlinclude.js
와 유사한 다른 HTML 문서 내에 HTML 조각을 포함하는 간단한 프런트 엔드 전용 HTML API<div></div>
는 괜찮습니다. <!DOCTYPE html><html lang="en"><head><title>title</title></head><body><div></div></body></html>
일 필요는 없습니다.<div>1</div> <div>2</div>
는 <div><div>1</div> <div>2</div></div>
가 include-html
구성 요소가 DOM에 더 이상 존재하지 않습니다script
속성이 설정되지 않은 경우 동일 출처 콘텐츠에서 태그를 실행합니다sanitize
script
더 이상 고민하지 않고 구현은 다음과 같습니다.
isSameOrigin
이 기능을 사용하여 포함된 콘텐츠의 출처가 동일한지 확인합니다. 그렇지 않은 경우 제3자가 스크립트를 삽입할 수 있는 것을 원하지 않기 때문에 확실히 정리가 필요합니다.
/** @param {string} src */
const isSameOrigin = (src) =>
new URL(src, window.location.origin).origin === window.location.origin
base
constructor에 두 번째 매개변수URL
를 제공하여 현재 원점을 기준으로 src
를 해결합니다. 그런 다음 둘 중 origin
가 같은지 확인합니다.예를 들어:
new URL('./bar.html', 'https://foo.co')
는 https://foo.co/bar.html
로 해석되며, 그 중 origin
는 여전히 https://foo.co
이므로 결과는 true
가 됩니다.new URL('https://baz.co/quux.html', 'https://foo.co')
는 https://baz.co/quux.html
로 해석됩니다. base
가 이미 정규화되었으므로 이 경우 src
매개변수는 무시됩니다. origin
는 https://baz.co
이고 https://foo.co
와 다르므로 결과는 false
가 됩니다.safeHTML
필요한 경우 HTML을 삭제하는 데 사용하는 기능입니다.
/** @param {{ sanitize?: boolean } = {}} */
const safeHtml = ({ sanitize } = {}) =>
/** @param {string} html */
(html) => {
const sanitized = sanitize !== false ? DOMPurify.sanitize(html) : html
return Object.assign(sanitized, {
__html: sanitized,
})
}
우리는
DOMPurify
을 사용합니다. HTML 삭제를 위해 광범위하게 사용되고 실전 테스트를 거친 솔루션입니다.문자열에서
Object.assign
를 사용하면 추가 속성이 추가된 String
개체가 제공됩니다. __html
속성을 추가하면 원하는 경우 React의 dangerouslySetInnerHTML
와 함께 결과를 직접 사용할 수 있지만 여전히 문자열이기 때문에 요소의 innerHTML
에 직접 할당할 수 있습니다... sort of .const result = safeHtml()('<hr/>')
result // String {"<hr>", __html: "<hr>"}
result.valueOf() // "<hr>"
'' + result // "<hr>"
IncludeHtml 웹 구성 요소
다음은 웹 구성 요소 자체입니다.
class IncludeHtml extends HTMLElement {
async connectedCallback() {
const forceSanitize = Boolean(this.attributes.sanitize)
const src = this.attributes.src.value
if (!this.innerHTML.trim()) {
this.textContent = 'Loading...'
}
const res = await fetch(src)
const html = safeHtml({
sanitize: !isSameOrigin(src) || forceSanitize,
})(await res.text())
const range = document.createRange()
// make rendering of fragment context-aware
range.selectNodeContents(this.parentElement)
this.replaceWith(range.createContextualFragment(html))
}
}
customElements.define('include-html', IncludeHtml)
range.createContextualFragment
을 사용한다는 것은 렌더링 시 존재하는 모든 script
태그를 실행하는 HTML 조각을 생성할 수 있음을 의미합니다(아직 제거하지 않았다고 가정). range.selectNodeContents
는 렌더링이 주변 컨텍스트를 인식하는 방식으로 예상대로 작동함을 의미합니다. 예를 들어 테이블 외부에 tr
를 삽입하려고 하면 아무 것도 렌더링되지 않지만 테이블 내에서는 예상대로 작동합니다.this.replaceWith
를 사용하면 콘텐츠가 렌더링될 때 즉시 DOM에서 웹 구성 요소를 제거합니다. 이는 백엔드 템플릿 프레임워크에서 기대하는 것과 유사합니다.용법
마지막으로 사용 중인 구성 요소의 몇 가지 예는 다음과 같습니다.
<nav>
<include-html src="./includes/nav.html"></include-html>
</nav>
<main>
<!--
Including from 3rd-party source works
(if CORS headers set properly on the source)
-->
<include-html
src="https://dinoipsum.herokuapp.com/api/?format=html¶graphs=2&words=15"
></include-html>
</main>
<footer>
<include-html sanitize src="./includes/footer.html"></include-html>
</footer>
이 라이브 CodeSandbox 데모에서 렌더링된 출력을 보고 직접 사용해 볼 수 있습니다.
읽어 주셔서 감사합니다! API 또는 기능에 어떤 개선 사항이 있습니까?
Reference
이 문제에 관하여(HTML-in-HTML 포함: 반복), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/lionelrowe/include-html-in-html-an-iteration-45ik텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)