图书列表案例
-
静态列表效果
-
基于数据实现模板效果
-
处理每行的操作按钮
1、 提供的静态数据
-
数据存放在vue 中 data 属性中
var vm = new Vue({ el: '#app', data: { books: [{ id: 1, name: '三国演义', date: '' },{ id: 2, name: '水浒传', date: '' },{ id: 3, name: '红楼梦', date: '' },{ id: 4, name: '西游记', date: '' }] } }); var vm = new Vue({ el: '#app', data: { books: [{ id: 1, name: '三国演义', date: '' },{ id: 2, name: '水浒传', date: '' },{ id: 3, name: '红楼梦', date: '' },{ id: 4, name: '西游记', date: '' }] } });
2、 把提供好的数据渲染到页面上
-
利用 v-for循环 遍历 books 将每一项数据渲染到对应的数据中
<tbody> <tr :key='item.id' v-for='item in books'> <!-- 对应的id 渲染到页面上 --> <td>{{item.id}}</td> <!-- 对应的name 渲染到页面上 --> <td>{{item.name}}</td> <td>{{item.date}}</td> <td> <!-- 阻止 a 标签的默认跳转 --> <a href="" @click.prevent>修改</a> <span>|</span> <a href="" @click.prevent>删除</a> </td> </tr> </tbody>
3、 添加图书
-
通过双向绑定获取到输入框中的输入内容
-
给按钮添加点击事件
-
把输入框中的数据存储到 data 中的 books 里面
<div> <h1>图书管理</h1> <div class="book"> <div> <label for="id"> 编号: </label> <!-- 3.1、通过双向绑定获取到输入框中的输入的 id --> <input type="text" id="id" v-model='id'> <label for="name"> 名称: </label> <!-- 3.2、通过双向绑定获取到输入框中的输入的 name --> <input type="text" id="name" v-model='name'> <!-- 3.3、给按钮添加点击事件 --> <button @click='handle'>提交</button> </div> </div> </div> <script type="text/javascript"> /* 图书管理-添加图书 */ var vm = new Vue({ el: '#app', data: { id: '', name: '', books: [{ id: 1, name: '三国演义', date: '' },{ id: 2, name: '水浒传', date: '' },{ id: 3, name: '红楼梦', date: '' },{ id: 4, name: '西游记', date: '' }] }, methods: { handle: function(){ // 3.4 定义一个新的对象book 存储 获取到输入框中 书 的id和名字 var book = {}; book.id = this.id; book.name = this.name; book.date = ''; // 3.5 把book 通过数组的变异方法 push 放到 books 里面 this.books.push(book); //3.6 清空输入框 this.id = ''; this.name = ''; } } }); </script>
4 修改图书-上
-
点击修改按钮的时候 获取到要修改的书籍名单
-
4.1 给修改按钮添加点击事件, 需要把当前的图书的id 传递过去 这样才知道需要修改的是哪一本书籍
-
-
把需要修改的书籍名单填充到表单里面
-
4.2 根据传递过来的id 查出books 中 对应书籍的详细信息
-
4.3 把获取到的信息填充到表单
-
<div id="app"> <div class="grid"> <div> <h1>图书管理</h1> <div class="book"> <div> <label for="id"> 编号: </label> <input type="text" id="id" v-model='id' :disabled="flag"> <label for="name"> 名称: </label> <input type="text" id="name" v-model='name'> <button @click='handle'>提交</button> </div> </div> </div> <table> <thead> <tr> <th>编号</th> <th>名称</th> <th>时间</th> <th>操作</th> </tr> </thead> <tbody> <tr :key='item.id' v-for='item in books'> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.date}}</td> <td> <!--- 4.1 给修改按钮添加点击事件, 需要把当前的图书的id 传递过去 这样才知道需要修改的是哪一本书籍 ---> <a href="" @click.prevent='toEdit(item.id)'>修改</a> <span>|</span> <a href="" @click.prevent>删除</a> </td> </tr> </tbody> </table> </div> </div> <script type="text/javascript"> /* 图书管理-添加图书 */ var vm = new Vue({ el: '#app', data: { flag: false, id: '', name: '', books: [{ id: 1, name: '三国演义', date: '' },{ id: 2, name: '水浒传', date: '' },{ id: 3, name: '红楼梦', date: '' },{ id: 4, name: '西游记', date: '' }] }, methods: { handle: function(){ // 3.4 定义一个新的对象book 存储 获取到输入框中 书 的id和名字 var book = {}; book.id = this.id; book.name = this.name; book.date = ''; // 3.5 把book 通过数组的变异方法 push 放到 books 里面 this.books.push(book); //3.6 清空输入框 this.id = ''; this.name = ''; }, toEdit: function(id){ console.log(id) //4.2 根据传递过来的id 查出books 中 对应书籍的详细信息 var book = this.books.filter(function(item){ return item.id == id; }); console.log(book) //4.3 把获取到的信息填充到表单 // this.id 和 this.name 通过双向绑定 绑定到了表单中 一旦数据改变视图自动更新 this.id = book[0].id; this.name = book[0].name; } } }); </script>
5 修改图书-下
-
5.1 定义一个标识符, 主要是控制 编辑状态下当前编辑书籍的id 不能被修改 即 处于编辑状态下 当前控制书籍编号的输入框禁用
-
5.2 通过属性绑定给书籍编号的 绑定 disabled 的属性 flag 为 true 即为禁用
-
5.3 flag 默认值为false 处于编辑状态 要把 flag 改为true 即当前表单为禁用
-
5.4 复用添加方法 用户点击提交的时候依然执行 handle 中的逻辑如果 flag为true 即 表单处于不可输入状态 此时执行的用户编辑数据数据
<div id="app"> <div class="grid"> <div> <h1>图书管理</h1> <div class="book"> <div> <label for="id"> 编号: </label> <!-- 5.2 通过属性绑定 绑定 disabled 的属性 flag 为 true 即为禁用 --> <input type="text" id="id" v-model='id' :disabled="flag"> <label for="name"> 名称: </label> <input type="text" id="name" v-model='name'> <button @click='handle'>提交</button> </div> </div> </div> <table> <thead> <tr> <th>编号</th> <th>名称</th> <th>时间</th> <th>操作</th> </tr> </thead> <tbody> <tr :key='item.id' v-for='item in books'> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.date}}</td> <td> <a href="" @click.prevent='toEdit(item.id)'>修改</a> <span>|</span> <a href="" @click.prevent>删除</a> </td> </tr> </tbody> </table> </div> </div> <script type="text/javascript"> /*图书管理-添加图书*/ var vm = new Vue({ el: '#app', data: { // 5.1 定义一个标识符, 主要是控制 编辑状态下当前编辑书籍的id 不能被修改 // 即 处于编辑状态下 当前控制书籍编号的输入框禁用 flag: false, id: '', name: '', }, methods: { handle: function() { /* 5.4 复用添加方法 用户点击提交的时候依然执行 handle 中的逻辑 如果 flag为true 即 表单处于不可输入状态 此时执行的用户编辑数据数据 */ if (this.flag) { // 编辑图书 // 5.5 根据当前的ID去更新数组中对应的数据 this.books.some((item) => { if (item.id == this.id) { // 箭头函数中 this 指向父级作用域的this item.name = this.name; // 完成更新操作之后,需要终止循环 return true; } }); // 5.6 编辑完数据后表单要处以可以输入的状态 this.flag = false; // 5.7 如果 flag为false 表单处于输入状态 此时执行的用户添加数据 } else { var book = {}; book.id = this.id; book.name = this.name; book.date = ''; this.books.push(book); // 清空表单 this.id = ''; this.name = ''; } // 清空表单 this.id = ''; this.name = ''; }, toEdit: function(id) { /* 5.3 flag 默认值为false 处于编辑状态 要把 flag 改为true 即当前表单为禁 用 */ this.flag = true; console.log(id) var book = this.books.filter(function(item) { return item.id == id; }); console.log(book) this.id = book[0].id; this.name = book[0].name; } } }); </script>
6 删除图书
-
6.1 给删除按钮添加事件 把当前需要删除的书籍id 传递过来
-
6.2 根据id从数组中查找元素的索引
-
6.3 根据索引删除数组元素
<tbody> <tr :key='item.id' v-for='item in books'> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.date}}</td> <td> <a href="" @click.prevent='toEdit(item.id)'>修改</a> <span>|</span> <!-- 6.1 给删除按钮添加事件 把当前需要删除的书籍id 传递过来 --> <a href="" @click.prevent='deleteBook(item.id)'>删除</a> </td> </tr> </tbody> <script type="text/javascript"> /* 图书管理-添加图书 */ var vm = new Vue({ methods: { deleteBook: function(id){ // 删除图书 #// 6.2 根据id从数组中查找元素的索引 // var index = this.books.findIndex(function(item){ // return item.id == id; // }); #// 6.3 根据索引删除数组元素 // this.books.splice(index, 1); // ------------------------- #// 方法二:通过filter方法进行删除 # 6.4 根据filter 方法 过滤出来id 不是要删除书籍的id # 因为 filter 是替换数组不会修改原始数据 所以需要 把 不是要删除书籍的id 赋值给 books this.books = this.books.filter(function(item){ return item.id != id; }); } } }); </script>
常用特性应用场景
1 过滤器
-
Vue.filter 定义一个全局过滤器
<tr :key='item.id' v-for='item in books'> <td>{{item.id}}</td> <td>{{item.name}}</td> <!-- 1.3 调用过滤器 --> <td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td> <td> <a href="" @click.prevent='toEdit(item.id)'>修改</a> <span>|</span> <a href="" @click.prevent='deleteBook(item.id)'>删除</a> </td> </tr> <script> #1.1 Vue.filter 定义一个全局过滤器 Vue.filter('format', function(value, arg) { function dateFormat(date, format) { if (typeof date === "string") { var mts = date.match(/(/Date((d+))/)/); if (mts && mts.length >= 3) { date = parseInt(mts[2]); } } date = new Date(date); if (!date || date.toUTCString() == "Invalid Date") { return ""; } var map = { "M": date.getMonth() + 1, //月份 "d": date.getDate(), //日 "h": date.getHours(), //小时 "m": date.getMinutes(), //分 "s": date.getSeconds(), //秒 "q": Math.floor((date.getMonth() + 3) / 3), //季度 "S": date.getMilliseconds() //毫秒 }; format = format.replace(/([yMdhmsqS])+/g, function(all, t) { var v = map[t]; if (v !== undefined) { if (all.length > 1) { v = '0' + v; v = v.substr(v.length - 2); } return v; } else if (t === 'y') { return (date.getFullYear() + '').substr(4 - all.length); } return all; }); return format; } return dateFormat(value, arg); }) #1.2 提供的数据 包含一个时间戳 为毫秒数 [{ id: 1, name: '三国演义', date: 2525609975000 },{ id: 2, name: '水浒传', date: 2525609975000 },{ id: 3, name: '红楼梦', date: 2525609975000 },{ id: 4, name: '西游记', date: 2525609975000 }]; </script>
2 自定义指令
-
让表单自动获取焦点
-
通过Vue.directive 自定义指定
<!-- 2.2 通过v-自定义属性名 调用自定义指令 --> <input type="text" id="id" v-model='id' :disabled="flag" v-focus> <script> # 2.1 通过Vue.directive 自定义指定 Vue.directive('focus', { inserted: function (el) { el.focus(); } }); </script>
3 计算属性
-
通过计算属性计算图书的总数
-
图书的总数就是计算数组的长度
-
<div class="total"> <span>图书总数:</span> <!-- 3.2 在页面上 展示出来 --> <span>{{total}}</span> </div> <script type="text/javascript"> /* 计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存 */ var vm = new Vue({ data: { flag: false, submitFlag: false, id: '', name: '', books: [] }, computed: { total: function(){ // 3.1 计算图书的总数 return this.books.length; } }, }); </script>