jirengu-inc / jrg-project-5

一个在线简历编辑器教程。
102 stars 13 forks source link

No Backend 2 #5

Open FrankFang opened 7 years ago

FrankFang commented 7 years ago
cp -r step-4 step-5
cd step-5
# 如果是 Windows 系统,再执行下面两行
rm -rf node_modules
npm i
# 结束 Windows 系统的命令
webpack --watch
# 然后新开一个窗口

数据关联

之前一个任务,虽然我们应该支持注册和登录了,但是用户的数据依然存在于 localStorage,这个任务我们将把数据存到用户名下,也就是让数据与用户关联(associate)起来。

这次任务与之前的任务有一个不同点,那就是我们尝试一些错误的方法。(尝试之后才发现是错的) 为什么要尝试错误的方法呢。 因为你工作中很难一下子就找到正确的方法呀。

保存 todo

之前的任务里,我们是在窗口关闭的时候将数据保存到 localStorage,这次我们想当然地,计划在窗口关闭的时候将数据保存到 LeanCloud。

第一次尝试

我们要用的 API 基本都在《数据存储开发指南 · JavaScript》里。

commit: 页面关闭或刷新时保存数据(看代码时请忽略 bundle.js)

请按照上述代码改写你的代码。

我们刷新页面之后,发现了一个严重的问题。

我们无法调试这段代码!

为什么呢?因为普通的请求如果发出去,我们是可以看见 Network 里面有一个请求的。 但是这次的代码是写在 window.onbeforeunload 里的,所以这个请求一发出,页面就刷新了,Network 也清空了。

怎么办?

这就是真实项目中遇到的问题。

这个时候有两个办法,

  1. 使用 debugger

    我们在 avTodos.save 这句话结束后,写上一句 debugger:

      avTodos.save().then(function (todo) {
        // 成功保存之后,执行其他逻辑.
        console.log('保存成功');
      }, function (error) {
        // 异常处理
        console.error('保存失败');
      });
      debugger // 👈
    

    然后刷新页面,然后再刷新页面。就发现断点设置成功了。 现在去 Network 看看有没有保存 todos 的请求。 居然还是没有……看了这个时候请求还没有发出。 那么我们到底要怎么看到这个请求呢?

  2. 使用 preserve log 勾选这个玩意,就能让页面刷新时不清空 Network。 我们删掉 debugger,刷新页面,然后再刷新页面,看看请求有没有发出。 为什么要刷新两次?第一次是让新代码载入页面,第二次是为了触发 beforeunload 事件。 从结果可以看到,AllTodos 保存请求失败了,被 canceled 了。 浏览器为什么会把我的请求取消掉呢? 老司机一想就猜到了:

    如果一个页面就要死了(刷新就表示不要当前页面了,当前页面可以死了),那么这个页面发出的请求其实就没有任何意义了。既然没有意义,浏览器为什么浪费时间去发这个页面里的请求呢?所以浏览器直接取消了这个请求。

    简单来说,那就是:beforeunload 事件里面的所有请求都发不出去,会被取消! 我还从来没有在哪一本书里看到过这个知识点。所以说「实践」是非常重要的。

至此,我们的第一次保存数据的尝试就宣告失败了,因为我们在 beforeunload 事件里不能存将数据存到 LeanCloud。

第二次尝试

一般新人第一次尝试失败就会沮丧了。但是真正的程序员,怎么可能被一次失败打倒。接下来我们尝试第二次。

注意,一旦你推导出 beforeunload 行不通,就不要再死磕它了。你必须推翻以前的思维,「重新思考」。

重新思考我们的目的是什么。

我们是不是希望把用户的数据保存在 LeanCloud?那么我们可不可以在用户对数据进行操作的时候马上就把数据存到 LeanCloud,也就是在每次用户新增、删除 todo 的时候,就发送一个请求

commit: addTodo 时 saveTodos,removeTodo 时也 saveTodos

刷新页面,

  1. 新增一个 todo,看到保存的请求
  2. 删除一个 todo,也看到保存的请求

就说明你成功了。

读取 todo

存完数据,就要读数据了。

这个时候我们想想这个功能要怎么做。怎么读数据。

每个 todo 都有一个 id,我可以通过 id 查询到对应的 todo,但是我们怎么知道当前用户有哪些 todo 呢?

好像……没法……知道……

我们目前没有办法知道当前用户有哪些 todo ……

恭喜你,你要返工了。我们保存 todo 的逻辑有问题:没有将用户和 todo 关联起来。

这种现象在实际工作中时有发生(尤其是新手),由于你在开始做项目的时候,没有考虑清楚,最后你发现你的代码根本无法完成需求!

这说明你的思考不够全面。

我怎么才能思考全面呢?

多踩坑。坑踩多了,经验就多了。今天的踩坑,是为了避免明天的踩坑~

重新设计保存逻辑

  1. todo 存在用户名下
  2. 只有 todo 所属的用户能读写这些 todo

由于你现在对「ACL(Access Control List)」没有概念,所以你只能听我告诉你,我们可以使用 LeanCloud 提供的 ACL 功能来实现上面两个功能。

翻看《数据存储开发指南 · JavaScript》,找到「角色」这一章节,你会看到一个链接:JavaScript 权限管理使用指南

参考文档,写出下面代码:

commit: 添加访问控制

重新读取 todo

这个时候就要看你读文档的能力了。

我们很容易在文档里找到一个 根据 id 获取数据的 API

但是很遗憾这不是我们想要的,因为我们根本没有 id 可用。

继续翻文档。

找啊找啊找,你发现有一个「例子」是不需要 id 也能获取数据的,那就是「批量操作」的例子

  var query = new AV.Query('Todo');
  query.find().then(function (todos) {
    todos.map(function(todo) {
      todo['status'] = 1;
    });
    return AV.Object.saveAll(todos);
  }).then(function(todos) {
    // 更新成功
  }, function (error) {
    // 异常处理
  });

现在还不确定行不行,那就「先试试」。

commit: 获取 User 的 AllTodos

刷新页面,看到控制台拿到数据了!

但是为什么是个数组?

一个用户的 AllTodos 应该只有一个,而不是多个。

原因是,我们存了多个 AllTodos。

我们在用户添加一个 todo 的时候,存了一个 AllTodos; 在用户添加第二个 todo 的时候,又存了一个「新的」AllTodos; 在用户删除一个 todo 的时候,我们又又存了一个「新的」AllTodos……

也就是说,我们的保存逻辑还是有问题。

正确的保存逻辑是:

  1. 如果发现当前用户没有存过 AllTodos,那么就存一个「新的」AllTodos
  2. 如果发现当前用户存过 AllTodos,那么就应该更新「之前的」AllTodos

我们怎么知道用户有没有存过 AllTodos 呢?根据 id,有 id 就表示这是数据库中存在的记录,没有 id 就表示是还没保存的记录。

又又又写一次存储逻辑

首先,我们去 LeanCloud 的控制面板把 AllTodos 表清空一下:

然后重写存储逻辑:

commit: 根据 id 选择 save(create) 或者 update

然后我们把一些 alert 去掉,免得惊吓到用户

commit: 去除多余的 alert,使用对用户无打扰的 console.log

测试!

接下来我们要测试「不同的用户是否得到不同的 todos」。

  1. 创建用户 123123
  2. 添加几个 todo,内容分别是 1、2、3
  3. 刷新页面,我应该看到 1、2、3 三条 todo
  4. 登出
  5. 创建用户 456456
  6. 登录后,我不应该看到 1、2、3 三条 todo

这样测试,如果成功,就能说明 456456 看不见 123123 创建的 todo 了。

BUG!

测试的时候,发现一个 bug:用户退出 123123 再重新登录 123123,居然看不到自己创建的 todo。

要解决这个 bug,只需要在用户登录后去读取一下 AllTodos 就行了:

commit: 登录后读取 todos

如果你发现不了这个 bug,就只能等你的用户发现这个 bug 了。

那个时候,场面就不太好看了……

致饥人谷学员

我们的 todo 应用就做到这里了,通过这个应用,我们已经大概知道了一个简单的动态页面改怎么做了,接下来我们就开始做在线简历应用了。

请完成上面的所有功能,并且自行测试10遍以上。

自行测试10遍以上! 自行测试10遍以上!

然后把预览链接放到下面。

注意 app id 和 app key

我今天发现有些同学并没有在 LeanCloud 上建立应用,而是直接用了我的 APP ID 和 APP KEY

let APP_ID = '8axnRtGoxCJhEzsvNPEAHnol-gzGzoHsz';
let APP_KEY = '0YH4XkYflb4CUPfA743TGj8G';

我请你们,换成自己的 APP ID 和 APP KEY!

否则哪一天我心情不好把我的应用删了,你的应用就没法读写数据了!

另外,春节快乐!

imgwho commented 7 years ago

效果预览 仓库地址

tcitds1 commented 7 years ago

预览

HuangHongRui commented 7 years ago

ShowPage ShowCode

andreaxiang commented 7 years ago

vue-todo demo @FrankFang

huoguozhang commented 7 years ago

预览 代码

zhuyutrisla commented 7 years ago

预览

clementlxd commented 7 years ago

预览 https://clementlxd.github.io/vue-task4/page.html 代码 https://github.com/clementlxd/vue-task4