不使用Cookie实现TodoList持久化及多设备同步技术咨询
解决TodoList持久化与多设备同步问题
为什么直接修改HTML文件不可行
浏览器中的JavaScript出于安全限制,没有权限直接修改本地的HTML文件。你用appendChild操作的只是内存中的DOM树,刷新页面后浏览器会重新加载原始HTML文件,所以临时添加的内容会消失。
方案1:单设备持久化(无需后端,用localStorage)
localStorage是浏览器提供的本地存储API,不属于Cookie,能将数据持久化存储在用户设备上,刷新页面后不会丢失。修改你的代码如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Practice </title> <link href="style.css" rel="stylesheet" type="text/css" /> </head> <body> <input id="todo-title" type="text" /> <input id="date-picker" type="date" /> <button onclick="addTodo();">Add Todo</button> <div id="todo-list"></div> <script> // 从localStorage读取已保存的todos,没有则用默认数组 let todos = JSON.parse(localStorage.getItem('todos')) || [{ title: 'Get groceries', dueDate: '2021-10-04' }, { title: 'Wash car', dueDate: '2021-02-03' }, { title: 'Make dinner', dueDate: '2021-03-04' }]; render(); function addTodo(){ const textbox = document.getElementById('todo-title'); const title = textbox.value.trim(); const datePicker = document.getElementById('date-picker'); const dueDate = datePicker.value; if (title && dueDate) { // 简单校验输入 todos.push({ title: title, dueDate: dueDate }); // 保存到localStorage localStorage.setItem('todos', JSON.stringify(todos)); render(); // 清空输入框 textbox.value = ''; datePicker.value = ''; } } function render(){ const todoList = document.getElementById('todo-list'); todoList.innerHTML = ''; todos.forEach(function(todo){ const element = document.createElement('div'); element.innerText = `${todo.title} is due by ${todo.dueDate}`; todoList.appendChild(element); }); } </script> <script src="script.js"></script> </body> </html>
关键修改点:
- 把
todos从const改成let,支持后续更新 - 初始化时从
localStorage读取数据,解析为JSON对象;无数据则用默认数组 - 每次添加Todo后,用
JSON.stringify把数组转成字符串,存入localStorage
方案2:多设备同步(需要后端服务)
localStorage仅能在单个设备存储数据,要实现多设备同步,必须借助后端服务存储和同步数据。这里推荐用Firebase实时数据库(无需自行搭建服务器),步骤如下:
- 注册Firebase账号,创建新项目,启用Realtime Database,测试阶段可设置公开规则(生产环境需配置权限):
{ "rules": { ".read": true, ".write": true } } - 为项目添加Web应用,获取Firebase配置代码
- 修改TodoList代码接入Firebase:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Practice </title> <link href="style.css" rel="stylesheet" type="text/css" /> <!-- 引入Firebase SDK --> <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-database.js"></script> </head> <body> <input id="todo-title" type="text" /> <input id="date-picker" type="date" /> <button onclick="addTodo();">Add Todo</button> <div id="todo-list"></div> <script> // 替换成你的Firebase配置 const firebaseConfig = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", databaseURL: "YOUR_DATABASE_URL", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_SENDER_ID", appId: "YOUR_APP_ID" }; // 初始化Firebase firebase.initializeApp(firebaseConfig); const db = firebase.database().ref('todos'); // 监听数据库变化,自动更新页面 db.on('value', (snapshot) => { const todos = snapshot.val() || []; render(todos); }); function addTodo(){ const textbox = document.getElementById('todo-title'); const title = textbox.value.trim(); const datePicker = document.getElementById('date-picker'); const dueDate = datePicker.value; if (title && dueDate) { // 向数据库添加新Todo db.push({ title: title, dueDate: dueDate }); // 清空输入框 textbox.value = ''; datePicker.value = ''; } } function render(todos){ const todoList = document.getElementById('todo-list'); todoList.innerHTML = ''; Object.values(todos).forEach(function(todo){ const element = document.createElement('div'); element.innerText = `${todo.title} is due by ${todo.dueDate}`; todoList.appendChild(element); }); } </script> <script src="script.js"></script> </body> </html>
说明:
- Firebase实时数据库会自动同步所有设备的数据,任何设备添加/修改Todo,其他设备都会实时更新
- 生产环境需配置Firebase身份验证规则,防止未授权访问
内容的提问来源于stack exchange,提问作者ThatGuyWhoNeedsHelp
相关产品推荐
相关产品推荐

