본문 바로가기
카테고리 없음

jQuery3

by 나나 (nykim) 2018. 6. 29.
jQuery

jQuery - 노드 다루기

2018. 06. 29 Fri.

노드 찾기

jQuery에서는 id 이름, 태그 이름, 클래스 이름, 속성을 통해 노드를 찾을 수 있습니다. 이는 CSS의 셀렉팅과 거의 같습니다. 따라서 속성으로 노드를 찾는 것만 복습하고 넘어가죠 :9

  • $("E[A]") : 속성 A를 포함한 모든 E 노드 찾기
  • $("E[A=V]") : 속성 A의 값이 V인 모든 E 노드 찾기
  • $("E[A^=V]") : 속성 A의 값이 V로 시작하는 모든 E 노드 찾기
  • $("E[A$=V]") : 속성 A의 값이 V로 끝나는 모든 E 노드 찾기
  • $("E[A*=V]") : 속성 A의 값이 V를 포함하고 있는 모든 E 노드 찾기

찾은 노드 다루기

$대상.length

length 프로퍼티를 이용하면 jQuery 객체 내부에 들어있는 노드 개수를 구할 수 있습니다.

$대상.eq(index)

eq() 메서드를 이용하면 찾은 노드의 n번째에 해당하는 노드에 접근할 수 있습니다.

<ul>
    <li>myLi</li>
    <li>myLi</li>
    <li>myLi</li>
    <li>myLi</li>
</ul>

var $liList = $("ul li");
var $li_1 = $liList.eq(1);

위 코드를 보면 HTML 문서에 li 태그가 4개이기 때문에, $liList의 jQuery 객체에는 HTMLLiElement DOM 객체가 4개 들어있습니다. 이때 $liList.eq(1)이 실행되면 $liList에 저장되어 있는 jQuery 객체 내부의 HTMLLiElement 객체 중 1번째 객체를 포함하는 새로운 jQuery 객체가 생성됩니다. 이 값이 $li_1 변수에 저장되는 거죠.

$대상.get(index)

만약 jQuery 내부에 들어있는 자바스크립트 DOM객체에 직접 접근하고 싶다면 .get() 메서드를 사용하면 됩니다.

var $liList = $("ul li");
var li_1 = $liList.get(1);

li_1.style.border="1px solid #333";

위 코드에서 li_1에는 $가 붙지 않았는데 이는 jQuery 객체가 아니기 때문입니다. 즉, 자바스크립트 DOM 객체인 거죠. 한편 다음과 같이 []를 사용해서 접근하는 것도 가능합니다.

var $liList = $("ul li");
var li_1 = $liList[1];

li_1.style.border="1px solid #333";

$대상.each()

each() 메서드는, $대상에 들어있는 노드 개수만큼 매개변수 값으로 넘겨 받은 함수를 반복해서 호출해 줍니다.

$("ul.menu li").each(function(index){
	console.log(this);
	$(this).addClass("on");
});

위 코드의 익명함수 내부의 this는 뭘 의미할까요? 이는 $("ul.menu li")라는 jQuery 객체 내부에 들어있는 index 번째에 해당하는 자바스크립트 DOM을 의미합니다.
그럼 $(this)는 뭐가 다를까요? 앞서 살펴본 것처럼 $는 jQuery 함수이며, 매개변수로 받은 태그 노드 정보를 파싱해 태그와 1:1 대응하는 HTMLElement 객체를 jQuery 객체로 포장해 리턴한다고 배웠습니다. 즉, $(this)는 this를 jQuery 객체로 만든 것 뿐입니다. 왜냐면 우린 이걸 가지고 addClass() 등의 메서드를 쓸 건데, 이건 일반 자바스크립트 DOM에는 없는 기능이잖아요? 따라서 $() 함수를 이용해 일반 자바스크립트 DOM 객체를 감싼 jQuery의 인스턴스로 만들어 addClass() 같은 메서드를 사용해야 합니다. 일종의 형변환 같은 거죠. 정리하자면 $(this)는 this라는 DOM 객체를 쉽게 다루기 위해 this를 jQuery 객체로 만든 것입니다.

$대상.filter("선택자")

찾은 노드 중에서 특정 노드만을 걸러내고 싶을 땐 filter() 메서드를 사용합니다. 이때, filter() 메서드가 찾는 대상은 오직 현재 찾은 노드이며, 현재 찾은 노드의 자손이나 부모는 포함하지 않습니다.

$("ul.menu li").filter(".on").css("border", "3px solid #f00");

$대상.find("선택자") / $대상.children("선택자")

찾은 노드의 자식(자손 포함) 노드 중에서 특정 노드를 찾고 싶을 때 find() 메서드를 사용합니다. 만약 자식 노드에서만 찾고 싶다면 children() 메서드를 사용합니다.

$대상.index() / $목록.index($대상)

$("ul.menu li").click(function(){
	alert( $(this).index() );
});

위 코드처럼 index() 메서드를 사용하면 노드가 위치한 인덱스 값을 쉽게 알 수 있습니다. 앞에서도 알아본 것처럼 이벤트 리스터 내부의 this는 클릭 이베트를 발생시킨 자바스크립트 DOM 객체인데, 이 객체는 클릭한 노드의 인덱스 값을 알아내는 기능이 없습니다. 따라서 인덱스 값을 쉽게 알 수 있는 index() 메서드를 쓰고자 $(this) 구문을 사용한 것입니다.
하나 더, index()메서드를 사용할할 때는 주의할 점이 있습니다.

$("ul.menu li a").click(function(){
	alert( $(this).index() );
});

위 예제의 결과물은 $("ul.menu li a")가 몇 개이든 무조건 index가 0이 나옵니다. 그 이유는 a가 연속해서 위치한 것이 아니라 li*4 > a 와 같이 각 li에 하나씩 있기 때문입니다. 따라서 무조건 index 0이 나올 수밖에 없습니다. 이럴 때는 $목록.index($대상)과 같이 사용해야 합니다.

var $menuLink = $("ul.menu li a");
$menuLink.click(function(){
	alert( $$menuLink.index(this) );
});

즉, <a> 태그 객체를 갖고 있는 jQuery 객체에게 클릭한 DOM 객체가 몇 번째 인덱스인지 물어보면 된는 거죠. 참고로 this 대신 $(this)를 써도 됩니다 :-9


자식 노드 찾기

$대상.children() / $대상.find()

children()메서드는 특정 노드의 바로 하위에 위치한 모든 자식 노드 중 태그 노드만을 찾는 메서드입니다. 여기에 자손 노드는 포함되지 않습니다.자식 노드를 구하는 메서드 중에는 contents()도 있습니다. 요녀석은 태그 노드는 물론 텍스트 노드, 주석 노드 등 모든 자식 노드를 찾아준다는 점이 다릅니다.
매개변수로 "선택자"를 넣어주면 해당 선택자에 해당하는 특정 자식 노드만 찾을 수도 있습니다. $(".main").children(".nykim")는 main 클래스를 가진 부모 노드의 자식 노드 중 nykim이라는 클래스를 가진 노드만 찾아주겠죠!

한편, find() 메서드는 하위 자식 노드뿐만 아니라 모든 자손 노드를 찾아줍니다.

첫 번째 자식 노드 찾기

첫 번째 자식 노드를 찾는 방법은 4가지 정도 있습니다.

  • $대상.children(":first") : children() 메서드에 ":first" 선택자를 추가하여 호출
  • $대상.children().first() : children() 메서드를 이용해 자식 노드를 구한 뒤 first() 메서드를 사용
  • $대상.children().eq(0) : children() 메서드로 구한 자식 노드 중 index가 0번째인 자식을 구함
  • $대상.children(":eq(0)") : children() 메서드에 ":eq(0)" 선택자를 추가하여 호출

그럼 뭐가 제일 효율적일까요?! 이때는 선택자를 이용한 방법이 더 효율적입니다. 전에 언급했듯, 메서드를 여러 번 호출하는 것은 영 조치가 안습미다. 우리는 jQuery 기능을 쓸 때 $만 쓰면 뚝딱 끝나지만, 코드 내부에는 루프를 도는 로직이 들어 있기 때문에 가급적 jQuery 기능 호출을 줄이는 것이 좋다고 했죠. 따라서 children(":first")와 같이 쓰는 걸 추천합니다.

그럼 번외편(?)으로 아래 코드를 효율적으로 바꿔봅시다.

/*기존 방법*/
var $menu = $("ul.menu");
$menu.children(":first").css("width", "50px");
$menu.children(":last").css("width","100px");
/*보다 효율적인 방법*/
var $menu = $("ul.menu");
var $children = $menu.children();
$children.first().css("width", "50px");
$children.last().css("width","100px");

마지막 자식 노드 찾기

요래조래 다양한 방법이 있지만 자주 쓰는 건 역시 선택자를 이용한 방법입니다.

  • $대상.children(":last")
  • $대상.children().last()
  • $대상.children().eq(-1)
  • $대상.children(":eq(-1)")
  • $대상.children().eq($대상.children().length-1)

n번째 자식 노드 찾기

얘도 마찬가지로 가급적 메서드 호출을 줄일 수 있는 방법으로 이용합시다.

  • $대상.children().eq(n)
  • $대상.children(":eq(n)")

부모 노드 찾기

$대상.parent() / $대상.parents(["선택자"])

parent()메서드는 바로 상위 노드인 부모 노드만을, parents()메서드는 모든 조상 노드를 찾습니다. 괄호 안에 매개변수로 선택자를 넣으면 해당 선택자에 해당하는 노드만 찾아주는 것도 똑같습니다.


형제 노드 찾기

$대상.prev() / $대상.prevAll(["선택자"])

특정 노드의 이전 형제 노드 또는 모든 이전 형제 노드를 찾습니다. prev()를 두 번 쓰면 이전의 이전 형제(...)에게 접근할 수 있죠.

$대상.next() / $대상.nextAll(["선택자"])

next()메서드는 prev() 메서드와 반대되는 메서드로, 특정 노드의 바로 다음에 있는 형제 노드를 찾고 싶을 때 사용합니다.