FxJS-DOM
HTML DOM Bindings for the FxJS
Selector
<div class="container div1" active="true">
<ul class="list1">
<li class="item1">1</li>
<li class="item2">2</li>
<li class="item3">3</li>
</ul>
<div class="div2" active="true">
<ul class="list2">
<li class="item4">4</li>
<li class="item5">5</li>
</ul>
</div>
</div>
$, $.all
$
는 document.querySelector
를 사용하고 $.all
은 document.querySelectorAll
을 사용합니다.
console.log($('.container li'));
console.log($.all('.container li'));
$.find, $.findAll
$.find
는 el.querySelector
를 사용하고 $.findAll
은 el.querySelectorAll
을 사용합니다.
console.log($.find('li', $('.container div')));
console.log($.findAll('li', $('.container div')));
console.log($.find('li', $('.container')));
console.log($.findAll('li', $('.container')));
console.log($.findAll('ul li', $('.container')));
el.querySelector
나 el.querySelectorAll
의 아쉬운점
el.querySelector
나 el.querySelectorAll
의 경우는 셀렉터의 시작으로 >
를 사용할 수 없습니다.
try {
document.querySelector('.container').querySelectorAll('> ul li');
} catch (e) {
console.log(e);
}
el.querySelector
나 el.querySelectorAll
의 경우는 셀렉터의 시작이 부모도 포함하고, 자식요소도 포함한다는 점을 유의해야합니다.
console.log(
document
.querySelector('.container')
.querySelectorAll('[active=true] > ul li')
);
with >, with &
아래 예제는 $.find
, $.findAll
와 el.querySelector
나 el.querySelectorAll
의 차이를 보여줍니다.
$.find, $.findAll
은 >
를 셀렉터의 시작으로 사용할 수 있습니다.&
를 통해 부모 element에 대해서만 추가 조건을 붙일 수 있습니다.
console.log($.findAll('> ul li', $('.container')));
console.log($.findAll('&[active="true"] li', $('.container')));
console.log($.findAll('&[active="true"] > ul li', $('.container')));
console.log($.findAll('&[active="false"] li', $('.container')));
$.closest
자신을 포함하여 셀렉터와 매칭되는 부모 엘리먼트를 찾습니다.
console.log($.closest('li', $('.item4')));
console.log($.closest('ul', $('.item4')));
console.log($.closest('div', $('.item4')));
console.log($.closest('div.container', $('.item4')));
$.children
$.prevAll
$.nextAll
$.prev
$.next
$.is
첫 번째 인자에 전달된 셀렉터와 매칭이 되는지 확인합니다.
console.log($.is('.item1', $('li:nth-child(1)')));
console.log($.is('.item1', $('li:nth-child(2)')));
$.contains
Create
$.els
console.log($.els('<span class="s1">1</span>'));
console.log($.els('<span class="s1">1</span><span class="s2">2</span>'));
$.el
console.log($.el('<span class="s1">1</span>'));
console.log($.el('<span class="s1">1</span><span class="s2">2</span>'));
Manipulation
$.append
$.append($('.comments'), $.el('<div class="comment">새 댓글</div>'));
$.prepend
$.prepend($('.posts'), $.el('<div class="post">새 글</div>'));
$.before
$.after
$.remove
$.remove($('.post'));
$.text
console.log($.text($.el('<div>hi</div>')));
$.setText
console.log($.setText('ho', $.el('<div></div>')));
$.html
console.log($.html($.el('<div><span>hi</span></div>')));
$.setHtml
console.log($.setHtml('<span>ho</span>', $.el('<div></div>')));
$.outerHTML
console.log($.outerHTML($.el('<div><span>hi</span></div>')));
$.setOuterHTML
let el = $('#div1');
$.setOuterHTML('<div id="div1" class="hi2"></div>', el);
console.log($('#div1'));
$.val
console.log($.val($.el('<input type="text" value="hoho">')));
$.setVal
console.log($.setVal('hoho', $.el('<input type="text">')).value);
$.attr
console.log($.attr('type', $.el('<input type="text" value="hoho">')));
$.setAttr
console.log($.setAttr({ status: 'ho' }, $.el('<div status="hi">')));
console.log($.setAttr({ status: 'ho', class: 'ye' }, $.el('<div status="hi">')));
console.log($.setAttr(['status', 'ho'], $.el('<div status="hi">')));
console.log($.setAttr({ status: '' }, $.el('<div status="hi">')));
$.removeAttr
console.log($.removeAttr('status', $.el('<div status="hi">')));
CSS
$.addClass
console.log($.addClass('selected', $.el('div')));
console.log($.addClass('hi ho', $.el('div')));
console.log($.addClass('hi', $.el('<div class="ye">')));
$.removeClass
console.log($.removeClass('selected', $.el('<div class="selected"></div>')));
console.log($.removeClass('hi ho', $.el('<div class="hi ho"></div>')));
console.log($.removeClass('hi', $.el('<div class="ye hi">')));
$.removeClass
console.log($.removeClass('selected', $.el('<div class="selected"></div>')));
console.log($.removeClass('hi ho', $.el('<div class="hi ho"></div>')));
console.log($.removeClass('hi', $.el('<div class="ye hi">')));
$.toggleClass
console.log($.toggleClass('selected', $.el('<div class="selected"></div>')));
console.log($.toggleClass('selected', $.el('<div></div>')));
$.css
$.setCss
$.show
$.hide
$.toggle
$.offset
console.log(
$.offset(
$.append(
$('body'),
$.setCss(
{ position: 'absolute', top: '20px', left: '30px', 'margin-top': '50px' },
$.el('div')))));
$.width
width
$.height
height
$.innerWidth
width + paddingLeft + paddingRight + borderLeft + borderRight
$.innerHeight
height + paddingTop + paddingBottom + borderTop + borderBottom
$.outerWidth
innerWidth + marginLeft + marginRight
$.outerHeight
innerHeight + marginTop + marginBottom
$.scrollTop
$.scrollLeft
$.setScrollTop
$.setScrollLeft
Event
$.on
$.on
은 el.addEventListener
를 대신합니다. $.on
은 이벤트를 등록할 함수를 리턴하며, 커링 방식으로만 사용할 수 있습니다.
- 인자로 받은 함수를 조작하지 않고
el.addEventListener
에 그대로 적용하여, 같은 엘리먼트에 같은 이벤트와 같은 함수를 등록이 되지 않는 el.addEventListener
의 특징을 그대로 유지했습니다. el.addEventListener
의 capture
, passive
등의 옵션을 사용할 수 있습니다.e.preventDefault
, e.stopPropagation
을 사용할 수 있습니다.el.removeEventListener
와 $.off
를 사용할 수 있습니다.
<button type="button" id="btn1">
<span>btn1</span>
</button>
const addClickEvent = $.on('click', function(e) {
console.log(e.currentTarget);
console.log(e.target);
});
addClickEvent($('#btn1'));
addClickEvent($('#btn1'));
$.trigger('click', $('#btn1 span'));
$.on
의 두 번째 인자에 셀렉터를 전달하면 매칭되는 자식요소에 이벤트를 등록합니다. 이 방식은 위임 방식이 아니며, 역시 el.addEventListener
의 주요 특징과 기능을 모두 사용할 수 있습니다.
<div class="articles">
<div class="article">
<button type="button" class="remove"><span>삭제</span></button>
</div>
<div class="article">
<button type="button" class="remove"><span>삭제</span></button>
</div>
</div>
const Articles = {
addEvents: pipe(
$.on('click', '.article:nth-child(1)', function(e) {
console.log(e.currentTarget);
}),
$.on('click', '.article', function(e) {
console.log(e.currentTarget);
}, { capture: true }),
$.on('click', '.remove', function(e) {
console.log('other_data:', e.other_data);
console.log(e.currentTarget);
}))
};
Articles.addEvents($('.articles'));
$.trigger('click', $('.articles .article:nth-child(1) .remove'));
$.trigger('click', $('.articles .article:nth-child(2) .remove'));
$.append($('.articles'), $.el(`
<div class="article new">
<button type="button" class="remove"><span>삭제</span></button>
</div>
`));
Articles.addEvents($('.articles'));
$.trigger('click', $('.articles .article:nth-child(1) .remove'));
$.trigger('click', $('.articles .article:nth-child(3) .remove'));
$.trigger('click', { other_data: 'hi' }, $('.articles .article:nth-child(3) .remove'));
$.off
$.on
에 전달한 모든 인자를 동일하게 전달하여 이벤트를 지울 수 있습니다.
<button type="button" id="btn2"></button>
const eventArgs = ['click', function() { console.log('hi~') }];
$.on(...eventArgs)($('#btn2'));
$.off(...eventArgs)($('#btn2'));
$.trigger('click', $('#btn2'));
$.delegate
이벤트 위임 방식으로 이벤트를 등록합니다. 이벤트를 등록하고자 하는 엘리먼트가 동적으로 간편하게 이벤트를 등록해둘 수 있습니다.
<div class="users">
</div>
go(
$('.users'),
$.delegate('click', '.remove', function() {
console.log('remove user');
}));
$.append($('.users'), $.el(`
<div class="user new">
<button type="button" class="remove"><span>삭제</span></button>
</div>
`));
$.trigger('click', $('.users .remove'));
이벤트 위임 방식은 아래와 같은 옵션들을 사용할 필요가 없는 상황에 한하여 사용하는 것을 권장합니다.
el.addEventListener
의 capture
, passive
등의 옵션을 사용할 수 없습니다.e.preventDefault
, e.stopPropagation
을 사용할 수 없습니다.el.removeEventListener
와 $.off
를 사용할 수 없습니다.mouseleave
, mouseenter
는 정상 동작하지 않습니다.
don.js에서는 이벤트 위임 방식에서 위 기능들을 모두 구현하여 제공했지만, 사실상 브라우저의 이벤트에 대한 모든 동작을 라이브러리 위에 다시 구현하는 장황한 코드들이 필요하며, 경험상 그 실용성이 떨어진다고 생각하여 FxJS-DOM은 해당 기능을 구현하지 않는 컨셉으로 가고자 합니다.
$.delegate + & 응용
<div class="signup" agree="false">
<input type="checkbox">
<button type="button">가입</button>
</div>
go($('.signup'),
$.delegate('change', 'input', function(e) {
$.setAttr({ agree: e.currentTarget.checked }, e.delegateTarget);
}),
$.delegate('click', '&[agree="false"] button', function() {
console.log('동의해주세요!');
}),
$.delegate('click', '&[agree="true"] button', function() {
console.log('감사합니다!');
}));
$.trigger('click', $('.signup button'));
$.trigger('click', $('.signup input'));
$.trigger('click', $('.signup button'));
Data
$.data, $.setData
<div class="item" fxd-data='{"id": 1, "active": true}'></div>
const { id, active } = $.data($('.item'));
console.log(id, active);
const data = $.data($.setData({ id: 1, active: false }, $('.item')));
console.log(data.active);
data.active = true;
console.log($.data($('.item')).active);
Fetch
$.get, $.post, $.put, $.delete
의 Content-Type
은 application/json
으로 설정되어있으며 응답이 오면 JSON 객체를 반환합니다. 4개 함수 모두 필요 인자는 2개 이상이며, 인자를 1개만 전달하면 함수를 리턴합니다.
$.get
$.get('/api/posts', { offset: 0, limit: 10 });
$.post
$.post('/api/posts', { content: 'ho~'});
$.put
$.put(`/api/posts/${post.id}`, post);
$.delete
$.delete(`/api/posts/${post.id}`, undefined);