用 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)
})
},
整个项目就写完了
一个新新手,完成这个项目还是有点点成就感哈哈哈,也是第一次写博客,写得很烂,求得到指点。