本地存储

2019-01-106103 阅读8 评论

还有一个问题,现在只要我们一刷新浏览器,所有todo 都没了,因为我们的数据保存在内存中,页面刷新数据就会清除。用户肯定不希望为了保存全部 todo 而不得不一直把这个浏览器页面开着。我们可以使用浏览器的 LocalStorage 来实现数据的持续性存储。这样一来只要用户不删除浏览器缓存,我们的 todo 会一直在。当然浏览器清除缓存后数据也没有了。为了更加持久化存储,我们可以使用数据库,但这里我们只是用 LocalStorage

我们首先来定义一个对象,用于 LocalStorage 存储和获取 todo 的相关操作:

var STORAGE_KEY = 'vue2.x-todo-tutorial';
var todoStorage = {
    fetch: function () {
        var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
        todos.forEach(function (todo, index) {
            todo.id = index
        });
        todoStorage.uid = todos.length;
        return todos
    },
    save: function (todos) {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
    }
};

STORAGE_KEY 用来区分存储到 LocalStorage 的内容,因为 LocalStorage 中可能存储其它应用的数据,使用这个 key 用于区分。

todoStorage 是一个 JavaScript 的对象,它的属性是两个方法。save 方法非常简单,即把 todos 转为 JSON 格式,然后将序列化的数据存入对应 key 为 STORAGE_KEY 的本地存储中。有存就有取,fetch 方法则从对应 STORAGE_KEY 的本地存储将之前存入的 todo 数据取出并反序列化。特别注意我们这里还为 todoStorage 对象绑定了一个 uid 属性,它的作用是后续添加 todo 时,用于确定新添加 todo 的 id。

注意这里代码中的 localStorage 就代表了本地存储对象,在支持 HTLM5 的浏览器中会存在这个对象,直接引用即可。

因此,每当用户打开页面时,我们因为去 LocalStorage fetch 一下存储的数据:

data: function () {
    return {
        todos: todoStorage.fetch(),
        newTodoTitle: '',
        editedTodo: null, // 用户暂存编辑前的 todo 状态
        intention: 'all', // 默认为 all
    }
},

同时,当我们添加 todo 时,由于可能已经存在从本地取出的 todo 数据,新的 todo id 不能是从 0 开始了,而应该从已有 todoStorage.uid 开始:

addTodo: function () {
    this.todos.push(
        // 修改后的 todo 模型
        {id: todoStorage.uid++, title: this.newTodoTitle, completed: false}
    );
    this.newTodoTitle = '';
},

另外,一旦添加了新的 todo,我们应该及时将新的 todo 存到本地,防止用户不小心关闭页面而导致数据丢失,我们可以使用 Vue 的 watch 来监听用户添加 todo 的事件,即监视 this.todos 的变化,一旦改变,立即修改本地存储的 todos 的数据:

el: '#todo-app',
data: function () {
    ...
},
// 监测 todos 列表的变化,将变化存储到 local storage
watch: {
    todos: {
        handler: function (todos) {
            todoStorage.save(todos)
        },
        deep: true
    }
},

大功告成!还有一个问题,现在只要我们一刷新浏览器,所有todo 都没了,因为我们的数据保存在内存中,页面刷新数据就会清除。用户肯定不希望为了保存全部 todo 而不得不一直把这个浏览器页面开着。我们可以使用浏览器的 LocalStorage 来实现数据的持续性存储。这样一来只要用户不删除浏览器缓存,我们的 todo 会一直在。当然浏览器清除缓存后数据也没有了。为了更加持久化存储,我们可以使用数据库,但这里我们只是用 LocalStorage

我们首先来定义一个对象,用于 LocalStorage 存储和获取 todo 的相关操作:

var STORAGE_KEY = 'vue2.x-todo-tutorial';
var todoStorage = {
    fetch: function () {
        var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
        todos.forEach(function (todo, index) {
            todo.id = index
        });
        todoStorage.uid = todos.length;
        return todos
    },
    save: function (todos) {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
    }
};

STORAGE_KEY 用来区分存储到 LocalStorage 的内容,因为 LocalStorage 中可能存储其它应用的数据,使用这个 key 用于区分。

todoStorage 是一个 JavaScript 的对象,它的属性是两个方法。save 方法非常简单,即把 todos 转为 JSON 格式,然后将序列化的数据存入对应 key 为 STORAGE_KEY 的本地存储中。有存就有取,fetch 方法则从对应 STORAGE_KEY 的本地存储将之前存入的 todo 数据取出并反序列化。特别注意我们这里还为 todoStorage 对象绑定了一个 uid 属性,它的作用是后续添加 todo 时,用于确定新添加 todo 的 id。

注意这里代码中的 localStorage 就代表了本地存储对象,在支持 HTLM5 的浏览器中会存在这个对象,直接引用即可。

因此,每当用户打开页面时,我们因为去 LocalStorage fetch 一下存储的数据:

data: function () {
    return {
        todos: todoStorage.fetch(),
        newTodoTitle: '',
        editedTodo: null, // 用户暂存编辑前的 todo 状态
        intention: 'all', // 默认为 all
    }
},

同时,当我们添加 todo 时,由于可能已经存在从本地取出的 todo 数据,新的 todo id 不能是从 0 开始了,而应该从已有 todoStorage.uid 开始:

addTodo: function () {
    this.todos.push(
        // 修改后的 todo 模型
        {id: todoStorage.uid++, title: this.newTodoTitle, completed: false}
    );
    this.newTodoTitle = '';
},

另外,一旦添加了新的 todo,我们应该及时将新的 todo 存到本地,防止用户不小心关闭页面而导致数据丢失,我们可以使用 Vue 的 watch 来监听用户添加 todo 的事件,即监视 this.todos 的变化,一旦改变,立即修改本地存储的 todos 的数据:

el: '#todo-app',
data: function () {
    ...
},
// 监测 todos 列表的变化,将变化存储到 local storage
watch: {
    todos: {
        handler: function (todos) {
            todoStorage.save(todos)
        },
        deep: true
    }
},

大功告成!

-- EOF --

8 评论
登录后回复
user0
2024-03-26 15:24:40

复制过来的代码,首行注释少了星号,另外头像裂开也很难受,用git的账号重发下吧

根据教程尝试后,发现回收站数据并没有存储在本地。添加了以下代码供参考:
/依据上面todoStorage再添加一个类似的,处理回收站的相关操作/
var STORAGE_KEY_RECYCLE_BIN = 'vue2.x-todo-tutorial-recycle-bin';
var recycleBinStorage ={
fetch:function(){
var recycleBin = JSON.parse(localStorage.getItem(STORAGE_KEY_RECYCLE_BIN) || '[]');
recycleBin.forEach(function(todo,index){
todo.id = index
});
return recycleBin
},
save:function(recycleBin){
localStorage.setItem(STORAGE_KEY_RECYCLE_BIN,JSON.stringify(recycleBin))
}
}

data: function(){
return{
todos: todoStorage.fetch(),
recycleBin:recycleBinStorage.fetch(), //回收站,用于存放已经删除的todo
newTodoTitle:'',
checkEmpty:false,
removedTodo:null,
editedTodo:null,
intention:'all',
}
}

watch:{
todos:{
handler:function(todos){
todoStorage.save(todos)
},
deep:true
},
/添加回收站监听/
recycleBin:{
handler:function(recycleBin){
recycleBinStorage.save(recycleBin)
},
deep:true
}
},

回复
user0 user0
2024-03-26 15:26:38

星号还是被吞了,排版也很一言难尽,我的意思传达到了就好...(评论不能删除呢QAQ)

回复
追梦人物 user0
2024-03-26 15:28:50

评论不支持删除的,是否使用 markdown 格式提交的评论呢?代码块可以用 markdown 格式。

回复
2024-03-26 15:19:33

根据教程尝试后,发现回收站数据并没有存储在本地。添加了以下代码供参考:
/依据上面todoStorage再添加一个类似的,处理回收站的相关操作/
var STORAGE_KEY_RECYCLE_BIN = 'vue2.x-todo-tutorial-recycle-bin';
var recycleBinStorage ={
fetch:function(){
var recycleBin = JSON.parse(localStorage.getItem(STORAGE_KEY_RECYCLE_BIN) || '[]');
recycleBin.forEach(function(todo,index){
todo.id = index
});
return recycleBin
},
save:function(recycleBin){
localStorage.setItem(STORAGE_KEY_RECYCLE_BIN,JSON.stringify(recycleBin))
}
}

data: function(){
  return{
    todos: todoStorage.fetch(),
    recycleBin:recycleBinStorage.fetch(),    //回收站,用于存放已经删除的todo
    newTodoTitle:'',
    checkEmpty:false,
    removedTodo:null, 
    editedTodo:null, 
    intention:'all', 
  }
}

watch:{
  todos:{
    handler:function(todos){
      todoStorage.save(todos)
    },
    deep:true
  },
  /*添加回收站监听*/
  recycleBin:{
    handler:function(recycleBin){
      recycleBinStorage.save(recycleBin)
    },
    deep:true
  }
},
回复
杨灿就是杨火山
2019-10-23 11:14:37

强烈建议博主在一个这个实例的简单后端搭建的教程,这样就可以把这个应用开发闭环,帮助很多小白理解整个开发的流程,不知道每次写的东西都是功能不全的,拿不出手。最后感谢博主写了这么好的教程~

回复
追梦人物 杨灿就是杨火山
2019-10-23 16:01:53

谢谢肯定!这个是 vue 的教程,对 vue 来说这就是一个完整应用,后端交互又是另一块的内容了,我最近在做全栈教程,后续会陆续发出来。

回复
莫奈湖的水
2019-08-14 18:31:06

内容重复了

大功告成!还有一个问题,现在只要我们一刷新浏览器,所有todo 都没了,因为我们的数据保存在内存中,页面刷新数据就会清除。用户肯定不希望为了保存全部 todo 而不得不一直把这个浏览器页面开着。我们可以使用浏览器的 LocalStorage 来实现数据的持续性存储。这样一来只要用户不删除浏览器缓存,我们的 todo 会一直在。当然浏览器清除缓存后数据也没有了。为了更加持久化存储,我们可以使用数据库,但这里我们只是用 LocalStorage

回复
CyberFork 莫奈湖的水
2020-01-10 18:20:58

重要的事情说两遍

回复