前端主流框架vue学习笔记第二篇


Posted in Javascript onJuly 26, 2017

接上篇,在本篇中,我们将要实现如下,功能,编辑和查询,我们当前的todolist程序,和线上其它的demo程序不同,我们会对其进行增删改查的基本操作,之后进行进一步的完善,按照常规的系统使用经验,一般我们新增和编辑都是在模态框中处理,这里我们不会去构建复杂的模态框,只用一个简单的div层来代替,后期接下来的文章中我们会重复造轮子,构建我们自己的轻量级框架(UI库)。

首先,我们对我们的页面结构进行一下简单的调整,加入bootstrap只是为了让页面不那么赤裸裸,对其它不会有任何影响

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" 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" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">

</head>

<body class="container">
 <div id="app" class='row'>
 <div class="col-md-6">
  <table class="table table-bordered">
  <tr>
   <th>title</th>
   <th>desc</th>
   <th></th>
  </tr>
  <tr v-for="(todoItem,index) in todolist">
   <td>{{todoItem.title}}</td>
   <td>{{todoItem.desc}}</td>
   <td><input type="button" value="remove" @click="remove(index)" class="btn btn-danger" /></td>
  </tr>
  </table>
 </div>
 <div class="col-md-6">

  <div class="form-inline">
  <label for="title" class="control-label col-md-4">title:</label>
  <input type="text" v-model="title" class="form-control col-md-8">
  </div>
  <div class="form-inline">
  <label for="desc" class="control-label col-md-4">desc</label>
  <input type="text" v-model="desc" class="form-control col-md-8">
  </div>
  <div class="form-inline">
  <input type="button" value="OK" v-on:click="addItem()" class="btn btn-primary offset-md-10" />

  </div>

 </div>


 </div>
 <script>
 var TodoItem = function (title, desc) {
  this.title = title;
  this.desc = desc;
 }
 new Vue({
  el: '#app',
  data: {
  todolist: [],
  title: '',
  desc: ''
  },
  methods: {
  addItem: function () {
   this.todolist.push(new TodoItem(this.title, this.desc))

   this.title = this.desc = '';

  },
  remove: function (index) {
   this.todolist.splice(index, 1);
  }

  }
 })
 </script>
</body>

</html>

js没有任何变化,只是引入了bootstrap4之后,对html结构进行了微调整,由于我们需要增加编辑操作,我们把增加编辑操作归纳为以下几个步骤:

1、增加编辑按钮;

2、点击编辑按钮绑定所对应todoitem到表单进行编辑

3、点击表单中OK按钮,对编辑结果进行应用。

注意:这里需要区分,在点击OK按钮时,进行的是新增操作还是编辑操作,我们对我们数据结构加入自增ID来标示,如果编辑项目有ID,则为保存编辑操作,如果不存在ID则为新增保存操作,对我们的数据结构进行以下微调,由于新增了ID项目,那么在data属性中也要增加ID属性,这样每次新增属性都要直接修改data属性,这就是变化点,下面我们对变化点进行简单封装,修改代码如下:

data: {
  todolist: [],
  todoItem:{
   id:'',
   title:'',
   desc:''
  }
  },

另外我们需要实现自增ID,这里采用最直接的方式,全局ID,使其自增即可,对TodoItem进行简单的闭包处理:

var TodoItem = (function () {
  var id = 1;
  return function (title, desc) {
  this.title = title;
  this.desc = desc;

  this.id = id++;
  }
 })();

为了适应新数据结构的变化,则其它修改部分整体贴出来,变化部分见黄色:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" 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" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">

</head>

<body class="container">
 <div id="app" class='row'>
 <div class="col-md-6">
  <table class="table table-bordered">
  <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)" class="btn btn-danger" /></td>
  </tr>
  </table>
 </div>
 <div class="col-md-6">

  <div class="form-inline">
  <label for="title" class="control-label col-md-4">title:</label>
  <input type="hidden" v-bind:value="todoItem.id" />
  <input type="text" v-model="todoItem.title" class="form-control col-md-8">
  </div>
  <div class="form-inline">
  <label for="desc" class="control-label col-md-4">desc</label>
  <input type="text" v-model="todoItem.desc" class="form-control col-md-8">
  </div>
  <div class="form-inline">
  <input type="button" value="OK" v-on:click="addItem()" class="btn btn-primary offset-md-10" />

  </div>

 </div>


 </div>
 <script>
 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: ''
  }
  },
  methods: {
  addItem: function () {
   // this.todolist.push(new TodoItem(this.title, this.desc))
   this.todolist.push(
   new TodoItem(
    this.todoItem.title,
    this.todoItem.desc
   )
   );

   this.todoItem={};

  },
  remove: function (index) {
   this.todolist.splice(index, 1);
  }

  }
 })
 </script>
</body>

</html>

刷新页面,测试效果如下:

前端主流框架vue学习笔记第二篇

自增ID已经完成,那么添加编辑时绑定,按照上面的步骤,先添加编辑按钮,在删除按钮后添加编辑按钮,并在methods对象中增加对应的回调函数,对edit操作进行响应,函数中主要实现对todoItem对象进行绑定操作,具体代码修改如下:

<table class="table table-bordered">
  <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)" class="btn btn-danger" />
   <input type="button" value="edit" @click="edit(todoItem.id)" class="btn btn-info" />
   </td>
  </tr>
  </table>
methods: {
    edit: function (id) {
     //找到id值等于所传参数的todoitem
     var obj = this.todolist.filter(v => v.id === id)[0];
     //对数据进行绑定,则数据会响应到表单上
     this.todoItem = obj;
    },
   ...省略其它
}

这样有没有问题呢?我们运行看一下效果:

前端主流框架vue学习笔记第二篇

从运行结果上看,我们点击edit操作,的确完成了绑定,但是在我们修改编辑,还没有点击OK按钮的情况下,表单中的变化已经提现到了列表中,这就不符合正常逻辑了,为什么会有这样的情况呢,原因就在于this.todoItem=obj;这句代码就是所谓的引用赋值,所以todoitem和obj指向的是同一个地址,则对this.todoItem的修改,会直接反应到obj上,也就是todoList中的这个元素上,所以在列表中会直接提现出来,避免这种情况的发生的方法,只要避免饮用赋值即可,所以对上述代码进行如下修改:

//找到id值等于所传参数的todoitem
   var obj = this.todolist.filter(v => v.id === id)[0];
   //对数据进行绑定,则数据会响应到表单上
   this.todoItem = {
   id:obj.id,
   title:obj.title,
   desc:obj.desc
   };

刷新运行,发生程序按照预期运行了,接下来,增加更新保存操作,修改OK按钮的事件绑定方式为save,并通过id判断新增还是修改操作:

<div class="col-md-6">

  <div class="form-inline">
  <label for="title" class="control-label col-md-4">title:</label>
  <input type="hidden" v-bind:value="todoItem.id" />
  <input type="text" v-model="todoItem.title" class="form-control col-md-8">
  </div>
  <div class="form-inline">
  <label for="desc" class="control-label col-md-4">desc</label>
  <input type="text" v-model="todoItem.desc" class="form-control col-md-8">
  </div>
  <div class="form-inline">
  <input type="button" value="OK" v-on:click="save()" class="btn btn-primary offset-md-10" />
  </div>
 </div>
methods: {
  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 = {};
  },
  
  remove: function (index) {
   this.todolist.splice(index, 1);
  }

  }

代码比较简单,这里就不再赘述,可以看一下运行效果:

前端主流框架vue学习笔记第二篇

为了逼格更高一点,这里我再介绍一个指令,其实上面已经使用了,v-bind ,这个指令和v-on是类似的,两者的区别在于后面的参数不同,一般v-bind用来传递属性参数,一般使用缩写形式:attr,可以绑定自定义属性,上面代码中我们对Id值的绑定已经使用了v-bind:value="todoItem.id",这里相当于angular中ng-bind。基于对v-bind的了解,我们可以推理,给v-bind添加disable的属性,使OK按钮只有再title不为空的前提下再可用。

<div class="form-inline">
  <input type="button" value="OK" v-on:click="save()" class="btn btn-primary offset-md-10" :disabled='!todoItem.title'/>
  </div>

刷新运行:

前端主流框架vue学习笔记第二篇

上面代码能很好的运行,但是现在如果我需要修改一下验证规则,在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 class="form-inline">
  <input type="button" value="OK" v-on:click="save()" class="btn btn-primary offset-md-10" :disabled='canSave'/>
  </div>

刷新页面,运行效果如图:

前端主流框架vue学习笔记第二篇

ok,编辑这部分内容就到这里吧,在没有后端接口的前提下,保存操作都是模拟的,接下来对我们的查询进行一下简单的介绍,这里查询,由于没有后端接口,咱们只做最简单的演示,对代码做如下处理:

1、增加查询输入框,keyword,添加查询按钮

2、点击查询操作,预期结果:根据输入的查询关键字,过滤列表

按照上面思路对我们代码进行修改:

<div class="row toolbar">
 <div class="col-md-8">
  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);
  }

刷新页面运行效果如图:

前端主流框架vue学习笔记第二篇

代码部分注释中已经写的很清楚了,有疑问可提价comment。本章就到这里,文章有点水,在(三)中会加入添加服务端支持,并使用axios和服务端rest接口进行交互敬请期待,准备睡觉。

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" 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" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">

</head>

<body class="container">
 <div id="app">
 <div class="row toolbar">
  <div class="col-md-8">
  keyword:
  <input type="text" v-model="keyword" />
  <input type="button" @click="query()" value="search" />
  </div>
 </div>
 <div class='row'>

  <div class="col-md-6">
  <table class="table table-bordered">
   <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)" class="btn btn-danger" />
    <input type="button" value="edit" @click="edit(todoItem.id)" class="btn btn-info" />
   </td>
   </tr>
  </table>
  </div>
  <div class="col-md-6">

  <div class="form-inline">
   <label for="title" class="control-label col-md-4">title:</label>
   <input type="hidden" v-bind:value="todoItem.id" />
   <input type="text" v-model="todoItem.title" class="form-control col-md-8">
  </div>
  <div class="form-inline">
   <label for="desc" class="control-label col-md-4">desc</label>
   <input type="text" v-model="todoItem.desc" class="form-control col-md-8">
  </div>
  <div class="form-inline">
   <input type="button" value="OK" v-on:click="save()" class="btn btn-primary offset-md-10" :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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
符合W3C网页标准的iframe标签的使用方法
Jul 19 Javascript
JS启动应用程序的一个简单例子
May 11 Javascript
ExtJS GTGrid 简单用户管理
Jul 01 Javascript
控制页面按钮在后台执行期间不重复提交的JS方法
Jun 24 Javascript
动态载入js提高网页打开速度的方法
Jul 04 Javascript
AngularJS基础 ng-value 指令简单示例
Aug 03 Javascript
jQuery选择器特殊字符与属性空格问题
Aug 14 jQuery
微信小程序实现下载进度条的方法
Dec 08 Javascript
Material(包括Material Icon)在Angular2中的使用详解
Feb 11 Javascript
浅谈Vue网络请求之interceptors实际应用
Feb 28 Javascript
JS实现电话号码的字母组合算法示例
Feb 26 Javascript
JS继承实现方法及优缺点详解
Sep 02 Javascript
浅谈vue.js中v-for循环渲染
Jul 26 #Javascript
前端主流框架vue学习笔记第一篇
Jul 26 #Javascript
关于vue.js组件数据流的问题
Jul 26 #Javascript
Vue.js弹出模态框组件开发的示例代码
Jul 26 #Javascript
VueJs单页应用实现微信网页授权及微信分享功能示例
Jul 26 #Javascript
node实现简单的反向代理服务器
Jul 26 #Javascript
Angular项目中$scope.$apply()方法的使用详解
Jul 26 #Javascript
You might like
Excel数据导入Mysql数据库的实现代码
2008/06/05 PHP
PHP比你想象的好得多
2014/11/27 PHP
php封装db类连接sqlite3数据库的方法实例
2017/12/19 PHP
php 下 html5 XHR2 + FormData + File API 上传文件操作实例分析
2020/02/28 PHP
Jquery为a标签的href赋值实现代码
2013/05/03 Javascript
原生JS实现响应式瀑布流布局
2015/04/02 Javascript
基于jQuery通过jQuery.form.js插件使用ajax提交form表单
2015/08/17 Javascript
js中json处理总结之JSON.parse
2016/10/14 Javascript
如何使用Bootstrap 按钮实例详解
2017/03/29 Javascript
学习JS中的DOM节点以及操作
2018/04/30 Javascript
vue cli2.0单页面title修改方法
2018/06/07 Javascript
vue实现的仿淘宝购物车功能详解
2019/01/27 Javascript
vue elementUI table表格数据 滚动懒加载的实现方法
2019/04/04 Javascript
JS实现瀑布流效果
2020/03/07 Javascript
Python 3.6 性能测试框架Locust安装及使用方法(详解)
2017/10/11 Python
Python实现的摇骰子猜大小功能小游戏示例
2017/12/18 Python
详解TensorFlow在windows上安装与简单示例
2018/03/05 Python
python监控文件并且发送告警邮件
2018/06/21 Python
pycharm修改界面主题颜色的方法
2019/01/17 Python
对Python3中dict.keys()转换成list类型的方法详解
2019/02/03 Python
python制作抖音代码舞
2019/04/07 Python
Python Request爬取seo.chinaz.com百度权重网站的查询结果过程解析
2019/08/13 Python
Python学习笔记之列表推导式实例分析
2019/08/13 Python
tesserocr与pytesseract模块的使用方法解析
2019/08/30 Python
Django和Flask框架优缺点对比
2019/10/24 Python
python实现图像全景拼接
2020/03/27 Python
python解压zip包中文乱码解决方法
2020/11/27 Python
CSS3教程(1):什么是CSS3
2009/04/02 HTML / CSS
政府绩效管理实施方案
2014/05/04 职场文书
师德演讲稿范文
2014/05/06 职场文书
自我推荐信范文
2014/05/09 职场文书
化学专业自荐信
2014/05/28 职场文书
离职告别感言
2015/08/04 职场文书
诚信考试主题班会
2015/08/17 职场文书
告诉你创业计划书的8个实用技巧
2019/07/12 职场文书
2019年公司卫生管理制度样本
2019/08/21 职场文书