임베디드 프로젝트를위한 작은 (512 바이트) 가상 DOM 템플릿 엔진
| IE / 엣지 | 파이어 폭스 | 크롬 | 원정 여행 | 오페라 | iOS 사파리 | 안드로이드 크롬 |
|---|---|---|---|---|---|---|
| 가장자리 14+ | 45+ | 49+ | 10+ | 37+ | 10.2+ | 55+ |
.Dom은 React.js (예 : 재사용 가능한 구성 요소 및 가상 DOM)에서 일부 개념을 빌려서 가장 작은 발자국으로 복제하여 ES6 JavaScript 기능을 악용하려고합니다.
왜? 이러한 라이브러리를 사용하면 IoT 장치와 같은 단단한 우주 환경에서 강력한 GUI를 만들 수 있습니다.
작은 디자인 : 라이브러리의 크기가 512 바이트를 초과해서는 안됩니다. 목표는 또 다른 템플릿 엔진이 아니라 512 바이트에서 가능한 많은 기능을 갖는 것입니다. 새로운 기능이 필요한 경우 다른 기능이 사라지거나 범위를 줄여야합니다.
미래를 위해 구축 : 라이브러리는 ES6 사양을 크게 활용하여 이전 브라우저에서 지원 하지 않음을 의미합니다. 현재 시장의 90%의 90%가 지원하고 있지만 내년에는 100%가 가까워 질 것으로 예상됩니다.
선언 : HTML DOM을 구조적이고 자연스럽게 설명하여 강력하지만 읽을 수있는 사용자 인터페이스를 만들 수 있도록 도와줍니다.
구성 요소 지향 : react.js와 마찬가지로 .DOM은 기능 구성 요소의 사용을 촉진합니다.
"쓰기 덜"가속기 : 라이브러리 API는 짧은 기능 이름과 가속기를 갖도록 특별히 설계되어 코드가 적은 뷰를 설명 할 수 있습니다.
.dom 사용하는 프로젝트 프로젝트에서 .dom 사용하고 있습니까? 이 저장소를 포크하고 목록에 추가하십시오!
최소 발자국의 경우 프로젝트에 dotdom.min.js.gz (512b)를 포함시킵니다.
< script src =" dotdom.min.js.gz " />또는 스크립트 직전에 라이브러리의 최소화 버전을 포함시킬 수 있습니다. 조정 된 코드를 복사하면됩니다.
이미 react.js를 알고 있다면 다음 예제는 .Dom 프리미티브가 반응과 어떤 관련이 있는지 이해하는 데 도움이 될 수 있습니다.
매우 간단한 DOM 구조를 렌더링합니다.
| 반응 | .Dom |
|---|---|
ReactDOM . render (
React . createElement ( 'div' , null , 'Hello world' ) ,
document . body
) ; | R (
H ( 'div' , 'Hello world' ) ,
document . body
) |
속성을 전달할 수있는 구성 요소 작성.
| 반응 | .Dom |
|---|---|
function Hello ( props ) {
return React . createElement (
'div' , null , `Hello ${ props . toWhat } `
) ;
}
ReactDOM . render (
React . createElement (
Hello , { toWhat : 'World' } , null
) ,
document . body
) ; | function Hello ( props ) {
return H ( 'div' , `Hello ${ props . toWhat } ` ) ;
}
R (
H ( Hello , { toWhat : 'World' } ) ,
document . body
) |
자신의 상태를 유지할 수있는 구성 요소를 만듭니다.
| 반응 | .Dom |
|---|---|
class Clickable extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
clicks : 0
} ;
}
render ( ) {
const { clicks } = this . state ;
return React . createElement (
'button' , {
onClick ( ) {
this . setState ( { clicks : clicks + 1 } )
}
} , `Clicked ${ clicks } times`
) ;
}
}
ReactDOM . render (
React . createElement ( 'div' , null ,
React . createElement ( Clickable , null , null ) ,
React . createElement ( Clickable , null , null )
) ,
document . body
) ; | function Clickable ( props , state , setState ) {
const { clicks = 0 } = state ;
return H ( 'button' ,
{
onclick ( ) {
setState ( { clicks : clicks + 1 } )
}
} ,
`Clicked ${ clicks } times`
) ;
}
R (
H ( 'div' ,
H ( Clickable ) ,
H ( Clickable )
) ,
document . body
) |
구성 요소는 생명주기 이벤트를 구독 할 수도 있습니다.
| 반응 | .Dom |
|---|---|
class WithLifeCycle extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
mounted : "no"
} ;
}
componentDidMount ( ) {
this . setState ( { mounted : "yes" } )
}
render ( ) {
const { mounted } = this . state ;
return React . createElement (
'div' , null , `mounted = ${ mounted } `
) ;
}
}
ReactDOM . render (
React . createElement ( 'div' , null ,
React . createElement ( WithLifeCycle , null , null ) ,
) ,
document . body
) ; | function WithLifeCycle ( props , state , setState , hooks ) {
const { mounted = "no" } = state ;
hooks . m . push ( ( ) => {
setState ( { mounted : "yes" } )
} ) ;
return H ( 'div' ,
`mounted = ${ mounted } `
) ;
}
R (
H ( 'div' , H ( WithLifeCycle ) ) ,
document . body
) |
키드 업데이트는 Rendering Engine이 업데이트 할 요소에 대한 현명한 결정을 내릴 수있는 React의 유용한 조정 기능입니다.
특히 유용한 사례는 동적 요소 목록을 렌더링 할 때입니다. 렌더링 엔진은 어떤 요소가 변경되었는지 이해하지 못하므로 잘못 업데이트로 끝납니다.
이 문제를 해결하기 위해 VDOM 엔진은 트리의 요소를 독특하게 식별하는 key 속성을 사용합니다. 그러나 vdom 요소 인스턴스 자체에 요소 상태의 사본을 유지하여 해결합니다.
즉, key 속성이 필요하지 않다는 것을 의미합니다. 이전과 동일한 vDom 인스턴스를 반환하십시오.
동적 요소 (예 : VDOM 요소 배열)를 생성하는 경우 .
| 반응 | .Dom |
|---|---|
class Clickable extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
clicks : 0
} ;
}
render ( ) {
const { clicks } = this . state ;
const { ket } = this . props ;
return React . createElement (
'button' , {
onClick ( ) {
this . setState ( { clicks : clicks + 1 } )
}
} , `clicks= ${ clicks } , key= ${ key } `
) ;
}
}
const list = [ "first" , "second" , "third" ] ;
const components = list . map ( key =>
React . createElement ( Clickable , { key } , null ) ;
ReactDOM . render (
React . createElement ( 'div' , null ,
components
) ,
document . body
) ; | function Clickable ( props , state , setState ) {
const { clicks = 0 } = state ;
const { key } = props ;
return H ( 'button' ,
{
onclick ( ) {
setState ( { clicks : clicks + 1 } )
}
} ,
`clicks= ${ clicks } , key= ${ key } `
) ;
}
const list = [ "first" , "second" , "third" ] ;
const components = list . map ( key =>
H ( Clickable , { key } ) ;
R (
H ( 'div' , components ) ,
document . body
) |
위의 솔루션은 순서가 변경된 경우에도 상태가 많은 구성 요소를 올바르게 업데이트합니다. 그러나 개별 키를 업데이트하는 완전한 반응과 같은 기능을 원한다면 Keyed 플러그인을 사용할 수 있습니다.
function Container ( props , state ) {
const { components } = props ;
// The function `K` accepts the component state and an array of components that
// contain the `key` property, and returns the same array of components, with their
// state correctly manipulated.
return H ( "div" , K ( state , components ) ) ;
} 후크의 .r 속성을 진실한 값으로 설정하여 RAW (조정되지 않은) vdom 노드 (예 : 임의의 HTML 컨텐츠를 전달하는)를 만들 수 있습니다.
이것은 하위 노드에 대한 추가 화해를 비활성화하여 내용을 그대로 유지합니다.
function Description ( props , state , setState , hooks ) {
const { html } = props ;
hooks . r = 1 ; // Enable raw mode
return H ( 'div' , {
innerHTML : html
} )
} R( VNode, DOMElement ) R ( H ( 'div' , 'Hello' ) , document . body )주어진 vnode 트리를 주어진 dom 요소로 렌더링합니다. 상태가 많은 구성 요소의 추가 업데이트는 직계 어린이에게만 발생합니다.
H( tagName | function, [properties], [children ...]) 생성 H ( 'tag' )
H ( 'tag' , { prop : "value" } )
H ( 'tag' , H ( 'child' ) )
H ( 'tag' , { prop : "value" } , H ( 'child' ) )
H ( Component , { prop : "value" } )vnode 요소를 만듭니다. 문자열이 첫 번째 인수로 전달되면 HTML 요소가 생성됩니다. 함수가 주어지면 상태가 많은 구성 요소가 생성됩니다.
속성과 어린이는 선택 사항이며 생략 할 수 있습니다.
태그 이름 대신 더 높은 수준의 논리에 따라 가상 DOM을 반환하는 함수를 제공 할 수 있습니다. 이러한 기능은 다음과 같은 시그니처를 가지고 있습니다.
const Component = ( props , state , setState , hooks ) {
// Return your Virtual DOM
return div ( ... )
} props 속성에는 구성 요소가 생성 될 때 주어진 속성 객체가 포함되어 있습니다.
state 빈 개체 {} 로 초기화되며 setState({ newState }) 메소드를 호출하여 업데이트됩니다. 후자는 또한 구성 요소와 아이들에 대한 업데이트를 유발할 것입니다.
업데이트를 원하지 않는 경우 state 객체에 속성을 직접 할당 할 수도 있습니다.
hooks 객체는 구성 요소 수명주기 방법에 핸들러를 등록하려고 할 때 사용할 수 있습니다.
RECT와 유사하게 .DOM 구성 요소에는 수명주기가 있습니다.
수명주기 메소드에 액세스하려면 구성 요소 기능의 네 번째 인수를 사용해야합니다. 보다 구체적으로 다음 분야 중 하나에서 취급 기능을 푸시해야합니다.
const Component = ( props , state , setState , hooks ) {
hooks . m . push ( ( domElement ) => {
// '.m' is called when the component is mounted
} ) ;
hooks . u . push ( ( ) => {
// `.u` is called when the component is unmounted
} ) ;
hooks . d . push ( ( domElement , previousDomElement ) => {
// `.d` is called when the component is updated
} ) ;
...
}tag( [properties], [children ...] ) const { div , span , a } = H ;
div ( 'hello' , span ( 'world' ) )
div ( 'click' , a ( { href : '#' } , 'Here' ) , 'to continue' ) 속기 기능은 H 함수에서 속성으로 추출 될 수 있습니다. 그러한 속기는 H 와 똑같이 행동하지만 태그 이름은 이미 채워졌습니다.
자바 스크립트 미니어가 결과를 더욱 최적화하도록 돕기 위해 스크립트 시작시 탈퇴 할당을 사용하는 것이 좋습니다.
const {div, span, a, button} = H;
tag.class( [properties], [children ...] ) const { h1 , span , p } = H ;
h1 . short ( 'short header' , span . strong ( 'strong text' ) )
button . primary ( { onclick : handleClick } , 'Primary Action' )
p . bold . italic ( twitterPost ) className 속성으로 제공하는 대신 속기 태그 방법과 함께 .className 속기를 사용할 수 있습니다.
이것은 div({className: 'className'}) 호출하는 것과 동일하며 함수 인터페이스는 위와 정확히 동일합니다.
참고 : 태그에 둘 이상의 .class 연결하여 둘 이상의 클래스를 추가 할 수 있습니다. 예를 들면 : div.foo.bar div({className: 'foo bar'}) 와 동일합니다.
프로젝트의 초점은 작은 크기이므로 정신 점검이 부족합니다. 이로 인해 오류에 취약 해집니다. 다음 경고에 대해 매우주의 하십시오.
속성 제거로 업데이트를 트리거 할 수 없습니다. 대신 새 속성을 빈 값으로 설정 해야합니다 . 예를 들어:
// Wrong
R ( div ( { className : 'foo' } ) , document . body ) ;
R ( div ( { } ) , document . body ) ;
// Correct
R ( div ( { className : 'foo' } ) , document . body ) ;
R ( div ( { className : '' } ) , document . body ) ; 구성 요소에서 $ 라는 속성을 사용해서는 안됩니다 . 그렇게하면 속성 객체를 가상 DOM 노드로 간주하고 예상치 못한 결과로 이어질 것입니다.
// *NEVER* do this!
R ( H ( MyComponent , { $ : 'Foo' } ) , document . body ) K(state, components)
plugin-keyed.min.js에서
key 속성에 따라 목록의 구성 요소 상태가 동기화되도록합니다. 이를 통해 반응과 같은 키드 업데이트를 수행 할 수 있습니다.
function ValueRenderer ( ... ) {
...
}
function MyComponent ( props , state ) {
const { values } = props ;
const components = values . map ( value => {
H ( ValueRenderer , {
key : value ,
value : value
} ) ;
} )
// Synchronize state of components, based on their key
return H ( 'div' , K ( state , components ) )
} .Dom 에 기여하는 데 관심이 있습니까? 당신은 환영하는 것 이상입니다! 가이드 라인을 따르십시오.
npm install
npm test && npm run build && ls -l dotdom.min.js.gz
테스트가 통과되고 dotdom.min.js.gz 의 크기가 512 바이트보다 작거나 같으면 풀 요청을 작성하십시오. 그렇지 않으면 범위를 줄이거 나 다른 구현을 생각하여 512 바이트로 되돌려 놓으십시오.
극단적 인 JavaScript 해킹을 수행해야하므로 코드에 올바르게 의견을 제시하십시오. gudeliens는 다음과 같습니다.
/**
* Functions are commented as JSDoc blocks
*
* @param {VNode|Array<VNode>} vnodes - The node on an array of nodes to render
* ...
*/
global . R = render = (
vnodes , // Flat-code comments start on column 70 and
dom , // wrap after column 120.
/* Logical separations can be commented like this */
...Apache 라이센스, 버전 2.0에 따라 라이센스