Blog fellyph cintra - localstorage banner

localStorage: Armazenando dados com JavaScript

Esse post é um dos posts mais visualizados do blog, foi criado em 2013, mas darei uma atualizada no que aconteceu de lá para cá. Armazenamento local com localStorage é umas dos recursos mais úteis do HTML5, podemos utilizar para uma infinidade de ações, agora com Progressive Web Apps esse recurso voltou a ficar evidência.

LocalStorage

Ela permite armazenar strings com chave e valor é considerado cookies é uma forma mais segura de armazenamento, mas ela não tem acesso por Service Worker. Mas é um recurso nativo no browser de implementação simples que não necessita de plugin ou biblioteca externa.

Para aplicações mais complexas temos a opção de utilizar o IndexedDB. Mas um dos pontos fortes do localStorage é o suporte comparado a outras APIs, ele é suportado por 93% dos navegadores:

tipos de armazenamento
tipos de armazenamento

LocalStorage é um dos recursos do DOM Storage com ele podemos armazenar dados apenas em formato de texto, mas claro podemos contornar essa limitação. Vamos primeiro exemplo básico de armazenamento.

localStorage.setItem("key_da_propriedade","Valor armazenado");Code language: JavaScript (javascript)

No código acima adicionamos uma variável com nome “key_da_propriedade” que irá armazenar “Valor armazenado”. Quando esse código for armazenado pelo browser o usuário pode sair da aplicação, continuar navegando em outras aplicações, quando ele voltar para nossa aplicação o dado continuará lá. Esse recurso será útil caso utilizarmos uma versão offline da nossa aplicação com PWA.

Como visualizar os dados do LocalStorage?

Para visualizar a informação que foi salva, no Google Chrome, para abrir o DevTools vamos em menu > View > developer > developer tools, tecla de atalho ctrl+shift+i ou simples, clique o com botão direito do mouse e selecionamos a opção inspect, com DevTools aberto vamos à aba Application, na sessão storage vemos a opções disponíveis. Quando clicamos em Local Storage vemos as aplicações separadas por URL, no meu teste, estou rodando em localhost, clicando no URL da nossa aplicação, vemos os dados armazenados:

Visualizando dados do localstorage
Visualizando dados do localstorage

Agora que sabemos que a informação foi salva vamos resgatar esse valor com o seguinte código:

const minha_propriedade = localStorage.getItem('key_da_propriedade');
alert("Valor:" + minha_propriedade);
Code language: JavaScript (javascript)

No código acima passamos a função getItem e como parâmetro passamos a key da informação que queremos resgatar, na linha seguinte apenas executamos um alerta para exibir a informação.

Caso queria remover essa informação do localStorage utilizamos o seguinte código:

localStorage.removeItem('key_da_propriedade');
Code language: JavaScript (javascript)

Aplicando localStorage, na prática

Agora vamos para um exemplo prático aplicando essas três funções que virmos acima, no caso: salvar, ler e excluir os dados no localStorage.

<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>LocalStorage tutorial</title>
	<script>
		window.addEventListener('load',() => {
			if(localStorage.getItem('name')){
				sayMyName()
			}else{
				whatsYourName()
			}
		});
		
		function whatsYourName(){
            document.body.innerHTML = '';
            // criando um input para cadastrar o nome;
            const inputName = document.createElement('input');
            inputName.type = 'text';
            inputName.placeholder = 'Digite seu nome';
            inputName.id = 'nome';
            document.body.appendChild(inputName);

            // criando saveButton
            const saveButton = document.createElement('button');
            saveButton.innerHTML = 'Salvar';
            document.body.appendChild(saveButton);
            
            // adicionando listener para salvar a informação
			saveButton.addEventListener('click', saveName);
		}
		
		
		function sayMyName(){
            document.body.innerHTML = '';
            // criando mensagem
            const welcomeMessage = document.createElement('h1');
            welcomeMessage.innerText = 'Olá' + localStorage.getItem("name");
            
            // criando removeButton
            const removeButton = document.createElement('button');
            removeButton.innerHTML = 'Excluir';
            document.body.appendChild(removeButton);
            
            // adicionando o listener para remover informação
			removeButton.addEventListener('click',removeName);
		}
		
		function removeName(){
			if(localStorage.getItem('name')){
				localStorage.removeItem('name');
				whatsYourName()
			}	
		}
		
		function saveName(){
			var nome = document.getElementById('nome').value;
			localStorage.setItem('name', nome) 
			sayMyName();
		}
	</script>
</head>
<body>
</body>
</html>
Code language: HTML, XML (xml)

O Exemplo acima resumindo rapidamente ele verifica se tem o dado com a key “name” no localStorage, caso tenha, exibe o nome. Caso contrário adiciona um input para cadastrar o dado. Quando o nome é exibido também adicionamos um button para chamar a função de excluir os dados. Nos Exemplos anteriores apenas adicionamos e removemos algumas strings, para trabalhar com objetos no localStorage precisamos usar a Classe JSON, com ela é possível fazer a ponte entre textos e objetos.

		window.addEventListener('load',() => {
			if(localStorage.getItem('user')){
				const texto = localStorage.getItem("user");
				const objeto = JSON.parse(texto);
				document.body.innerHTML = `nome: <strong>${objeto.name}</strong> email: <strong>${objeto.email}<strong>`;
			}else{
				const user = { 
					name: 'Fellyph',
					email: 'fellyph@fellyph.com.br'
                }
				const userString = JSON.stringify(user);

				localStorage.setItem('user',userString);
				document.body.innerHTML = 'dados salvos';	
			}
		});
Code language: JavaScript (javascript)

No código acima focamos apenas no JavaScript, verificamos se existe um dado com uma key “user”, caso o exista resgata a informação na variável “texto” em seguida convertemos o texto em objeto utilizando a método parse da classe JSON. Assim temos um objeto como retorno e adicionamos o conteúdo no body do nosso arquivo, no código acima utilizamos string literals para concatenar o nosso conteúdo.

Caso o usuário não tenha nenhuma informação salva com a key “user”, o código irá criar um objeto e em seguida converter em texto, assim temos a possibilidade de salvar os dados no nosso localStorage. Esse exemplo não é muito funcional, apenas exemplifica como é salvar um objeto no nosso localStorage.

Agora vamos partir para um exemplo mais funcional, vamos montar uma todo-list utilizando localStorage, desta vez vamos separar o código no arquivo todo-list.html, js/app.js e css/style.css. O exemplo a seguir utiliza ES2015 caso queira dar uma olhada no exemplo em EcmaScript 5 só dá uma olhada no gitHub no seguinte link: https://github.com/fellyph/Tutorial-bbUI/tree/master/localstorage

Nosso HTML:

<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Todo List</title>
	<link rel="stylesheet" href="css/style.css">
	<script src="js/app.js"></script>
</head>
<body>
	<h1>todo-list</h1>
	<div id="tasks-output"></div>
	<form id="form-task">
		<input type="text" name="descricao" placeholder="adicione uma nova task" required>
		<input type="submit" value="Salvar">
	</form>
</body>
</html>
Code language: HTML, XML (xml)

Nosso CSS:

#tasks-output li {
	cursor: pointer;
}

#form-task {
	border-top: 1px solid #ddd;
	padding: 10px 0;
	margin: 10px 0;
}

#tasks-output li[data-done="true"] {
	text-decoration: line-through;
}
Code language: CSS (css)

Detalhe para o último seletor que trata quando o item da lista possui o atributo data-done igual a true, ele vai adicionar uma linha sobre o texto.

let todoList;
let todoOutput;

function formatDate(date) {
  // formata a data para o formato DD/MM/YYYY
  const time = new Date(date);
  return `${time.getDate()}/${time.getMonth()}/${time.getFullYear()}`;
}

function showList() {
  // mostra a lista de todo
  if (todoList.length > 0) {
    const htmlTemp = `<ul>
      ${todoList.map(todoItem => `<li data-id="${todoItem.id}" data-done="${todoItem.done}">${todoItem.descricao} - ${formatDate(todoItem.date)}</li>` )}
      </ul><button>Limpar tarefas realizadas</button>`;
    todoOutput.innerHTML = htmlTemp;
  } else {
    todoOutput.innerHTML = 'Nenhuma tarefa cadastrada';
  }
}

function saveList() {
  // converte os dados em string e salva no local storage
  localStorage.setItem('tasks', JSON.stringify(todoList));
}

function clearList() {
  // varre a lista a procura de tarefas realizadas
  for (let i = 0; i < todoList.length; i += 1) {
    if (todoList[i].done === 'true') {
      // remove 1 elemento na posição i;
      todoList.splice(i, 1);
      // voltando o indice no array para validar novamente a lista
      i = 0;
    } else {
      todoList[i].id = i;
    }
  }
  showList();
  saveList();
}

function clickList(e) {
  // somente fazer algo quando clicar em um item li
  if (e.target.localName === 'li') {
    e.target.dataset.done = !e.target.dataset.done === 'true';
    todoList[e.target.dataset.id].done = e.target.dataset.done;
    saveList();
  } else if (e.target.localName === 'button') {
    clearList();
  }
}


function onSubmit(e) {
  const task = {};

  // pego o valor cadastrado no primeiro input do meu form
  task.descricao = e.target[0].value;
  task.date = new Date();
  task.id = todoList.length;
  task.done = 'false';

  // adicionando a task na lista
  todoList.push(task);
  saveList();
  showList();
  // utiliza o preventDefault para evitar do form realizar o reload da página
  e.preventDefault();
}


window.addEventListener('load', () => {
  // guarda em uma variável o elemento tasks-output
  todoOutput = document.getElementById('tasks-output');
  if (localStorage.getItem('tasks')) {
    todoList = JSON.parse(localStorage.getItem('tasks'));
    showList();
  } else {
    todoList = [];
  }

  if (todoList.length === 0) {
    todoOutput.innerHTML = 'Nenhuma tarefa cadastrada';
  }
  // adiciona o listener para o evento submit, utilizei form para usar o required do input HTML
  document.getElementById('form-task').addEventListener('submit', onSubmit);
  todoOutput.addEventListener('click', clickList);
});

Code language: JavaScript (javascript)

Tentei comentar os pontos-chave do código, na listagem utilizo um map para montar a nossa lista. Caso não esteja familiarizado só conferir a versão anterior desse código no GIT ou conferir os posts relacionados a ecmaScript 2015, mas o código acima o usuário pode cadastrar as tasks que serão vinculadas uma data, quando o usuário clica no item da lista a propriedade “data-done” muda entre true ou false. Caso o utilizador queira limpar as suas listas de task clica no botão “Limpar tarefas…” o código irá varrer da lista os itens com valor da propriedade data-done igual a true e retirar da lista.

Além do LocalStorage temos o SessionStorage, a diferença entre os dois é que o sessionStorage como o nome sugere, ele guarda as informações apenas na seção, ou seja, quando a aplicação é finalizada a informação é removida.

Quando utilizar localStorage?

LocalStorage é ideal para armazenar pequenas strings, nos nossos exemplos fomos em algo mais complexo para ter uma ideal do potencial deste recurso. Mas os casos mais comuns para o uso da API são:

  • Configurações do usuário: preferências de idioma, tema da interface, etc.
  • Dados persistentes: informações que precisam ser mantidas mesmo após o fechamento do navegador, como itens favoritos, carrinho de compras, etc.
  • Cache de dados: armazenar dados localmente para melhorar o desempenho, como resultados de API ou imagens.

Quais são os problemas de utilizar localStorage?

Quando trabalhamos com local storage devemos lembrar que os dados que salvamos no

  • Segurança: os dados armazenados no localStorage não são criptografados, o que significa que podem ser acessados por qualquer pessoa com acesso ao navegador.
  • Tamanho: o localStorage tem um limite de armazenamento de 5MB por domínio.
  • Compatibilidade: o localStorage não é suportado por todos os navegadores antigos.
  • Sincronização: os dados armazenados no localStorage não são sincronizados entre diferentes navegadores ou dispositivos.

IndexDB e LocalStorage: Qual é o melhor?

IndexDB:

  • Banco de dados NoSQL com maior capacidade de armazenamento e estruturação de dados.
  • Permite transações complexas e acesso assíncrono.
  • Suporta chaves compostas e índices para otimizar consultas.

LocalStorage:

  • Mais simples de usar e implementar.
  • Ideal para armazenar pequenas quantidades de dados simples.
  • Acesso mais rápido do que o IndexDB.

Melhor escolha:

  • IndexDB: Se você precisa armazenar grandes quantidades de dados estruturados ou precisa de transações complexas.
  • LocalStorage: Se você precisa armazenar pequenas quantidades de dados simples e precisa de um acesso rápido.

Outras considerações:

  • Segurança: O IndexDB oferece criptografia de dados, enquanto o localStorage não.
  • Compatibilidade: O IndexDB não é suportado por todos os navegadores antigos, enquanto o localStorage tem uma compatibilidade maior.

Em resumo, o localStorage é uma boa opção para armazenar pequenas quantidades de dados simples que precisam ser persistentes. Se você precisa de mais flexibilidade, segurança ou capacidade de armazenamento, o IndexDB é a melhor escolha.

Fechamos por aqui e até o próximo tutorial, para saber mais como acessar recursos do device confira a página da categoria PWA.


Publicado

em

, ,

por

Comentários

4 respostas para “localStorage: Armazenando dados com JavaScript”

  1. Avatar de Wesley
    Wesley

    porque que no começo das funções whatsYourName é sayMyName e colocado document.body.innerHTML = ‘ ‘? é muinto obrigado já me deu uma ajuda

    1. Avatar de Fellyph Cintra
      Fellyph Cintra

      Olá Wesley, boa pergunta. No caso essa atribuição é para simplesmente para limpar o conteúdo anterior salvo no body. Mas isso só por conta da função appendChild, ele não substitui o conteúdo anterior só adicionar conteúdo ao final do texto.

  2. Avatar de izaias de oliveira elias
    izaias de oliveira elias

    Bom dia.
    Eu estou criando um site de notas com alerta de tempo de tarefa e estou tendouitos problemas com pouco conhecimento, vc poderia me ajudar?.
    Ótimo artigo.

  3. Avatar de Lucas
    Lucas

    Salvou aqui mano, ajudou muito – Agradeço d+

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *