이미 가지고있는 HTML로 UI 구성 요소를 구축하십시오.
2KB Gzipped 및 6KB 미니! ?
data 속성을 삭제하십시오 < div data-component =" Counter " >
< p data-bind =" state:Counter.count " > 0 </ p >
< button data-action =" click->Counter.decrement " >
-1
</ button >
< button data-action =" click->Counter.increment " >
+1
</ button >
</ div >class 구성 요소를 작성 하시겠습니까? import { Component } from "domponent" ;
export default class Counter extends Component {
constructor ( el ) {
super ( el ) ;
}
increment ( ) {
this . setState ( { count : this . state . count + 1 } ) ;
}
decrement ( ) {
this . setState ( { count : this . state . count - 1 } ) ;
}
} import { Init } from "domponent" ;
import Counter from "./Counter.js" ;
const config = {
selector : document . getElementById ( "root" ) ,
components : {
Counter
} ,
appCreated : callbackFunction
} ;
new Init ( config ) ;그리고 당신은 가기 좋다 !!
이 라이브러리는 사전 사전 HTML을 UI 구성 요소로 전환하는 깨끗하고 현대적인 방법을 설정합니다. 이 스크립트의 일부 규칙을 사용하여 일부 데이터 바인딩을 쉽게 구현하고, 범위를 처리하고, 데이터를 전달하고, 구성 요소를 만들 수 있습니다. 그것은 약간의 반응 풍미 (수명주기 방법, 소품 및 구성 요소 상태)를 가진 자극에 대한 매우 가벼운 대안이기도합니다.
Domponent는 클라이언트 측면 렌더링을 상자에서 처리하지 않으며 가상 DOM을 생성하지 않으며 DOM이 차이가 없지만 상태와 소품이 다릅니다). 라우팅 또는 전체 응용 프로그램 상태를 처리하는 것은 아닙니다. HTML 조각 (Thymeleaf, Rails, Pug, 사용하는 템플릿 엔진)을 사용하여 구성 요소 형태로 재사용 가능한 기능을 작성해야합니다.
Domponent는 어떤면에서 녹아웃과 유사합니다.
Knockoutjs와 달리 Domponent :
녹아웃
HTML
< p > First name: < input data-bind =" value: firstName " /> </ p >
< p > Last name: < input data-bind =" value: lastName " /> </ p >
< h2 > Hello, < span data-bind =" text: fullName " > </ span > ! </ h2 >JS
var ViewModel = function ( first , last ) {
this . firstName = ko . observable ( first ) ;
this . lastName = ko . observable ( last ) ;
this . fullName = ko . pureComputed ( function ( ) {
return ` ${ this . firstName ( ) } ${ this . lastName ( ) } ` ;
} , this ) ;
} ;
ko . applyBindings ( new ViewModel ( "Planet" , "Earth" ) ) ;Domponent
HTML
< div data-component =" Hello " data-state =" { " firstName ": "Planet", "lastName": "Earth"}" >
< p > First name: < input data-action =" input->Hello.setFirstName " /> </ p >
< p > Last name: < input data-action =" input->Hello.setLastName " /> </ p >
< h2 > Hello, < span data-bind =" state:Hello.fullName " > </ span > ! </ h2 >
</ div >JS
import { Component } from "domponent" ;
export default class Hello extends Component {
constructor ( conf ) {
super ( conf ) ;
}
setFirstName ( event ) {
this . setState ( { firstName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setLastName ( event ) {
this . setState ( { lastName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setFullName ( ) {
this . setState ( {
fullName : ` ${ this . state . firstName } ${ this . state . lastName } `
} ) ;
}
}https://tamb.github.io/domponent/
TODO 목록 : https://codesandbox.io/embed/domponent-todo-with-undo-redo-p3s2?fontsize=14
로컬 데모
git clone reponpm installnpm run build:html-dev 또는 npm run build:html-prod npm install -- save domponent 이 파일을 가져 와서 domponent/dist/domponent.es5.production.min.js 가져 오면 ES5 버전을 사용할 수 있습니다.
트랜스 필러를 사용하지 않는 경우 ES5 UMD를 사용하는 것이 좋습니다. JSDELVR 링크는 다음과 같습니다.
// production
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.production.min.js" defer > </ script >
// development
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.development.min.js" defer > < / script > 참고 : 원하는 만큼이 라이브러리를 사용하거나 거의 사용하지 마십시오. data-component , data-ref 및 data-ref-array 속성에만 사용하여 DOM 선택을 훨씬 쉽게 사용할 수 있습니다. Exponent 클래스로 무국적 구성 요소를 만들 수 있습니다. 하늘은 한계입니다. 핵심적으로 Domponent는 HTML을위한 유틸리티 클래스 세트입니다.
data-component 우리는이 나쁜 소년을 사용하여 구성 요소 이름과 일치하는 Init 구성 객체의 해당 class 와 일치합니다.
예 : html이 data-component="Counter" 인 경우 Counter 라는 구성에 구성 요소가 있어야합니다.
data-bind state 또는 props 요소의 textContent 에 바인딩하는 첫 번째 state 또는 props data-bind="state:Counter.count" 또는 data-bind="props:Counter.count" 왼쪽 절반의 왼쪽 절반을 바인딩 할 수있는 객체를 알려줍니다 :
data-action구성 요소 방법으로 DOM 이벤트를 바인딩합니다. 다음을 고려하십시오.
< button data-action =" click->Counter.increment " >
+1
</ button > 왼쪽 절반 : DOM 이벤트가들을 문자 그대로 문자열을 나타냅니다. 오른쪽 절반은 구성 요소 방법에 해당합니다
참고 : 파이프로 여러 리스너를 추가 할 수 있습니다 | 예:
< button data-action =" click->Counter.increment|mouseover->Counter.anotherMethod " >
+1
</ button > eventListener 옵션도 전달할 수 있습니다. 옵션은 다음이어야합니다 . 수업 방법 후. 옵션은 쉼표로 분리해야합니다 ,
< button
data-action =" click->Counter.increment.passive,capture|mouseover->Counter.anotherMethod.once,passive "
>
+1
</ button > data-state 구성 요소를 메모리에서 특정 상태로 인스턴스화하려면 구성 요소의 루트 요소 에 data-state 속성을 첨부해야합니다.
<div data-component="Counter" data-state='{"count":24, "isEven": true}'>
...
</div>
좋아요. data-state 유효한 JSON 객체를 취합니다.
data-ref DOM 요소를 참조 해야하는 경우 data-ref 사용할 수 있습니다.
< div data-ref =" Counter.myElement " > </ div > 요소가 켜져있는 구성 요소를 서문해야합니다. 그런 다음 구성 요소 $refs 객체에 저장됩니다.
그런 다음 구성 요소 인스턴스 내에서 this.$refs.myElement 사용하여 Counter 에서 요소에 액세스 할 수 있습니다.
data-ref-array이 방법으로 구성 요소에 요소 배열을 만들 수 있습니다.
< div data-ref-array =" Counter.elements " > </ div >
< div data-ref-array =" Counter.elements " > </ div > 그런 다음 구성 요소 $refs 객체에 저장됩니다. 구성 요소의 요소 배열에 액세스 할 수 있습니다 this.$refs.elements .
data-key 이것은 완전히 선택 사항입니다. 각 구성 요소 인스턴스에 대한 고유 한 문자열입니다.
이것은 내부적으로 소품을 바인딩하는 데 사용됩니다. 따라서 소품을받는 구성 요소의 $key 알아야합니다.
< div data-component =" Counter " data-key =" aUniqueKey " >
...
</ div >템플릿 언어로 이것을 반복하고 있다고 가정 해 봅시다. 키가 고유한지 확인해야합니다.
# for (let i=0; i < 10 ; i++){
< div data-component =" Counter " key =" `aUniqueKey${i}` " > ... </ div >
} 이 속성을 사용하지 않으면 각 구성 요소 인스턴스에 고유 키가 자동으로 할당됩니다. this.$key
data-props 부모 구성 요소의 상태를 아동 구성 요소에서 props 으로 공유 할 수 있습니다. 마크 업은 이렇게 보일 것입니다
< div data-component =" Counter " key =" parentCounter " >
< div
data-props =" myAwesomeProp<-parentCounter:ofFive "
data-component =" DisplayAnything "
> </ div >
</ div > 화살표 <- 의 왼쪽은 DisplayAnything 구성 요소의 소품의 이름입니다. 화살표의 오른쪽은 상위 구성 요소의 $key , 콜론 : 상속 된 state 의 이름입니다.
그런 다음 라이프 사이클 메소드 propsWillUpdate 및 propsDidUpdate 를 사용하여 자녀 구성 요소 내에서 변경할 수 있습니다.
Component 클래스를 확장 하시겠습니까?카운터를 계속합시다. 구성 요소를 작성하는 데 필요한 최소 JS는 다음과 같습니다.
class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
}
} super 구성 요소에 필요한 기본 방법과 속성을 추가합니다.
상태를 직접 돌연변이하지 마십시오. this.setState 전화하십시오
setState ( stateObject , callbackFunction ) ;이는 React의 SetState와 개념이 비슷합니다. 비록 다르게 구현되었지만.
JS 구성 요소에 기본 상태를 추가하여 DOM에서 재정의 할 수 있습니다.
export default class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
this . state = {
count : parseInt ( this . state . count ) || 0 ,
isEven : this . state . count
? this . state . count % 2 === 0
? true
: false
: true ,
stateFieldFromDOM : this . state . stateFieldFromDOM || "default cat" ,
stateFieldDefault : "default iPhone 11"
} ;
this . setState ( this . state ) ;
} <div data-component="Counter" data-state="{"count": 4, "isEven":true, "stateFieldFromDOM": "some value here"}"
위의 상태 필드는 기본 JS 상태 필드를 무시합니다.
setState 의 값 바인딩은 항상 textContent 입니다. 상태/소품을 사용하여 HTML을 렌더링하려면 해당 값에 대한 감시자를 추가하고 새 HTML을 수용 할 $refs 노드를 업데이트 할 수 있습니다.
watch ( ) {
return {
count : {
post ( newCount ) {
this . $refs . exclaimCount . innerHTML = `<div class="uppercase"> ${ newcount } !</div>` ;
}
}
}
}다음은 수명주기의 다양한 지점에서 구성 요소에 액세스하는 데 사용할 수있는 방법입니다.
| 수명주기 방법 | 문맥 | 설명 |
|---|---|---|
| 연결 | 구성 요소/지수 | 라이브러리가 구성 요소/지수를 올리기 전에 다른 방법에 액세스 할 수 있습니다. |
| 연결 | 구성 요소/지수 | 구성 요소/지수가 연결된 후 모든 이벤트리스트 리너가 제자리에 있습니다. |
| 연결을 끊습니다 | 구성 요소/지수 | 이벤트리스트 테너를 제거하고 메모리에서 구성 요소/지수를 삭제하기 전에 |
| propswillupdate | 구성 요소/지수 | 성분 내에서 소품이 업데이트되기 전에 DOM 돌연변이가 발생하지 않았습니다. |
| propsdidupdate | 구성 요소/지수 | 소품이 업데이트되고 DOM이 변경된 후 |
| StateWillupdate | 요소 | 현재 구성 요소의 상태 또는 부양 가족이 변경되기 전에 |
| 명시 적용 | 요소 | 상속 된 소품이있는 아동 구성 요소는 DOM 조작을 수행했으며 상태와 소품이 변경되었습니다. |
Component 및 Exponent 클래스에는 객체를 반환 해야하는 watch 방법이 있습니다. 감시자는 구성 요소 수명 기간 동안 특정 state 또는 props 값 변경에 연결할 수 있습니다. 이를 통해 stateWillUpdate , stateDidUpdate , propsWillUpdate 또는 propsDidUpdate 와 함께 모든 것을 막는 대신 상태 논리를 분리 할 수 있습니다. 이것은 Vue.JS 에서 감시자를 밀접하게 모방하기위한 것입니다. 참고 : state 와 props 필드의 이름을 동일하게 지정하지 마십시오. 이것은 나쁜 연습이며 감시자들을 깨뜨릴 것입니다.
watch ( ) {
return {
myField : {
pre ( newValue , oldValue ) {
// my logic
} ,
post ( newValue ) {
// my logic
}
}
}
} Components $watchers Object에서 시청 상태 필드를 볼 수 있습니다.
Exponent 클래스를 확장하여 props 만으로 구성 요소를 생성하여 Component 보다 약간 밝습니다. 더 빨리 연결하고 메모리를 덜 차지합니다.
import { Exponent } from 'domponent'
class StatelessThing extends Exponent{
constructor(conf){
super(conf);
}
}
그런 다음 다음에만 액세스 할 수 있습니다.
propsWillUpdatepropsDidUpdate 왜 Exponent ??
주어진 데이터를 단순히 해석하거나 설명하기 때문에 구성 요소처럼 들리기 때문입니다.
구성 요소 또는 지수에는 다음 분야가 제공됩니다.
| 필드 이름 | 유형 | 입장 | 문맥 | 설명 |
|---|---|---|---|---|
| $ 앱 | 물체 | 공공의 | 구성 요소/지수 | 전체 domponent 응용 프로그램 |
| $ b | 정렬 | 사적인 | 구성 요소/지수 | 내부 사용을위한 EventListener 바인딩 |
| $ d | 물체 | 사적인 | 요소 | 부모 구성 요소는 자녀를 참조합니다 |
| $ 키 | 끈 | 공공의 | 구성 요소/지수 | 구성 요소 인스턴스의 고유 식별자 |
| $ 이름 | 끈 | 공공의 | 구성 요소/지수 | 구성 요소 유형의 이름입니다 |
| $ p | 물체 | 사적인 | 구성 요소/지수 | 소품의 내부 컬렉션 및 DOM 참조 |
| 소품 | 물체 | 공공의 | 구성 요소/지수 | 통과 된 데이터의 키/값 쌍 |
| $ 루트 | 요소 | 공공의 | 구성 요소/지수 | 구성 요소의 루트 돔 노드 |
| $ s | 물체 | 사적인 | 요소 | 내부 상태 및 DOM 참조 |
| 상태 | 물체 | 공공의 | 요소 | 키/값 업데이트 할 수있는 데이터 쌍 |
| $ 감시자 | 물체 | 공공의 | 요소 | 저장된 변경 기능 및 해당 상태 및 소품 키 |
Init 기능? 이 기능은 앱을 생성하고 모든 구성 요소를 등록합니다. 필요한 인수로 config 객체를 사용합니다.
const config = {
selector : document . getElementById ( "root" ) ,
components : { Counter } ,
appCreated : callbackFunction
} ;
const App = new Init ( config ) ;그런 다음 다음 방법을 노출시킵니다.
그리고 다음 객체 :
구성 요소의 components 객체를 제외하고 시작할 구성 요소없이 앱을 만들 수도 있습니다.
createComponent@params :
App . createComponent ( document . getElementById ( "added-html" ) , callback ) ; register@params
App . register ( NewComponent , callback ) ; deleteComponent@params :
data-key 통해 할당하거나 this.$key App . deleteComponent ( "my-component-instance-key" , callback ) ; unregister@params :
App . unregister ( "NewComponent" , callback ) ; 다른 선택기, 라이브러리 등과 충돌하는 data- 속성을 피하려면 앱 구성 객체에서 기본 속성 이름을 무시할 수 있습니다.
Init ( {
selector : getElementById ( 'root),
components : { Counter } ,
dataAttributes : {
component : 'mynamespace-component' ,
state : 'cool-state' ,
}
} ) ;이것은 귀하의 HTML이 다음과 같습니다.
< div data-mynamespace-component =" Counter " data-cool-state =' {"count":12} ' >
...
</ div >HTML에서 사용하는 구문을 선택적으로 사용자 정의 할 수 있습니다. 다음 항목을 사용자 정의 할 수 있습니다.
INHERITS_FROM: '<-',
FROM_COMPONENT: '.',
KEY_VALUE: ':',
MULTIPLE_VALUES: "|",
METHOD_CALL: "->",
LIST: ","
이것은 구성에서 다음을 추가 할 수 있음을 의미합니다.
{
customSyntax : {
LIST : "!" ,
METHOD_CALL : "#"
}
}그리고 당신의 HTML은 이것을 사용할 수 있습니다!
Domponent와 함께 개발할 때 개발 빌드를 사용하여 Development DOM (이 Guy->)에서 콘솔에 유용한 오류와 로그를 추가합니다.
이것을 사용하는 가장 쉬운 방법은 WebPack Aliases와 관련이 있습니다.
resolve : argv . mode === 'development' ? {
alias : {
domponent : 'domponent/dist/domponent.development.js'
}
} : { } ,이렇게하면 Webpack의 개발 빌드는 Domponent의 프로덕션 버전을 DOM의 도움으로 뿌려진 버전을 교체합니다.
다양한 템플릿 엔진에 대한 구성 요소 HTML을 작성하여 엔진이 "HTML의 청크"라고하는 부분/조각으로 포함시킬 수 있습니다 .
다음은 Domponent를 사용하는 방법에 대한 몇 가지 예입니다.
참고 : 마크 업에서 이러한 구문 차이에도 불구하고 구성 요소는 단순히 JS 클래스 ✌️임을 기억하십시오.
퍼그 구문 예 ?
// counter.pug
mixin counter ( count )
div ( data - component = "Counter" data - state = `
{
"count": count,
"isEven": count % 2 === 0
}
` )
p ( data - bind = "state:Counter.count" ) # { count }
button ( data - action = "click->Counter.increment" ) + 1
button ( data - action = "click->Counter.decrement" ) - 1
// usage
+ counter ( 101119 )
+ counter ( 61316 )Thymeleaf Syntax 예 ?
// counter.html
< div
data-component =" Counter "
th:fragment =" Counter "
th:data-state =' |{"count":${count}, "isEven": ${count % 2 == 0}}| '
>
< p data-bind =" state:Counter.count " th:text =" ${count} " > </ p >
< button data-action =" click->Counter.increment " >
+1
</ button >
< button data-action =" click->Counter.decrement " >
-1
</ button >
</ div >
// usage
< th:block th:replace =" ./counter.html :: Counter(count: 1289) " />
< th:block th:replace =" ./counter.html :: Counter(count: 491) " />Razor Syntax 예제 ⚔️ 출시 예정 ...
Ruby on Rails 구문 예 ? 곧 올다 ...
콧수염 구문 예 ? 곧 올다 ...
domponent [at] gmail [dot] com ( 주제 Domponent Support 사용하거나 응답하지 않음 )@domponent