티스토리 뷰
DOM(Document Object Model)
HTML요소를 Object처럼 조작할수 있는 모델
DOM을 이용하면 HTML을 조작 가능 -> HTML로 구성된 웹 페이지를 동적으로 움직이게 할수 있다.
웹 페이지를 제어하기 위한 목적으로 자바스크립트를 사용
HTML에 javascript를 적용할려면 <script>태그를 이용한다.
<script src = "xxxxxx.js"></script>
<script>요소를 만나면 웹 브라우저는 html해석을 멈추고 <script>부터 먼저 실행한다.
<script> 추가 방법
1. <head> 안쪽에 삽입
HTML 페이지를 파싱하던 중 js파일을 받아오고(Fetching), 실행(Executing)한 뒤 다시 페이지를 파싱하게 된다.
2. <body> 요소 끝나기 전에 삽입
HTML 페이지를 파싱을 먼저 진행하고 JS파일을 받아오고 실행
맨뒤에 삽입하는 이유?
html태그와 CSS가 모두 동작한 다음 불러오기 때문에 미완성된 화면이 지속X
문서의 DOM(Document Object Model)구조가 완료된 시점에서 실행
DOM 구조를 조회할때
console.dir 유용
console.log와 달리 DOM을 객체의 모습으로 출력
console.dir(document.body) //html element에 지정할수 있었던 객체내의 많은 속성들이 존재
console.dir(document.body.children)으로 바로 자식요소 조회가능
자료구조 중 트리구조
부모가 자식 여러개 갖고 부모가 하나인 구조가 반복되는 것
CRUD
DOM을 이용하여 HTML Element를 추가, 조회 변경 삭제하는 방법을 알자
APPEND
DOM을 이용하여 HTML Element를 부모 노드에 포함하는 방법을 알자
CREATE
document객체의 createElement 메서드를 이용하여 <div>요소 만들기
document.createElement('div')
const tweetDiv = document.createElement('div')
APPEND
CREATE에서 생성한 tweetDiv를 트리구조와 연결
append메서드를 이용해 변수 tweeDiv를 <body>에 넣는다.
document.body.append(tweeDiv)
READ
DOM으로 HTML 엘리먼트의 정보 조회 방법
querySelector*셀렉트를 조회한다 의미)의 첫 번째 인자로
셀렉터를 HTML요소("div"),id(#tweetList) .class(.tweet)를 전달하여 확인
클래스 이름이 tweet인 html엘리먼트 중 첫번째 요소 조회
const oneTweet = document.querySelector('.tweet')
여러개 요소 한번에 가져오기
const tweets = document.querySelectorAll('.tweet')
클래스 이름이 tweet인 모든 html 요소를 유사배열(for문 이용가능 , 배열 X)로 받아온다.
const getOneTweet =document.getElementByID('container') 는 비슷한 역할을 하지만
이전 버전의 브라우저 호환성을 신경써야 하면 이것을 사용
create에서 생성한 div요소를 cotainer에 넣는다.
const container = document.querySelector('#container') //DOM 객체를 선택해서 조회(READ)해서 container변수에 할당
//id이름이 container인 html엘리먼트 중 첫번째 엘리먼트 조회
const tweetDiv = document.createElement('div') //create에서 생성한 div요소(CREATE)
container.append(tweetDiv) //container의 마지막 자식 요소로 추가(APPEND)
UPDATE
const oneDiv = document.createElement('div')
oneDiv라는 이름의 div요소 생성
oneDiv.textConent = 'dev'; //<div>dev</div>
textContext를 이용해 문자열 입력
oneDiv.classList.add('tweet') //<div class="tweet">dev</div>
classList.add를 이용해 'tweet'클래스를 추가
const container = document.querySelector('#container') //DOM 객체를 선택해서 조회(READ)해서 container변수에 할당
container.append(oneDiv) //append를 이용해 container의 자식 요소에 oneDiv추가(APPEND)
setAttribute
DLETE
const container = document.querySelector('#container')
//DOM 객체를 선택해서 조회(READ)해서 container변수에 할당
const tweetDiv = document.createElement('div') //create에서 생성한 div요소(CREATE)를 tweetDiv에 할당
container.append(tweetDiv) //append를 이용해 container의 자식 요소에 tweeDiv추가(APPEND)
tweetDiv.remove() //append한 tweetDiv요소를 삭제
하나의 자식요소가 아닌 여러개 자식 요소 삭제
innerHTML
document.querySelector('#container').innerHTML = ' ';
container의 자식 모든 요소가 삭제
removeChild
1.
const container = document.querySelector('#container')
while(container.firstChild) {
container.removeChild(container.firstChild)
}
자식 요소가 남아있지 않을 때까지 첫 번째 자식요소 삭제
container의 첫 번째 자식요소가 존재 -> 첫번째 자식요소 삭제
2.
const container = document.querySelector('#container');
while(container.children.length>1){
container.removeChild(container.lastChild);
}
container의 자식 요소가 1개 남을때까지
마지막 자식 요소를 제거한다.
3.
const tweets = document.querySelector('.tweet')
tweets.forEach(function(tweet){
tweets.remove();
})
forEach ?
주어진 함수를 배열 요소 각각에 대해 실행
배열의 반복문
배열에서만 사용하는 메서드
ex ) const tweets = ['a','b','c'];
const tweecopy =[];
for(let i=0; i<items.length; i++){
copy.push(items[i]);
}
=>
tweets.forEach(function(tweet){
copy.push(tweet);
}
? 여기서 배열에서만 사용할수 있다고 해서 요소는 사용을 못하는지 검색을 해봤다.
querySelector나 querySelectorAll 메서드는 특정 유형의 요소나 모든 요소를 선택하는데 사용된다.
반환된 목록은 배열이 아니라 노드 컬렉션을 포함하는 NodeList 개체이다.
NodeList는 배열이 아니지만 forEach()를 사용하여 반복할수 있다.
NodeList ? NodeList 객체는 노드의 컬렉션
node는 상위개념 , Dom의 관련 객체는 node에서 대부분 파생
node의 기능을 적용한 객체는 element 타입을 많이 사용
BOM ? window객체를 통해 브라우저에 접근
DOM ? document를 통해 html접근
html와 javascript의 객체구조는 트리구조로 javascript 의 dom으로 접근하기 수월
document.cloneNode: 복제하는 메서드
document.importNode : template을 활욯하여 내용을 붙여 넣을 때 사용하는 메서드
또는
for(let tweet of tweets){
tweet.remove();
}
클래스이름이 tweet인 요소만 찾아서 제거
innerHTML ? div안에 있는 HTML 전체 내용을 가져오는 것을 확인
ex)
hi
<span style ='display:none'>innerText는 안보임</span>
innerText ?Element 내에서 사용자에게 '보여지는' 텍스트 값을 읽는다.
hi
textContext ?innetText와는 달리 <script>나 <style> 태그와 상관없이
해상 노드가 가지고 있는 텍스트 값을 그대로 읽는다.
hi
innnerText는안보임
과제-유효성 검사
MVP(Minimum Viable Product)
최소기능 제품으로 고객의 피드백을 받은 최소한의 기능을 구현한 제품
고객 : 아이디 입력창에 글자를 키보드로 입력할때 글자수가 4개 이상이면 사용할수 있는 아이디입니다 라고 메시지 출력
비밀번호와 비밀번호 확인창이 일치하지 않으면 일치하지 않습니다 메시지 출력
먼저, DOM으로부터 필요한 엘리먼트를 불러온다.
let xxxxx = document.querySelector('index.html에 있는 id,class를 불러옴');
elPasswordRetype.onkeyup =function(){
if(isMatch(elPassword.value,elPasswordRetype.value)){ //일치하면
//오류: value값을 안집어넣음
//일치하지 않습니다. 메시지가 숨겨야함
elMismatchMessage.classList.add('hide');
}else{ //일치하지 않으면
//일치하지 않습니다 메시지 보여야함
elMismatchMessage.classList.remove('hide');
}
}
//}
return password1 === password2; //값이 같으면 true 같지 않으면 false
}
onkeydown : 자판에서 키를 눌렀을 때 발생하는 이벤트
onkeypress : 자판에서 키를 누르고 있는 동안 발생하는 이벤트
onkeyup : 자판에서 키를 눌렀다 놓았을 때 발생하는 이벤트
visibility:hidden vs display:none
visibility:hidden 브라우저에서 엘리먼트가 차지하는 영역 그대로 남겨놓음
display:none 브라우저에서 영역 조차 사라짐
let elInputUsername = document.querySelector('#username')
let elFailureMessage = document.querySelector('.failure-message')
let elSuccessMessage = document.querySelector('.success-message')
let elPassword = document.querySelector('#password')
let elPasswordRetype = document.querySelector('#password-retype')
let elMismatchMessage = document.querySelector('.mismatch-message')
let EngnumMessage = document.querySelector('.Engnum-message');
let strongPwMessage =document.querySelector('.strong-password');
let signupBtn = document.querySelector('#signup-btn');
//오류 : signup-btn을 class로 함
//let signUp = document.querySelector('signup');
let validId=false;
let validPassword=false;
let validRetype=false;
elInputUsername.onkeyup = function(){
if(isMoreThan4Length(elInputUsername.value)){ //4글자 넘고
//4글자 이상 실패메시지가 가려야함
elFailureMessage.classList.add('hide');
if(onlyNumberAndEnglish(elInputUsername.value)){ //영숫자입력함
validId=true;
console.log(validId);
//4글자 이상 성공메시지가 보여야함
elSuccessMessage.classList.remove('hide')
//영어 숫자 실패 메시지 가려야함
EngnumMessage.classList.add('hide');
}
else{//영숫자 입력하지 않음
//4글자 이상 실패메시지가 가려야함
elSuccessMessage.classList.add('hide');
//영어 숫자 실패 메시지 보여야함
EngnumMessage.classList.remove('hide');
}
}
else if(!elInputUsername.value){ //입력 값이 없을때
elFailureMessage.classList.add('hide');
elSuccessMessage.classList.add('hide');
EngnumMessage.classList.add('hide');
}
else{ //4글자 넘지 않으면
//4글자 이상 성공메시지가 가려야함
elSuccessMessage.classList.add('hide')
//4글자 이상 실패메시지가 보여야함
elFailureMessage.classList.remove('hide')
if(onlyNumberAndEnglish(elInputUsername.value)){ //영숫자입력함
//영어 숫자 실패 메시지 가려야함
EngnumMessage.classList.add('hide')
}
else{ //영숫자 입력하지 않음
//영어 숫자 실패 메시지 보여야함
EngnumMessage.classList.remove('hide');
}
}
}
//아이디가 4글자 이상 넘었을때
function isMoreThan4Length(value) {
return value.length>=4;
}
//아이디에 영어 또는 숫자를 썻을때
function onlyNumberAndEnglish(str) {
return /^[A-Za-z][A-Za-z0-9]*$/.test(str);
}
elPassword.onkeyup =function(){
if(strongPassword(elPassword.value)){
//비밀번호 8자이상 알숫특 하나이상 포함
//최소 8자 이상 알숫특 하나이상 포함 메시지 가려야함
validPassword =true;
console.log(validPassword);
strongPwMessage.classList.add('hide');
}
else if(!elPassword.value){
//비밀번호 값이 없을때
strongPwMessage.classList.add('hide');
}
else{
//최소 8자 이상 알수록 하나이상 포함 메시지 보여야함
strongPwMessage.classList.remove('hide');
}
}
//비밀번호가 최소 8자 이상하면서, 알파벳과 숫자 및 특수문자(@$!%*#?&) 는 하나 이상 포함
function strongPassword(str) {
return /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/.test(str);
}
//elPassword.onkeyup =function(){ 이것도 됨
elPasswordRetype.onkeyup =function(){
if(isMatch(elPassword.value,elPasswordRetype.value)){ //일치하면
validRetype=true;
//오류: value값을 안집어넣음
//일치하지 않습니다. 메시지가 숨겨야함
elMismatchMessage.classList.add('hide');
}else{ //일치하지 않으면
//일치하지 않습니다 메시지 보여야함
elMismatchMessage.classList.remove('hide');
}
if(validId && validPassword && validRetype){
//따로 뺏더니 회원가입창이 생김 elPasswordRetype 누르자 마자 판단 ?
//조건에 만족시키면 signUp 회원가입버튼 보여야함
signupBtn.classList.remove('hide');
}
else{
//조건 만족하지 않으면 signUp 회원가입버튼 안보여야함
signupBtn.classList.add('hide');
}
}
//비밀번호와 비밀번호 확인이 일치할때
function isMatch (password1, password2) {
return password1 === password2;
}
/*function isAll (value1, value2,value3) {
return value1 === value2 ? (value2 === value3) : false ? true :false;
}*/
script.js와 validatator.js를 동시에 적용했을때 가장 먼저 적은 validatator.js 하나만 적용이 되었다.
할수 없이 script.js안에 모두 넣어서 했긴 했지만
다른 동기들의 답을 보니 , head안에 validatator.js를 넣고 body 마지막에 sctript.js를 넣어주고
validatator.js는 코드 수정없이 유효성 검증 함수만 두고
script.js에서 유효성 검수 함수를 가져와서 수정을 할수 있었다.
따라서 어떤 순서대로 js파일을 html에 적용 시킬지가 중요하다는 것을 알게 되었다.
결과
이벤트 객체
이벤트 객체는 사용자 입력(onclick, onkeyup, onscroll 등)을 트리거로 발생한 이벤트 정보를 담은 객체
어떤 버튼(btn)이 존재
콘솔에 버튼이 눌렸습니다. 출력
1.
btn.onclick = function() {
console.log('버튼이 눌렀다.');
}
2.
btn.addEventListener('click',function(){
console.log('버튼이 눌렀다.');
});
3.
function handler(){
console.log('버튼이 눌렀다.');
}
btn.onclick = handler //이벤트 속성(onclick)에 핸드러(이벤트가 발생했을때 실행되는 함수) 등록
let menus = document.querySelector("button")
let btnAmericano = menus[0];
let btnCaffelatte = menus[1];
btnAmericano.onclick = handleClick;
btnCaffelatte = handleClick;
function handClick(){
let currentMenu = event.target.textContext;
consle.log(currentMenu + "를 클릭");
}
event ? PointerEvent {isTrusted: true, pointerId: 0, width: 1, height: 1, pressure: 0, …}
event.target ? <button>카페라떼</button> or <button>아메리카노</button>
어떤 버튼에 클릭했는지에 따라 타겟이 달라진다
.event.targe.textContext ? 카페라떼 or 아메리카노
이벤트리스너
요소에 특정 이벤트가 발생했을 때 원하는 작업 수행
element.addEventListener(event, function, useCapture);
;element : 이벤트를 등록할 요소
function : 이벤트가 발생했을 때 수행할 함수
useCapture(optional): 이벤트의 캡쳐링 여부 (기본값은 false)
event : 등록할 이벤트 종류
btn.addEventListener("click", function(){ alert("Button was clicked!"); });
document.querySelector('div') : 최상단 div 요소 조회
document.getElementsByTagName('div') :div 요소 전부 조회
document.getElementById('div') :id가 div 요소 하나 조회
document.querySelectorAll('div') : div 요소 전부 조회
.getElementsByClassName('div')rAll('div') :class가 div요소 여러개 조회
let a =document.createElement('a')
aElement.setAttribute('id','so')
aElemen.textCotent ='hi'
innerHTML은 JavaScript에서 사용되는 속성으로, HTML 요소의 자식노드를 가져오거나 설정할 때 사용됩니다.
예를 들어, element.innerHTML은 해당 element의 자식노드를 문자열 형태로 가져옵니다.
let a =document.createElement('a')
aElement.id = 'so'
aElemen.innerHTML ='hi' //HTML tag를 직접 삽입하여 실행하는 것은 지양 , script tag를 활용하여 xss atack일어날수 있음(강제로 해커가 원하는 script를 실행)
removeChild 메서드는 선택된 요소를 부모 요소에서 삭제하며, 삭제된 요소는 다시 사용할 수 없다는 것을 유의
ex) parentNode.removeChild(childNode);
'codestates > section1' 카테고리의 다른 글
unit11-coz'mini hackathon (0) | 2023.01.09 |
---|---|
unit9[javascript]JavaScriptkonans 10문제 (0) | 2023.01.04 |
unit9[javascript] 핵심개념과 주요문법 (0) | 2023.01.03 |
unit8[javaScript]배열,객체 (0) | 2022.12.29 |
unit7[Linux,git기초] (0) | 2022.12.28 |