vue 和 leancloud 的 todolist

用 vue 和 leancloud 云储存做了一个简单的 todolist :对 todo 事项的添加修改删除
适合初学vue用来练练手
虽然用到了 leancloud 云储存,但也就是一个数据的存储和获取
leancloud 有一个数据存储入门教程 · JavaScrip,下载该demo源码对着文档看一下很容易就能够上手了

源码在这里

第一步安装vue-cli就不多说了,官网都有
下完后执行 npm i --save leancloud-storage 安装leancloud

一共有三个页面
首先我们打开页面会进入到登陆页面,如下
这里写图片描述

没有账号就点击注册,进入注册页面
这里写图片描述

登陆和注册后都是直接进入 todolist 页面
这里写图片描述
点击退出登陆则返回登陆页面

那么路由就出来了:
根路径: ‘/’ ————————————- 对应登陆界面 即 Login 这个组件
登陆路径: ‘/login’ —————————- 也对应登陆界面
注册路径: ‘/signup’ ————————–对应注册组件 Signup.vue
登陆注册后的路径即 todolist 页面: ‘/home’ ———-对应 Home.vue

这样文件目录就出来了,添加了三个vue组件,其他只需在已有文件里略做修改
这里写图片描述


开始写代码
router 文件夹下的 index.js 文件是配置路由的
把刚刚分析的三个路由配置进去

// router/index.js

// 首先在文件里导入那三个组件
import Vue from 'vue'
import Router from 'vue-router'
import Signup from '@/components/Signup'
import Login from '@/components/Login'
import Home from '@/components/Home'

然后配置

// router/index.js

 routes: [
    {
      path: '/',
      name: 'Login',
      component: Login
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
        path: '/signup',
        name: 'Signup',
        component: Signup
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    }
  ]

接着写组件
在 src 文件夹下新建 components 文件夹,新建 Login.vue 文件

首先是 html

// src/components/Login.vue

<template>
    // template标签里只能有一个最外层标签
    <div>
    // 这是右上角的导航链接
    <nav>
      <ul>
        <li>
          // router-link 相当于 a 标签
          // 详细可查 vue 官方文档
          // to 表示点击后会跳转到该页面,比如根页面为 '/',
          // 那这里就会跳转到 '/login' 页面
          // 至于页面显示什么怎么显示,后面会讲
          <router-link to="/login">登陆</router-link>
        </li>
        <li>
          <router-link to="/signUp">注册</router-link>
        </li>
      </ul>
    </nav>
    <form class="form login">
        <h2>登陆</h2>

        // 暂时只是普通的input和button
        <input type="username" class="form-control" placeholder="username" required autofocus>
        <input class="form-control" type="password" placeholder="Password" required>
        <button type="submit">登陆</button>
    </form>
</div>
</template>

上面两个 input 框的 value 值我们必须拿到,他们是用户名和密码,后面登陆的时候需要,所以给他们添加 vue 的 v-model 双向绑定:

// src/components/Login.vue

<input v-model="username" type="username" class="form-control" placeholder="username" required autofocus>
<input v-model="password" class="form-control" type="password" placeholder="Password" required>

点击登陆按钮的时候,我们要验证账号密码,同时跳转到 todolist 页面,所以给他添加点击事件

// src/components/Login.vue

// 点击“登陆”按钮时调用 login 方法
<button v-on:click="login" type="submit">登陆</button>

在这个文件下面接着写

// src/components/Login.vue

<script>
    // 将组件暴露出来以待随地引用
    export default {
        name: 'Login',
        data() {
            return {
                // 在这里绑定用户名和密码的 value 值
                username: '',
                password: ''
            }
        },
        methods: {
           // 这是点击登陆按钮的事件处理方法
            login: function() {
                // 这里要跳转路由
                // 然后用到 leancloud 验证登陆
            }
        }
    }
</script>
<style>
// css样式就不放了,自己觉得怎么好看怎么来
</style>

接着是Signup 组件

// src/components/Signup.vue

<template>
    <div>
        <nav>
            <ul>
                // 这里的“登陆”和“注册” Login 组件也有
                // 应该是可以把他们提取出来,写成一个父组件
                // 然后包含着两个子组件:登陆和注册
                // 我这里没有这样写,有兴趣的可以自己弄一下
                <li>
                    <router-link to="/login" class="active">登陆</router-link>
                </li>
                <li>
                    <router-link to="/signUp">注册</router-link>
                </li>
            </ul>
        </nav>
        <form class="form signup">
            <h2>注册新用户</h2>
            // 这里同样用 v-model 获取注册时用的用户名和密码以及邮箱
            <input v-model="signupUsername" type="username" id="inputUsername" class="form-control" placeholder="username" required autofocus>
            <input v-model="signupPassword" type="password" id="inputPassword" class="form-control" placeholder="Password" required>
            <input v-model="emailAddress" type="email" id="inputEmail" class="form-control" placeholder="Email address" required>
            // 点击“注册”按钮时调用 pushMessage 方法
            <button v-on:click="pushMessage" type="submit">注册</button>
        </form>
    </div>
</template>

<script>
    export default {
        name: 'Signup',
        data() {
            return {
                signupUsername: '',
                signupPassword: '',
                emailAddress: ''
            }
        },
        methods: {
            pushMessage: function() {
                // 获取注册时用户输入的账号密码邮箱
                var username = this.signupUsername;
                var password = this.signupPassword;
                var email = this.emailAddress;  
                // 待会传给 leancloud
            }
        }
    }
</script>

接着简单写个Home组件,随便放点数据先跑通就行

// src/components/Home.vue

<template>
    <div class="container">
        <nav>
            // 登陆进来后自然也可以退出 
            <router-link to="/">退出登陆</router-link>
        </nav>
        <p>这是 todolist 页面
    </div>
</template>

<script>
    export default {
        name: 'Home'
    }
</script>

现在整个项目应该是能跑通的
点击登陆、注册和退出登陆按钮都能跳转到对应的页面

接着先实现注册页面的逻辑
得先注册了账号才能登录嘛
这里要导入 leancloud
前面已经安装了 leancloud
这里直接在文件里引入就可以了

// src/components/Signup.vue


<script>
    // 在<script>标签下第一行导入
    import AV from 'leancloud-storage';
    // 因为之前没有用 npm ,都是 script 标签本地引入文件
    // 然后用了 vue-cli 之后,就懵了,不知道把引入标签放哪
    // 基础知识很差,理解能力也很差
    // 只知道用 import 把一个文件或者说模块导入另一个文件/模块
    // 但是还是没有 “ 一切皆模块 ” 的概念
    // 所以这里换成没用过的 leancloud ,而不是像往常常见的 vue 或 vue-router
    // 就不知道怎么导入了,折腾了很久才领悟到
    // 其实写程序想法真的应该简单直接点

    // 下面要用到 leancloud 
    // 可以看一下文章开头提到的 leancloud demo
    // 导入后要初始化 leancloud 
    // 把下面的 ID 和 KEY 换成你自己的
    var APP_ID = 'eAQGWOHouG1eTjsMkbAdlUD8-gzGzoHsz';
    var APP_KEY = 'R7yHLgfevCPbj8axml1CN49N';
    AV.init({
      appId: APP_ID,
      appKey: APP_KEY
    });

下面实现点击“注册”按钮的逻辑

// src/components/Signup.vue

// 点击注册调用的是 pushMessage 方法
// 在 methods 里添加该方法
    methods: {
        pushMessage: function() {
            // 获取到账号密码邮箱
            // 待会要推到 leancloud 上面
            var username = this.signupUsername;
            var password = this.signupPassword;
            var email = this.emailAddress;

            // leancloud 有自己的 User 对象
            // 实例化
            var user = new AV.User();
            // 用 leancloud 提供的方法让 leancloud 自己管理账号密码邮箱
            // 我们只要提供这些值就可以了
            user.setUsername(username);
            user.setPassword(password);
            user.setEmail(email);
            // leancloud 提供的注册方法
            user.signUp().then(function (loginedUser) {
                // 注册成功后的异步函数
                // 就是成功之后才会执行的
                // 没有成功就不会执行这里
                // 注册成功后我们要跳转到 Home 也就是 todolist 页面
                this.$router.push(path: '/home') // 不过这里这句语句会报错,一会说
            }, (function (error) {
                // 注册失败的提示
                // 其实这些代码那个 leancloud demo 都有现成的
                // 基本就是粘贴复制,感觉自己像个裁缝 
                alert(JSON.stringify(error));
            }));    
        }
    }

写完后可以试着注册一下,点击注册按钮
噔~报错了
上面说了那句代码会报错
因为我们用了 this !
用 this 的时候总要记得看一下 this 到底指向哪
this 是绑定在调用它的对象上面的
所以这里就是指向 user 对象,因为前面用的是 user.signUp()嘛
获取不到原来的 this 怎么办
那就先把原来的 this 存起来
添加一句:

// src/components/Signup.vue

    methods: {
            pushMessage: function() {
                // 存给 that
                var that = this;

然后改一下:

this.$router.push(path: '/home')

改成

that.$router.push(path: '/home')

现在再试一下注册
成功了有咩有
很简单有咩有

接着写登陆页面

// src/components/Signup.vue

<script>
    // 记得导入 leancloud
    import AV from 'leancloud-storage';

    export default {
        name: 'Login',
        data() {
            return {
                // 这里之前已经写了的
                username: '',
                password: ''
            }
        },
        methods: {
            // 点击登陆后的处理方法
            login: function() {
                // 还是先存 this 
                var that = this.$router

                var username = this.username;
                var password = this.password;
                // 同样用 leancloud 的登陆方法
                // 我们只需要负责传递用户名和密码给他就可以了
                AV.User.logIn(username, password).then(function (loginedUser) {
                    // 登陆后跳转到 Home 页面
                    that.push('/home')
                }, function (error) {
                  alert(JSON.stringify(error));
                });
            }
        }
    }
</script>

接下来是 todolist 主页
这个页面会稍微复杂一点
用户输入一条 todo 后
需要显示在页面上同时还要发给 leancloud 存起来
输入了的 todo 可以再次被修改
点击 delete 后页面上删除了 leancloud 上也需要被删除
然后用户退出重新登陆后他之前保存的 todo 也要展示在页面上

先实现静态效果:

// Home.vue

<template>
    <div class="container">
        <nav>
            <a v-on:click="logout">退出登陆</a>
        </nav>
        <form>
                // 用户在这个输入框输入 todo 事项
                // 点击回车后执行 input_todo 方法
            <input v-on:keyup.enter="input_todo" v-model="whatTodo" type="text">
        </form>
        <div>
            // 输入每一个 todo 事项后展示在这里
            // 用户重新登录后也会在这里看到已经输入的 todo 事项
            // todo 事项肯定有很多条,我们把他们装在一个数组里,用 v-for 输出
            // 用到的都是 vue 很基础的 就不解释了
            <ul class="todo-list">
                <li v-for="(item, index) in todos">
                    // 选择 input 来装 todo 事项本来是想给一个修改的功能
                    // 点击 label 里的 modify 将 input 的 disabled 属性去掉
                    // 但是没成功实现用 vue 去掉元素属性的方法
                    // 所以这里不用点击 modify 直接点击 input 框直接就可以修改了...
                    // 这个方法很挫了.. 有追求的可以自己改一下
                    <input v-bind:value="item" v-bind:id="index">
                    <label v-bind:for="index" >modify</label>
                    <span v-on:click="deleteTodo(index)">delete</span>
                </li>
            </ul>
        </div>
    </div>
</template>

input_todo 和 deleteTodo 方法:

<script>
    // 用来接收用户输入的所有 todo
    var todolists = [];

    export default {
        name: 'Home',
        data() {
            return {
                whatTodo: '',
                todos: todolists
            }
        },
        methods: {
            // 输入一条 todo 后
            input_todo: function() {
                // 获取当前用户输入的值
                var whatTodo = this.whatTodo;
                // 如果用户什么都没输入就回车了,就提示他:
                if (whatTodo == '') {
                    alert('请输入待办事项');
                    return 0;
                }
                // 在 div 添加 todo 
                // 将输入的todo添加到数组就可以了
                todolists.push(whatTodo);
                // 清空输入框,方便下次输入
                this.whatTodo = '';
            },
            deleteTodo: function(index) {
                // 每个input都有一个delete
                // 所以他们的index是一样的
                // 点击的delete index是几
                // 那么要删除的 todo index 也是几
                this.todos.splice(index, 1);
                })
            }
        }

如果没有 leancloud 那么到这里就可以结束这个项目了,
但是现在在添加 todo 的时候,不止页面要显示,也要添加到 leancloud 里面
删除的时候也要删除 leancloud 里的
重新登陆的时候也要从 leancloud 里面把当前用户的 todo 抓出来显示给他
这个项目就是这里稍微有点难度了
还是先写 input_todo 方法

// 先在前面导入 leancloud
<script>
    import AV from 'leancloud-storage';
    // 在leancloud创建 Todo 类
    var Todo = AV.Object.extend('Todo');

// 然后修改方法
            input_todo: function() {
                // 在页面添加 todo 事项
                var whatTodo = this.whatTodo;
                if (whatTodo == '') {
                    alert('请输入待办事项');
                    return 0;
                }
                // 暂时保存当前 todo 的 id
                // 因为 leancloud 对数据操作需要取得该条数据的 id
                var userID;

                this.todos.push(whatTodo);

                // 添加到 leancloud
                var todo = new Todo();
                todo.set('todoList', whatTodo);
                todo.set('owner', AV.User.current());
                todo.set('userID', currentUserId)
                todo.save().then(function (todo) {
                  // 成功保存之后返回当前对象,ID在这里能拿到,删除用
                  userID = todo.id;
                  // 取到 id 后存给这个对象,后面再要用某个todo的id就容易拿到了
                  // 不管后面有没有用,先存起来
                  todo.set('myId', userID);
                  todo.save();
                }, function (error) {
                  console.error('Failed to create new object, with error message: ' + error.message);
                });
                // 清空输入框,方便下次输入
                this.whatTodo = '';

            },
            //点击退出登陆回到登陆页面
            //这里没有直接用<router-link>的to属性
            //因为跳转之前得先把账号退出
            logout: function() {
                // 退出账号
                AV.User.logOut();
                this.$router.push('/')
            },

            deleteTodo: function(index) {
                // 在 leancloud 里删除todo需要拿到该todo的某属性来找到该todo
                // 这里我们拿该todo文字内容
                var todoContent = this.todos[index];

                this.todos.splice(index, 1);

                // leancloud 的查找操作
                var query = new AV.Query('Todo');
                // 根据文字内容找到那条todo
                query.equalTo('todoList', todoContent)
                query.find().then(function(results) {
                    // 成功找到之后取得他的id
                    var currentID = results[0]['id'];
                    // 然后删除
                    var deleteTodo = AV.Object.createWithoutData('Todo', currentID);
                    deleteTodo.destroy().then(function (success) {
                        // 删除成功
                    }, function (error) {
                        alert(error)
                    });
                })
            }

添加todo和删除todo都弄好了,
还有一个重新登陆页面时抓取当前用户已经有的todo放到页面上
直接写一个函数放在上面的话那时页面还没加载完成,
获取不到当前用户,自然也就拿不到这个用户的todo
所以得写在 mounted 周期里
我对vue生命周期还是没有弄太懂
如果不太确定是哪个周期的话可以每个周期都试一下

        mounted: function() {
            this.$nextTick(function () {
                // 初始化
                todolists = [];
                // 获取当前用户及用户ID
                var currentUser = AV.User.current();
                currentUserId = currentUser['id'];

                // 查找实例化
                var query = new AV.Query('Todo');
                // 在 Todo 类里查找 userID 为当前用户ID的对象
                query.equalTo('userID', currentUserId);

                // query.descending('createdAt');
                query.find().then(function (lists) {
                    // 遍历查找结果
                    lists.forEach(function(list) {
                        // 获取对象的 todolist 文本内容
                        let todolist = list.get('todoList')
                        // 将每条 todo 添加到 todolist数组
                        todolists.push(todolist);
                    })
                })
                // 将数组赋值给 data 里的 todos
                this.todos = todolists;
                console.log('this.todos' + this.todos)

             })

        },

整个项目就写完了
一个新新手,完成这个项目还是有点点成就感哈哈哈,也是第一次写博客,写得很烂,求得到指点。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值