일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 티스토리 쿠키 삭제
- 서버설정
- 처음 만나는 AI 수학 with Python
- Kernighan의 C언어 프로그래밍
- GIT
- 스프링부트핵심가이드
- 네트워크 설정
- 리눅스
- iterator
- d
- 알파회계
- 목록처리
- /etc/network/interfaces
- network configuration
- 구멍가게코딩단
- ㅒ
- 자료구조와함께배우는알고리즘입문
- 코드로배우는스프링부트웹프로젝트
- 자료구조와 함께 배우는 알고리즘 입문
- 페이징
- 이터레이터
- 자바편
- 코드로배우는스프링웹프로젝트
- 스프링 시큐리티
- 데비안
- 처음 만나는 AI수학 with Python
- baeldung
- 선형대수
- resttemplate
- 친절한SQL튜닝
- Today
- Total
bright jazz music
[프레임워크 없는 프론트엔드 개발] 1.2. 뷰 함수 분리 본문
https://catnails.tistory.com/577
[프레임워크 없는 프론트엔드 개발] 1.1. 순수함수를 이용한 렌더링 구현
https://github.com/hojuncha997/frameworkless-front-end-dev GitHub - hojuncha997/frameworkless-front-end-dev: 프레임워크 없는 프론트엔드 서적 학습 리포지토리프레임워크 없는 프론트엔드 서적 학습 리포지토리. Contribut
catnails.tistory.com
이전 포스팅에서 다뤘던 view.js의 함수는 DOM 을 조작하는 함수가 하나뿐이었다. 이번에는 해당 함수를 기능별로 나누었다.
프로젝트 디렉토리의 루트 경로에 view 디렉토리를 만들고 아래의 파일을 만들어 주었다.
1. /view 디렉토리 내부의 파일 설명
- app.js (작은 뷰 함수들로 이루어진 뷰 함수)
: 컨트롤러 역할을 하는 index.js로부터 변경해야 할 HTML 요소와 상태(배열과 필터 텍스트)를 넘겨 받는다. 그리고 아래 파일(함수)들에 분배한다. 함수들로부터의 반환값은, 깊은 복사를 한 HTML 요소에 적용하고 이 복제된 요소를 다시 반환한다.
- todo.js (할일 목록을 렌더링하는 뷰 함수)
: app.js로부터 HTML 요소와 상태를 인자로 받는다. 상태를 사용해 <li> 태그로 이루어진 텍스트를 만들고 그것을 다시 HTML 요소에 적용하여 변경된 HTML 요소를 반환한다.
- counter.js (할 일 개수를 렌더링 하는 뷰 함수)
: app.js로부터 HTML 요소와 상태를 인자로 받는다. 상태 객체 내부의 배열의 길이를 텍스트로 만들고, 인자로 받은 HTML요소의 textContent 메서드를 사용하여 텍스트 값을 적용한 뒤 반환한다.
- filter.js ( 필터링을 이후 결과를 렌더링하는 뷰 함수)
: app.js로부터 HTML 요소와 상태를 인자로 받는다. 건네 받은 요소의 하위 요소 가운데 textContent값이 인자로 받은 상태 객체의 currentFilter 속성 값과 같으면 selected라는 css class를 해당 요소에 추가한 뒤 반환한다.
2. 파일 내용
2.1. /index.js
:기존 view.js 대신 app.js를 임포트한다.
// /index.js
// 컨트롤러 역할을 하는 파일
import getTodos from './getTodos.js'
// import view from './view.js'
import view from './view/app.js' // 기존 view.js 대신 view/app.js 사용. app.js에서는 분리된 뷰 함수들을 사용한다.
const state = {
todos: getTodos(),
currentFilter: 'All'
}
const main = document.querySelector('.todoapp')
window.requestAnimationFrame(() => {
// 뷰 함수를 호출하여 투두 앱 요소를 반환한다.
const newMain = view(main, state)
// DOM에서 기존 요소를 제거하고 새 요소를 삽입한다.
main.replaceWith(newMain)
})
2.2. /view/app.js
// /view/app.js
import todosView from './todos.js'
import counterView from './counter.js'
import filtersView from './filters.js'
export default (targetElement, state) => {
const element = targetElement.cloneNode(true)
const list = element
.querySelector('.todo-list')
const counter = element
.querySelector('.todo-count')
const filters = element
.querySelector('.filters')
list.replaceWith(todosView(list, state)) // 상태(투두 배열과 필터)를 인자로 넘기고, 반환값으로 HTML 요소를 받아서 교체한다.
counter.replaceWith(counterView(counter, state)) // 상태(투두 배열)를 인자로 넘기고, 반환값으로 HTML 요소를 받아서 교체한다.
filters.replaceWith(filtersView(filters, state)) // 상태(필터)를 인자로 넘기고, 반환값으로 HTML 요소를 받아서 교체한다.
return element
}
2.3. /view/counter.js
// /view/counter.js
const getTodoCount = todos => {
const notCompleted = todos
.filter(todo => !todo.completed)
const { length } = notCompleted
if (length === 1) {
return '1 Item left'
}
return `${length} Items left`
}
export default (targetElement, { todos }) => {
const newCounter = targetElement.cloneNode(true)
newCounter.textContent = getTodoCount(todos)
// 새로운 카운터 HTML 요소를 반환한다.
return newCounter
}
2.4. /view/filters.js
// /view/filters.js
export default (targetElement, { currentFilter }) => {
const newCounter = targetElement.cloneNode(true)
Array
.from(newCounter.querySelectorAll('li a'))
.forEach(a => {
if (a.textContent === currentFilter) {
a.classList.add('selected') // 현재 필터와 같은 것에만 css 클래스를 추가한다.
} else {
a.classList.remove('selected') // 현재 필터와 다른 것에는 css 클래스를 제거한다.
}
})
// 새로운 필터 HTML 요소를 반환한다.
return newCounter
}
2.5. todos.js
// /view/todos.js : 할일을 표시하는 렌더링 함수
const getTodoElement = todo => {
const {
text,
completed
} = todo
return `
<li ${completed ? 'class="completed"' : ''}>
<div class="view">
<input
${completed ? 'checked' : ''}
class="toggle"
type="checkbox">
<label>${text}</label>
<button class="destroy"></button>
</div>
<input class="edit" value="${text}">
</li>`
}
export default (targetElement, { todos }) => {
const newTodoList = targetElement.cloneNode(true)
const todosElements = todos
.map(getTodoElement) // 상태로 넘어온 배열을 순회하며 각 투두 아이템 요소를 생성하고 이를 문자열로 변환하여 결합한다. <li>...</li> 여러 개가 한 줄로 만들어진 문자열이다.
.join('')
newTodoList.innerHTML = todosElements // 새로운 투두 아이템 HTML 요소를 반환한다.
return newTodoList
}
'Books > 프레임워크 없는 프론트엔드 개발' 카테고리의 다른 글
[프레임워크 없는 프론트엔드 개발] 1.1. 순수함수를 이용한 렌더링 구현 (0) | 2025.05.24 |
---|