上面代码能很好的运行,但是现在如果我需要修改一下验证规则,在title和desc都不为空的情况下,才使用OK按钮可用,如何做?你当然会说,很简单,直接加入一个&&条件不就行了,但是问题在于,现在我的模型比较小,属性比较少,如果我存在一个大量属性的对象,做类似的验证,这样来修改代码就是一个坑了,说到这里,其实已经可以想到,既然验证规则再变,那么可以考虑作为一个变化点封装起来,最直观的方式,是封装为一个方法,但是vue提供了更好的方式:computed,计算属性,这个计算属性应该是来自于knockout的概念,有兴趣的可以看一下knockout中计算属性,修改代码如下:
new Vue({ el: '#app', data: { todolist: [], todoItem: { id: '', title: '', desc: '' } }, computed:{ canSave:function(){ return !this.todoItem.title || !this.todoItem.desc; } }, ...省略其它 } })
可以看到computed属性是以方法的方式来定义的,这里是最简单方式,只读的方式,当然还可以通过get set方式进行读写控制,我们后期的代码中可能会见到,如果捉急,可以去查看官方文档。在computed使用的时候,和方法调用截然不同,而是和data属性中代理的模式一样,如果你使用过knockout,那么你对这种用法就见怪不怪了,html部分修改如下:
<div> <input type="button" value="OK" v-on:click="save()" :disabled='canSave'/> </div>
刷新页面,运行效果如图:
ok,编辑这部分内容就到这里吧,在没有后端接口的前提下,保存操作都是模拟的,接下来对我们的查询进行一下简单的介绍,这里查询,由于没有后端接口,咱们只做最简单的演示,对代码做如下处理:
1、增加查询输入框,keyword,添加查询按钮
2、点击查询操作,预期结果:根据输入的查询关键字,过滤列表
按照上面思路对我们代码进行修改:
<div> <div> keyword: <input type="text" v-model="keyword" /> <input type="button" @click="query()" value="search" /> </div> </div>
data中增加keyword属性,以实现对输入框的绑定,在methods中添加query方法:
//全局变量,用来缓存所有数据 var list = []; data: { todolist: [], todoItem: { id: '', title: '', desc: '' }, keyword:'' },
query: function () { //过滤title中不包含keyword的数据 //这里必须通过list全局变量过滤,而不能通过this.todolist,因为需要给this.todolist赋值,赋值后无法还原原来的列表。 this.todolist = list.filter(v => v.title.indexOf(this.keyword) !== -1); }
刷新页面运行效果如图:
代码部分注释中已经写的很清楚了,有疑问可提价comment。本章就到这里,文章有点水,在(三)中会加入添加服务端支持,并使用axios和服务端rest接口进行交互敬请期待,准备睡觉。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>demo1</title> <script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script> <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css"> </head> <body> <div> <div> <div> keyword: <input type="text" v-model="keyword" /> <input type="button" @click="query()" value="search" /> </div> </div> <div> <div> <table> <tr> <th></th> <th>title</th> <th>desc</th> <th></th> </tr> <tr v-for="(todoItem,index) in todolist"> <th>{{todoItem.id}}</th> <td>{{todoItem.title}}</td> <td>{{todoItem.desc}}</td> <td> <input type="button" value="remove" @click="remove(index)" /> <input type="button" value="edit" @click="edit(todoItem.id)" /> </td> </tr> </table> </div> <div> <div> <label for="title">title:</label> <input type="hidden" v-bind:value="todoItem.id" /> <input type="text" v-model="todoItem.title"> </div> <div> <label for="desc">desc</label> <input type="text" v-model="todoItem.desc"> </div> <div> <input type="button" value="OK" v-on:click="save()" :disabled='canSave' /> </div> </div> </div> </div> <script> var list=[]; var TodoItem = (function () { var id = 1; return function (title, desc) { this.title = title; this.desc = desc; this.id = id++; } })(); new Vue({ el: '#app', data: { todolist: [], todoItem: { id: '', title: '', desc: '' }, keyword: '' }, computed: { canSave: function () { return !this.todoItem.title || !this.todoItem.desc; } }, methods: { query: function () { //过滤title中不包含keyword的数据 //这里必须通过list全局变量过滤,而不能通过this.todolist,因为需要给this.todolist赋值,赋值后无法还原原来的列表。 this.todolist = list.filter(v => v.title.indexOf(this.keyword) !== -1); }, edit: function (id) { //找到id值等于所传参数的todoitem var obj = this.todolist.filter(v => v.id === id)[0]; //对数据进行绑定,则数据会响应到表单上 this.todoItem = { id: obj.id, title: obj.title, desc: obj.desc }; }, save: function () { if (this.todoItem.id) { //编辑保存 var obj = this.todolist.filter(v => v.id === this.todoItem.id)[0]; obj.title = this.todoItem.title; obj.desc = this.todoItem.desc; } else { //新增保存 this.todolist.push( new TodoItem( this.todoItem.title, this.todoItem.desc ) ); } //重置表单 this.todoItem = { title: '', desc: '' }; }, remove: function (index) { this.todolist.splice(index, 1); } } }) </script> </body> </html>