frameworkless-render
by cnhhoang850
HTML
<html>
<body>
<section class="app">
<header class="header">
<h1>Notes</h1>
<input
type="text"
class="new_note"
placeholder="Input new note here"
autofocus=""
/>
</header>
<section class="main">
<input type="checkbox" class="show-all" id="show-all" />
<label for="show-all"> Show all notes </label>
<ul class="todo-list"></ul>
</section>
<footer class="footer">
<span class="todo-count"></span>
<ul class="filters">
<li><a href="#/">All</a></li>
<li><a href="#/active">Active</a></li>
<li><a href="#/completed">Completed</a></li>
</ul>
<button class="clear-all">Clear completed</button>
</footer>
</section>
</body>
</html>
JavaScript
const state = {
todos: [
{
done: false,
value: "nội dung 1",
},
{
done: true,
value: "nội dung 2",
},
],
filter: "All",
};
const root = document.querySelector(".app");
window.requestAnimationFrame(() => {
const virtualRoot = render(root, state);
root.replaceWith(virtualRoot);
});
const renderTodo = (todo) => {
const { done, value } = todo;
return `
<li ${done ? 'class="done"' : ""}>
<div class="view">
<input ${done ? "checked" : ""}
type="checkbox" class="toggle" />
<label>${value}</label>
</div>
<input type="text" class="edit" value="${value}" />
</li>
`;
};
const countTodo = (todos) => {
const notDone = todos.filter((todo) => !todo.done);
const numberOfTodos = notDone.length;
return `${numberOfTodos} Todos left`;
};
const render = (renderTarget, state) => {
const { todos, filter } = state;
// Phải xác định DOM node thủ công
const targetElement = renderTarget.cloneNode(true);
const todoListElement = targetElement.querySelector(".todo-list");
const counterElement = targetElement.querySelector(".todo-count");
const filterElement = targetElement.querySelector(".filters");
// Logic nằm ở cùng một nơi
todoListElement.innerHTML = todos.map(renderTodo).join("");
counterElement.textContent = countTodo(todos);
Array.from(filterElement.querySelectorAll("li a")).forEach((a) => {
if (a.textContent === filter) {
a.classList.add("selected");
} else {
a.classList.remove("selected");
}
});
return targetElement;
};