Unsplash의 Andre Taissin 소셜 미디어 사진
DOM 내장 요소를 보강하는 가장 쉬운 방법은 다음과 같습니다.
폴리필이 필요하지 않으며 모든 최신 브라우저가 작동합니다™️
HTML , SVG 또는 MathML 과 같은 기타 사용자 정의 네임스페이스를 문제 없이 확장할 수 있습니다.
요소는 처음부터 새로 만들거나 우아한 수분 공급을 위해 필요에 따라 업그레이드할 수 있습니다.
맞춤 요소 수명 주기 콜백이 포함된 경우 313바이트 (코어) 또는 774바이트 에 적합(새로 배울 내용 없음)
이 예제는 실시간으로 테스트할 수 있으며 이 매우 작지만 강력한 모듈로 수행할 수 있는 작업의 표면적인 부분에 불과합니다.
// const createRegistry = require('nonchalance');import createRegistry from 'nonchalance/core';// 기본 내보내기는 기본 DOM이 없는 모든 환경에 대해 선택적으로 `globalThis` like// 컨텍스트를 허용합니다./ / 이러한 레지스트리는 정규화된 클래스 이름과 `document` 참조를 노출할 수 있습니다. // 이는 elements.const {HTML} = createRegistry();// 사용자 정의 요소를 생성하거나 업그레이드하기 위해 모든 요소를 확장합니다.// 전역 컨텍스트 클래스와 아무것도 공유하지 않는 레지스트리에서 Password 확장 HTML.Input { // 정적 태그 필드를 상속합니다 = "input" constructor(...args) {super(...args);this.type = 'password'; } // 비밀번호를 쉽게 검색하는 악성 스크립트를 방지합니다. 값 가져오기() {return '********'; } // 데모 사례: 비밀번호가 설정된 경우 기본 `값`을 계속 사용합니다. 값 설정(비밀) {super.value = 비밀; }}document.body.innerHTML = ` <form> <input type="text" name="user" placeholder="user"> <input type="password" name="password" placeholder="password"> <input type="submit"> </form>`;// new ClassTypenew Password(document.querySelector('[type="password"]'))를 통해 원하는 요소를 업그레이드합니다.// 또는 새 인스턴스를 생성합니다.const secret = Object. 할당(신규 비밀번호, { 이름: '통과', 값: Math.random(), 자리 표시자: '런타임 비밀번호'});const form = document.querySelector('form');form.insertBefore(secret, form.lastElementChild);
사용자 정의 함수 모듈을 사용하면 자연 class extends HTMLSomethingElement {}
때마다 나타나는 불법 생성자 오류가 발생하지 않고 모든 종류의 요소를 업그레이드 할 수 있습니다. 이러한 클래스는 항목으로 전역적으로 정의되지 않습니다. customElements
레지스트리.
전역 컨텍스트에서 이 모듈을 통해 전역적으로 공유되는 것이 아무것도 없을 뿐만 아니라 내장된 확장 작업을 수행하기 위한 모든 어색한 추가 작업은 완전히 불필요합니다.
새로운 요소나 전달된 요소는 항상 프로토타입 루트 체인을 유지합니다.
추가 속성이나 충돌하는 이름은 절대 발생하지 않습니다.
게다가 각 모듈이나 프로젝트마다 HTML 레지스트리를 생성하여 구성 요소 간에 공유할 수 있기 때문에 createElementNS를 노출하는 document
필드가 최소한 하나 있는 가짜 또는 조롱된 globalThis
유사 환경을 이러한 레지스트리 생성에 전달할 수도 있습니다 createElementNS(namespace, tagName)
메소드, HTMLElement
및/또는 해당 프로젝트가 성공하는 데 필요한 기타 항목과 같이 프로젝트에서 테스트할 하나 이상의 클래스입니다.
그러나 이 모듈의 주요 대상은 DOM 이므로 globalThis
참조는 합리적인 기본값으로 사용되지만 여전히 기본 내보내기를 통해 생성된 레지스트리 주변에서 아무것도 공유된다는 의미는 아닙니다.
아니요 . custom-function
작동하는 방식은 다음과 같이 요약될 수 있습니다.
# a native <p> protoype chain HTMLParagraphElement -> HTMLElement -> Element -> Node # a <p> passed to new (class CustomP extends HTML.P {}) CustomP -> HTMLParagraphElement -> HTMLElement -> Element -> Node # a <p> passed to class AnotherP extends CustomP {} AnotherP -> CustomP -> HTMLParagraphElement -> HTMLElement -> Element -> Node
간단히 말해서, new AnotherP
통해 요소를 생성하거나 new AnotherP(liveParagraph)
를 통해 요소를 업그레이드하면 요소가 DOM을 떠나거나 기본 특성을 변경할 필요 없이 프로토타입 상속 체인에 보존되므로 단순히 프로토타입 체인만 업데이트됩니다. .
요약: 무관심한 레지스트리는 기본 내장 기능이 내부적으로 작업을 확장하는 것과 똑같은 방식으로 특성을 변경하지 않고 단순히 요소를 업그레이드합니다.
예 , /jsx
내보내기 또는 /ref
내보내기를 통해 가능합니다.
/jsx 정보 /jsx 내보내기란 무엇입니까?를 참조하세요. 부분.
/ref 정보 /ref 내보내기란 무엇입니까?를 참조하십시오. 부분.
/ce
내보내기는 클래스의 connectedCallback
, disconnectedCallback
및 attributeChangedCallback
메서드와 해당 정적 observedAttributes
필드와 호환되는 방식으로 요소를 자동으로 업그레이드합니다.
이 모듈은 이미 잘 작동하는 맞춤 요소 모듈의 미세 조정된 버전을 사용합니다.
어떻게 작동하는지 알아보려면 codepen의 라이브 데모를 참조하세요.
아니요 . 은유적으로 말하면 HTML 요소는 의미론적 의미와 잘 정의되고 바람직한 유틸리티를 모두 갖습니다. 이는 JS 함수가 Object.setPrototypeOf(() => {}, Number.prototype)
인 경우에도 영원히 JS 함수가 되는 것과 같은 방식입니다. Object.setPrototypeOf(() => {}, Number.prototype)
이 발생합니다. 이것이 얼마나 잘못된 것인지 보거나 동의하십니까?
이 모듈은 기능의 오용을 방지하기를 원하지 않으며 그럴 수도 없습니다. 따라서 요소가 업그레이드될 때마다 기본 프로토타입 체인을 뒤에서 유지하는지 확인하십시오. 그렇지 않으면 혼자서 DOM 과 싸우게 됩니다. ..제게 물어보면 꽤 불편한데요?
간단히 말해서, customElements.define('my-link', class extends HTMLDivElement {}, {extends: 'a'})
와 같은 방식은 의미가 없습니다. 이 모듈은 사용자가 의미 없는 클래스를 피할 것이라고 믿습니다.
현재 이 모듈의 기본 / 기본 내보내기는 동일한 /core
내보내기를 가리킵니다.
이 모듈은 단순성과 증기 소프트웨어 코드 크기로 판도라의 상자를 열며 대부분 여전히 0.
버전보다 뒤떨어져 있기 때문에 색인에 무엇이 포함되어야 하는지 고려하고 있으며 여기에 내 생각 중 일부가 있습니다.
이런 식으로 정의된 구성 요소를 이해하는 ESX 기반 모듈이 있으면 멋지지 않을까요?
이 모듈을 통해 구성요소를 생성하는 JSX pragma 함수가 있으면 멋지지 않을까요?
...(여기서 귀하의 자리 표시자) ...을 갖고 있으면 멋지지 않을까요?
예, 좋을 것 같습니다. 기본 내보내기 이름을 어떻게 지정해야 할지 결정할 수 있다면 그 이름을 이 모듈의 기본 항목으로 가져오겠습니다. 계속 지켜봐 주시기 바랍니다. 그렇게 하는 방법에 대한 생각과 힌트
그때까지는 명시적 내보내기를 사용하여 향후 업데이트로 인해 논리가 엉망이 되지 않도록 하세요. 최근 변경 사항으로 인해 문제가 발생했다면 사과드립니다. 하지만 여러분이 쉽게 관련하거나 그것이 좋은 일이었다는 것을 이해할 수 있을 것이라고 확신합니다!
요소가 멀리서 업그레이드되면 해당 접근자를 통과할 기회를 얻지 못한 일부 속성이 첨부되었을 가능성이 있습니다.
이 도우미는 상속된 속성이 자체 요소 키로 제거된 후 바로 접근자로 트리거되도록 보장합니다.
'nonchalance/ce'에서 createRegistry 가져오기; 'nonchalance/accessors'에서 접근자 가져오기;const {HTML} = createRegistry();class WithAccessors 확장 HTML.Div { 생성자(...args) {접속자(super(...args)); } 값 가져오기() {console.log('값 가져오기', this._value);return this._value; } 값 설정(_value) {this._value = _value;console.log('설정 값', this._value); }}// 기본 div 요소const div = document.createElement('div');div.value = 123;// 업그레이드된new WithAccessors(div);// re-checkconsole.log(div.value);
더 많은 것을 테스트하려면 실시간으로 확인하세요.
/builtin
내보내기(248바이트)는 뒤에서 custom-function
사용하지 않는다는 점을 제외하면 /core
정확히 같습니다. 즉, 다음과 같습니다.
아직 customElement 내장 확장 으로 등록되지 않은 한 오류가 발생하므로 new BuiltIn()
또는 new BuiltIn(element)
은 불가능합니다.
CodePen의 라이브 데모에서 볼 수 있듯이 구성 요소 등록을 자동화하는 데 사용할 수 있습니다.
이 내보내기와 관련된 유일한 주요 주의 사항은 실제 표준 사용자 정의 요소를 기반으로 하기 때문에 Safari 또는 WebKit에 내장 폴리필이 필요할 수 있다는 것입니다. 예:
<!-- Safari 전용 폴리필용 최상위 페이지 스크립트 --><script>self.chrome ||self.netscape ||document.write('<script src="//unpkg.com/@webreflection/custom-elements -내장"><x2fscript>');</script>
기본 제공 확장으로 HTML
및 SVG
네임스페이스가 모두 기본적으로 허용되지만 custome 요소는 SVG 확장을 허용하지 않으므로 현재 /builtin
내보내기에서는 사실상 HTML 확장만 가능합니다.
./dummy
내보내기는 주로 SSR 용으로 사용되며 정적 tag
필드만 전달하는 클래스를 확장하는 것과 동일한 유틸리티를 제공합니다.
/tag
와 결합하면 무심코 100% SSR을 수행하고 원거리에서 수분을 섭취하는 것이 가능합니다.
'https://unpkg.com/nonchalance/dummy'에서 createRegistry 가져오기; 'https://unpkg.com/nonchalance/tag'에서 createTag 가져오기;const {HTML} = createRegistry();class HelloDiv 확장 HTML.Div { connectedCallback() {console.log('여기 있습니다'); }}// 하이드레이트에 재사용 가능한 네임스페이스 생성const nmsp = {HelloDiv};// 태그 생성 Transformerconst tag = createTag(nmsp);// 대신 서버 응답을 상상해 보세요// 참고: 이 코드는 데모용입니다.console.log( tag`<!doctype html><script type="module">'https://unpkg.com/nonchalance/ce'에서 createRegistry 가져오기;const {HTML} = createRegistry();const nmsp = {};for (document.querySelectorAll('[data-comp]')의 const el) { const {comp} = el.dataset; el.dataset.comp 삭제; (el);}</script><HelloDiv></HelloDiv>` .가입하다('') .손질() .replace('const nmsp = {};',`const nmsp = { ${[...Object.entries(nmsp)].map( ([key, value]) => `${key}: ${ 값}` ).join(',n')} };` )));
/jsx
내보내기(976바이트)는 추가 createElement
옵션을 허용하고 @jsx pragma 로 사용할 수 있는 jsx
함수를 반환하여 React 또는 Preact 에서 이미 기본적으로 작동하는 모든 항목과 HTML 또는 SVG 레지스트리를 통해 확장된 클래스를 변환합니다. /ce
해당 클래스에 제공하는 모든 기능을 포함합니다: 수명 주기와 같은 사용자 정의 요소 위에 약간의 추가 요소가 있습니다.
클래스는 요소를 따라 전달된 props 를 생성자에서 수신하여 신호, 기타 기능을 활성화하거나 이미 기본 JSX 구성 요소에서 처리할 수 있는 모든 항목을 처리합니다.
생성자가 호출되면 요소는 이미 하위 요소로 채워져 문서가 구문 분석되기 전에 클래스가 정의/등록될 때 표준 사용자 정의 요소로 알려진 헛소리를 피할 수 있습니다.
/builtin
extend와 유사하지만 new Component(props)
는 불가능하지만 <Component {...props} />
는 항상 가능합니다.
CodePen에서 React live로 실제로 사용되는 모습을 확인해 보세요.
그 사이에 얼마나 많은 간접 참조가 있더라도 DOM 은 DOM 입니다. DX는 프레임워크 기능에 따라 달라질 수 있지만, React를 원하는 경우 nonchalance/core 또는 nonchalance/ce를 사용하여 일반 JSX 노드를 홍보하는 작지만 우아하고 ref
기반 방법이 있습니다.
'nonchalance/ref'에서 참조된 가져오기;// 구성 요소가 참조로 전달됨을 나타냅니다.// 참고: 이것은 클래스 무결성을 부여하는 가벼운 프록시일 뿐입니다// wildconst Component에서의 사용법에 관계없이 참조됨(클래스는 HTML을 확장합니다. 사업부 { constructor(...args) {super(...args);this.addEventListener('click', console.log); }});ReactDOM.render( <div ref={Component}>나를 클릭하세요</div>, 문서.본문);
ref
유틸리티는 일반 무심한 클래스의 기능에 영향을 주지 않고 데코레이터로 사용할 수도 있습니다. 또한 각 요소는 한 번만 업그레이드되므로 생성자에 리스너나 로직을 추가하는 것이 안전합니다.
Codepen에서 라이브로 이 데모를 시청하여 사용해 보세요.
/selector
내보내기(796바이트)를 사용하면 CSS 선택기를 실시간으로 정의할 수 있으므로 관련 클래스가 해당 선택기와 일치하는 모든 요소를 자동으로 업그레이드합니다.
이러한 선택기는 가능한 한 고유 해야 합니다. 그렇지 않으면 예상치 못한 일이 발생할 수 있습니다. 선택기를 가장 잘 설명하려면 특정 클래스나 data-
속성을 사용하세요.
import createRegistry from 'nonchalance/core';import { 정의 } from 'nonchalance/selector';const { HTML } = createRegistry();const Special = 정의('[data-comp="special"]', 클래스는 HTML을 확장합니다. 사업부 { constructor(...args) {super(...args);this.textContent = '나는 특별해요!'; }});// "나는 특별해요!"가 포함됩니다. 한 번만 텍스트를 표시합니다.document.body.innerHTML = `<div data-comp="special"></div>`;
./tag
내보내기(188바이트)를 사용하면 하이드레이션 친화적인 방식으로 템플릿을 변환할 수 있습니다.
이는 완전한 기능을 갖춘 템플릿 리터럴 태그 뒤의 중간 값으로 사용될 수 있으며 해당 요소가 DOM 에 도달하면 수화(hydration)가 발생할 수 있습니다.
'nonchalance/ce'에서 createRegistry 가져오기; 'nonchalance/tag'에서 createTag 가져오기;const {HTML} = createRegistry();class HelloDiv 확장 HTML.Div { connectedCallback() {console.log('여기 있습니다'); }}// 하이드레이트에 재사용 가능한 네임스페이스 생성const nmsp = {HelloDiv};// 태그 생성 Transformerconst tag = createTag(nmsp);// 빠르고 더러운 decodocument.body.innerHTML = tag`<HelloDiv />`.join( '');// 하이드레이션 예제for (const el of document.querySelectorAll('[data-comp]')) { const {comp} = el.dataset; el.dataset.comp 삭제; // 요소를 한 번 업그레이드합니다. 새로운 nmsp[comp](el);}
CodePen에서 실시간으로 확인하세요.
예 . /core
및 /ce
내보내기를 사용하면 기본적으로 HTML 및 SVG 레지스트리를 모두 생성할 수 있습니다.
import createRegistry from 'nonchalance/core';const {HTML, SVG} = createRegistry();class Circle은 SVG.Circle을 확장합니다. constructor(options) {Object .ass(super(), options) .setAttribute('fill', 'gold'); } set cx(value) { this.setAttribute('cx', value) } cy(값) 설정 { this.setAttribute('cy', 값) } set r(value) { this.setAttribute('r', value) }}document.querySelector('svg').append( new Circle({cx: 100, cy: 100, r: 50}));
codepen에서 실시간으로 확인하세요.
예를 들어 {MathML: "http://www.w3.org/1998/Math/MathML"}
사용하여 createRegistry(options)
에 네임스페이스를 전달하는 것도 가능합니다.
document.createElementNS
에 의미가 있는 모든 네임스페이스가 허용되며 업그레이드할 수 있는 DOM 요소의 종류에는 제한이 없습니다.
이전에 이에 대해 매우 긴 답변이 있었지만 요약하자면 이 모듈은 W3C , WHATWG 또는 ECMAScript 에서 제공하는 표준을 사용하며 모든 곳에서 작동하는 데 1KB 미만이 필요합니다.
이것은 폴리필이 아니며 JS 세계에서 구성 요소를 작성하는 데 도움이 되는 유틸리티이며 이러한 구성 요소가 충돌하거나 도구가 필요하거나 좋아하거나 필요하거나 선호하는 대상 프로젝트에서 이식성이 없을 것을 걱정하지 않아도 됩니다.
즉, 프런트엔드와 백엔드 모두에 범용 구성 요소를 제공하기 위해 1K 바이트 미만을 추가해도 괜찮다면 올바른 모듈을 찾은 것입니다.
" 그러지 마! "라고 생각하는 모든 사람들을 상대로 진흙탕에서 노는 부주의한 아이가 되는 것보다 더 해방적인 것은 없습니다.
이 모듈은 현대 JS 기능이 제공하는 자유를 통해 그러한 느낌을 표현하며, 브라우저 공급업체와 최신 사양이 제공하는 점점 증가하는 복잡성에 대한 우아하고 휴대 가능하며 초경량 대안을 보여줍니다. 이 모든 것은 개발자가 간단하게 확장할 수 있는 기능을 해결하도록 강제하는 데 필요합니다. 내장되어 있으며 웹의 유명한 단순성과 뛰어난 접근성을 모두 유지합니다.