Ad/iklan :







Search.Pencarian Menu

Add text send email to rh3252705.adda@blogger.com or Click this (Text porn Will delete) | Tambah teks kirim email ke rh3252705.adda@blogger.com atau Klik ini (Teks porno akan dihapus)
Total post.pos : 13631+

[Go Make Things] Building complex apps with vanilla JavaScript (a series)

When I promote vanilla JS, one of the places I often get pushback is around building complex UIs.

Sure, vanilla JS is great for simple scripts and web apps. But as soon as things get complex, you need React.

Over the next few days, I want to take explore the edges where vanilla JS starts to fall apart, and highlight the vibrant middle ground between "100% hand-rolled vanilla JS" and "just use React."

Let's dig in!

A todo app

For this series, we're going to look at the most cliche example of all examples: a todo app.

It's a cliche example in large part because it seems deceiving simple, and can be built with varying levels of complexity. It's a great teaching project!

For our purposes, let's imagine we have a form element and an unordered list (ul).

<form id="add-todo">  	<label>What do you want to do?</label>  	<input type="text" id="todo">  	<button>Add Todo</button>  </form>    <ul id="app"></ul>

Whenever the user submits a todo using the #add-todo form, we want to create a new list item (li) and add it to the #app list.

Using traditional DOM manipulation

The old-school vanilla JS version of this app takes 28 lines of code, including comments and white space.

First, let's get the app and form elements using the document.querySelector() method, and assign them to variables.

// DOM elements  let app = document.querySelector('#app');  let form = document.querySelector('#add-todo');  

Next, lets listen for submit events on our form, and addTodo items whenever that happens.

// Add todos when form is submited  form.addEventListener('submit', addTodo);  

Inside the addTodo() function, we'll first use the event.preventDefault() method to stop the form from reloading the page.

Then, we'll make sure the #todo field inside the form has a value. If not, we'll end our function early.

Because the field has an ID, we can access it directly as a property of the form element.

/**   * Add todo to the list   * @param {Event} event The event object   */  function addTodo (event) {    	// Stop the form from reloading the page  	event.preventDefault();    	// If there's no field value, ignore the submission  	if (!form.todo.value) return;    }  

Otherwise, we'll use the document.createElement() method to create a new list item (li), and set the form.todo.value as its textContent.

Then, we can use the Element.append() method to inject it into the app list. We'll also clear the form field.

/**   * Add todo to the list   * @param {Event} event The event object   */  function addTodo (event) {    	// Stop the form from reloading the page  	event.preventDefault();    	// If there's no field value, ignore the submission  	if (!form.todo.value) return;    	// Otherwise, add a todo  	let li = document.createElement('li');  	li.textContent = form.todo.value;  	app.append(li);    	// Clear the form field  	form.todo.value = '';    }  

Now, we've got a basic todo app stood up with just a few lines of code. Try it yourself on CodePen.

Adding features (and a bit of complexity)

Now we've got an app where we can add todo items. But, every time the user reloads the page, they get wiped out.

We can fix that pretty easily with localStorage.

Whenever we add a todo item, we'll use the localStorage.setItem() method to save the innerHTML of the app element.

// Clear the form field  form.todo.value = '';    // Save list  localStorage.setItem('todos', app.innerHTML);  

And whenever the page is opened, we'll look for saved todos and load them into the UI.

// Add todos when form is submited  form.addEventListener('submit', addTodo);    // Load saved todos  app.innerHTML = localStorage.getItem('todos') || '';  

But if you're going to do this, you also need to provide a way for users to remove todo items.

After creating our list item, let's create a button with the [data-delete] attribute on it, and append() it inside the li element.

// Otherwise, create a todo  let li = document.createElement('li');  li.textContent = form.todo.value;    // Add a remove button  let btn = document.createElement('button');  btn.textContent = 'Delete';  btn.setAttribute('data-delete', '');  li.append(btn);    // Append to the UI  app.append(li);  

Since we're dynamically adding buttons, we can listen for clicks on our button using event delegation. We'll listen for all clicks in the document, and run the removeTodo() function in response.

// Remove todos when delete button is clicked  document.addEventListener('click', removeTodo);  

Inside the removeTodo() function, we'll ignore any clicks that weren't triggered by a [data-delete] button.

We can check that by running the Element.matches() method on the event.target, the element that triggered the event.

/**   * Remove todo items   * @param  {Event} event The event object   */  function removeTodo (event) {    	// Only run on [data-delete] items  	if (!event.target.matches('[data-delete]')) return;    }  

If it was a delete button, we'll use the Element.closest() method to find the parent list item (li), and the Element.remove() method to remove it from the DOM.

Then, we'll run the localStorage.setItem() method again to update our saved list.

/**   * Remove todo items   * @param  {Event} event The event object   */  function removeTodo (event) {    	// Only run on [data-delete] items  	if (!event.target.matches('[data-delete]')) return;    	// Otherwise, remove the todo  	let li = event.target.closest('li');  	if (!li) return;  	li.remove();    	// Save the list  	localStorage.setItem('todos', app.innerHTML);    }  

Here's another demo.

Things get unmanageably complex pretty fast

At this point, we're still in the world of "not too bad" with traditional DOM manipulation (in my opinion).

But that changes pretty fast!

For example, we probably want to display a message when there are no todo items yet. With traditional DOM manipulation, the easiest way to do that is to add an element in the DOM that we selectively show and hide.

<p id="no-todos" hidden><em>You don't have any todos yet.</em></p>

First, we'll create another variable for the noTodos element.

// DOM elements  let app = document.querySelector('#app');  let form = document.querySelector('#add-todo');  let noTodos = document.querySelector('#no-todos');  

Then, we'll create a loadSavedTodos() function to help us out.

If there's saved todos, we'll show them. Otherwise, we'll use the Element.removeAttribute() method to remove the [hidden] attribute and show our message.

/**   * Load saved todo items into the UI   */  function loadSavedTodos () {  	let saved = localStorage.getItem('todos');  	if (saved) {  		app.innerHTML = saved;  	} else {  		noTodos.removeAttribute('hidden');  	}  }  

Then, we'll run this method instead of directly loading saved todos.

// Load saved todos  loadSavedTodos();  

Whenever we append a list item to the app, we'll add the [hidden] attribute attribute back to hide the message if it's current visible.

// Append to the UI  app.append(li);    // Hide the no-todos message  noTodos.setAttribute('hidden', '');  

And when we remove a todo item, if there are no list items in our app, we'll remove the attribute again to show the message.

// Save the list  localStorage.setItem('todos', app.innerHTML);    // If there are no todos, show the no-todos message  if (!app.innerHTML.trim().length) {  	noTodos.removeAttribute('hidden');  }  

Here's another demo.

We've reached the breaking point

We're now up to 85 lines of code (with comments and whitespace), and there's still a ton of features you'd probably want to add to an app like this.

For example, you probably want a button to clear all todos. But you only want to show it if there are todo items to remove.

And you might also want to provide users with a way to edit existing todo items or mark them as complete.

At this point, the cost of adding new features has gotten quite high. It requires keeping track of the current state of the UI, and selectively adding, removing, and updating various pieces.

And this is where a completely different approach to building the app makes sense.

Tomorrow, we're going to dive into what that is.

The Vanilla JS Academy is a project-based online JavaScript workshop for beginners. Click here to learn more.

Cheers,
Chris

Want to share this with others or read it later? View it in a browser.

Share :

Facebook Twitter Google+
0 Komentar untuk "[Go Make Things] Building complex apps with vanilla JavaScript (a series)"

Back To Top