[ KDT] 핀테크 서비스프론트앤드 개발자 - TIL #7

Suhyxn·2022년 5월 9일
0

7주차 5/7 ~ 5/14


DOM(Document Object Model)

Element

Element 타입은 HTML 요소를 표현하며 이를 통해 태그 이름이나 자식, 속성 같은 정보에 접근이 가능하다.

document.querySelector('div')
  • DOM 탐색하기
  • //DOM
    //Document Object Model
    
    const divEl = document.querySelector('div')
    console.log(divEl.id) //하나의 문자데이터로 아이디를 출력해줌 2개라면 'abc efg'로 한개의 문자로 출력
    console.log(divEl.id.split(' '))// 아이디를 여러개를 각각 받 고 싶으면 split 을 사용해서 배열로 반환 가능
    
    console.log(divEl.className)// div의 class 값을 반환해준다 'btn btn-xs'와 같이 여러 클래스가 있는 경우 하나의 문자열로 반환
    
    //클래스 추가(add), 제거(remove), 확인(contains)
    console.log(divEl.classList.add('abc'))
    console.log(divEl.classList.remove('abc'))
    console.log(divEl.classList.contains('abc')) // boolean 값으로 반환
    document.getElementById('abe')
    // 성능 문제로 ID를 선택할 경우 .getElementById를 사용했었지만 현재는 성능 차이가 거의 없다고 볼 정도로 무방하다.
    const divEl = document.querySelector('div')
    
    console.log(divEl.parentNode)
    //부모 요소 
    console.log(divEl.previousElementSibling)
    //이전 형제 요소 
    console.log(divEl.nextElementSibling)
    //이후 형제 요소 
    
    //나의 부모의 다음 형제 
    console.log(divEl.parentNode.nextElementSibling)
  • HTML 구조 보기
  • const divEl = document.querySelector('div')
    
    console.log(divEl.innerHTML)//이 요소의 내부 html 구조를 얻을 수 있다. 
    console.log(divEl.textContent) // 이 요소가 가지고 있는 내용 중에 text만 보여 준다.
    //.innerText는 사용을 비추천한다고 한다.
  • innerHTML, textContent 는 getter이자 setter 이다.
  • divEl.textContent = '<h1>hello</h1>' // 그냥 문자로 넣어줌
    divEl.innerHTML = '<h1>hello</h1>' //html 요소로 넣어줌
    
  • 요소를 넣을 때
  • // 권장하지 않는 방법
    divEl.append('<h2>Hi!</h2>') //내부의 뒤에 text로 들어감
    divEl.prepend('<h2>Hi!</h2>')//내부의 앞으로 text로 들어감
    
    // 권장하는 방법
    const h2El = document.createElement('h2')
    h2El.textContent='hi!!'
    divEl.append(h2El)
    
    h2El.innerHTML=/* html */`<h1>hello</h1>` 
    divEl.append(h2El)
  • 여러가지 요소들을 추가할 때
  • const h2El = document.createElement('h2')
    h2El.textContent='hi!!'
    const h2El2 = document.createElement('h2')
    h2El2.textContent='hi!!'
    divEl.append(h2El, h2El2)
    
    // 반복문 써서 넣기
    let h2Els = []
    for (let i = 0; i < 10; i += 1){
      const h2El = document.createElement('h2')
      h2El.textContent = i
      h2El2.push(h2El)
    }
    divEl.append(...h2Els) //전개 연산자를 넣어서 배열의 괄호를 제거해 주고 추가할 때 한 번에 추가하도록 한다. 
  • 요소 속성 지정
  • const divEl = document.querySelector('div')
    
    //attributes
    console.log(divEl.getAttribute('title')) // title 속성 값을 가지고 온다.
    divEl.setAtribute('title', 'abbaba') //title 속성의 값이 지정된다.
    

    data-이름 html 요소에 data를 잠깐 보관해 두는 용도로 사용된다.

    //dataset
    const user = {
      name: 'Flyda',
      age: 85
    }
    divEl.dataset.user = JSON.stringify(user)
    console.log(JSON.parse(divEl.dataset.user))
  • 항상 Jacascript 와 HTML 사이 표기법을 주의하도록 하자!
  • ex ) user-name , userName

    => _.kebabCase() 를 적극 활용하자!

    //요소 크기 알아내기 
    console.log(divEl.clientWidth,divEl.clientHeight)
    
    //요소 위치
    console.log(divEl.clientTop)
    console.log(divEl.clientLeft)
    
    // 요소 렌더링 정보 // 중요!! 사각형이 화면에서 가지고 있는 모양 알아본다. 
    console.log(divEl.getBoundingClientRect()) //DOMRect 정보..
    // 호출될때 마다 화면을 계산해야하기때문에 남발 X! 유용하지만 주의하기!!
    
    // 요소 추가하기 
    const h1El = document.createElement('h1')
    h1El.id = 'abc'
    //h1El.setAttribute('id', 'abc')
    h1El.setAttribute('title', '123')
    h1El.className.padEnd('btn')
    
    document.body.append(h1El) 

    NODE

    Element는 node의 특정 타입 즉, Node.ELEMENT_NODE로, 각 노드는 부모와 children을 가질 수 있다.

    document.querySelectorAll('div')

    const divEl = document.querySelector('div')
    console.log('Element: ', divEl.childNodes)
    
    const divEls = document.querySelectorAll('div')
    console.log('', divEls)
    divEls.forEach(el => {
      console.log(el)
    })
    
    for (const el of divEls) {
      console.log(el)
    }

    Event handler == Callback

    const divEl = document.querySelector('div')
    const inputEl = document.querySelector('input')
    
    // const hanlder = function () {
    // 함수내용
    // }
    // divEl.addEventListener('click', hanlder)
    
    divEl.addEventListener('click', event => {
      console.log(event) //event의 target 부분 중요! 
    }) 
    
    
    // 대화형 사용자가 입력할 때 마다
    inputEl.addEventListener('input', event => {
      console.log(event) //data 속성(입력한 값), target 중요
      //input은 value라는 속성에 사용자가 입력한 데이터가 들어가 있다
      console.log(event.target.value) //evet의 target에 입력된 값
    })
    //event.key
    inputEl.addEventListener('keydown', event =>{
      console.log(event.target.value)
    })
    //keydown, keyup은 한글을 입력할때 엔터를 치면 2번 입력되는 이슈가 있다. 
    //그럴때는 이렇게 해결하기!! 
    inputEl.addEventListener('keydown', event =>{
      console.log(event.isComposing) // 어떤 키를 눌렀을 때 한글이 입력이 끝나지 않으면 true
      if (event.isComposing) return  // 이코드로 해결!!
      console.log(event.target.value)
    })

    Bubbling

  • 한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작하여 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작하는 현상을 말한다.
  • 거의 모든 이벤트는 버블링 됩니다.
    키워드는 ‘거의’ 입니다. focus 이벤트와 같이 버블링 되지 않는 이벤트도 있습니다.

    Capturing

  • 버블링과 반대 현상으로 최상위 태그에서 해당 태그를 찾아 내려가며 동작한다.
  • const parentEl = document.querySelector('.parent')
    const childEl = document.querySelector('.child')
    
    const heropy = () => {
      console.log('Child!')
    }
    
    childEl.addEventListener('click', heropy)
    parentEl.addEventListener('click', ()=> {
      childEl.removeEventListener('click', heropy)
    })
    window.addEventListener('click', ()=> {
      console.log('window')
    }, {
      capture: true // 캡처링 설정, 잘 사용되지 않으며 기본값은 false로 설정되어 있다.
    })
    
    //순서 확인
    document.body.addEventListener('click', ()=> {
      console.log('body!')
    })
    childEl.addEventListener('click', ()=> {
      console.log('child!')
    })
    parentEl.addEventListener('click', ()=> {
      console.log('parent!')
    })
    window.addEventListener('click'l, ()=> {
      console.log('window!')
    }) // 버블링 발생으로 가장 안쪽 태그에서 부터 버블링이 발생한다.
    // child! > parent! > body! > window! 순으로 발생
    // capture 값 true일 경우 설정한 값 (window) > child! > parent! > body! > window! 순으로 발생
    

    핸들러를 지울시 꼭 같은 단계에 remove를 적어 주어야 한다.

    button.addEventListener('click', () => {
      childEl.removeEventListener('click', heropy, {
        capture: true // capture 속성을 준 태그를 remove 할 때는 remove 태그에도 capture 속성을 주어야 한다.
      })
    })

    Bubbling 방지

    // 태그 기본 동작 방지
    parentEl.addEventListener('wheel', event => {
      event.preventDefault() // 기본 동작이 실행되지 않는다.
    })
    
    //
    childEL.addEventListener('click', event => {
      event.stopPropagation() // 태그에서만 버블링 발생
      console.log('child!')
    })
    
    parentEL.addEventListener('click', event => {
      console.log('parent!') // stopPropagation으로 전파되지 않아 뜨지 않는다 (버블링 방지)
    })
    
    // ex) 드롭다운을 닫기 위해서 window에 걸고 드롭다운에 stopprogation을 건다

    .capture 와 유사한 .addEventListener Method

    parentEl.addEventListener('wheel', event => {
      for (let i = 0; i < 10; i += 1) {
        console.log(event)
      }
    }, {
      passive: true // 사용성 향상 ( 화면과 로직 처리를 분리해 준다.)
      //once: true // 한 번만 실행한다.
      //capture: true // 캡처링 설정
    })

    0개의 댓글