用到的vue常用特性预览
- 表单操作
- 自定义指令
- 计算属性
- 侦听器
- 过滤器
- 生命周期
图书管理原始html
<div id="app">
<div class="grid">
<table>
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>时间</th>
<th>操作</th>
</tr>
<tr>
<td>1</td>
<td>三国演义</td>
<td>时间</td>
<td>操作</td>
</tr>
<tr>
<td>1</td>
<td>三国演义</td>
<td>时间</td>
<td>操作</td>
</tr>
<tr>
<td>1</td>
<td>三国演义</td>
<td>时间</td>
<td>操作</td>
</tr>
<tr>
<td>1</td>
<td>三国演义</td>
<td>时间</td>
<td>操作</td>
</tr>
</thead>
</table>
</div>
</div>
图书管理css
<style type="text/css">
.grid {
margin: auto;
width: 500px;
text-align: center;
}
.grid table {
width: 100%;
border-collapse: collapse;
}
.grid th,
td {
padding: 10;
border: 1px dashed orange;
height: 35px;
line-height: 35px;
}
.grid th {
background-color: orange;
}
</style>
提供的数据
books: [{
id: 1,
name: '三国演义',
date: ''
}, {
id: 2,
name: '水浒传',
date: ''
}, {
id: 3,
name: '红楼梦',
date: ''
}, {
id: 4,
name: '西游记',
date: ''
}]
基本效果
下面使用vue重构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.grid {
margin: auto;
width: 500px;
text-align: center;
}
.grid table {
width: 100%;
border-collapse: collapse;
}
.grid th,
td {
padding: 10;
border: 1px dashed orange;
height: 35px;
line-height: 35px;
}
.grid th {
background-color: orange;
}
.grid .book {
background-color: orange;
padding-top: 20px;
}
</style>
</head>
<body>
<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" v-focus>
<label for="name">
名称:
</label>
<input type="text" id="name" v-model="name">
<!-- 验证图书的存在性 -->
<button @click.prevent="add()">提交</button>
</div>
<!-- 计算属性,计算图书的总数 :就是books数组的长度-->
<div class="total">
<span>图书总数</span>
<span v-text='total'></span>
</div>
</div>
</div>
<table>
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>时间</th>
<th>操作</th>
</tr>
<!-- 通过循环,将数据渲染到页面 -->
<tr :key='item.id' v-for="(item,index) in books">
<td v-text='item.id'></td>
<td v-text='item.name'>三国演义</td>
<td v-text='item.date '></td>
<!-- 时间过滤器没有研究明白 -->
<!-- <td v-text='item.date| format(" yyyy-MM-dd hh:mm:ss ") '></td> -->
<td>
<a href="" @click.prevent='modify(item.id)'>修改</a>
<span> | </span>
<!-- 注意:删除名不能用delete,因为是关键字 -->
<a href="" @click.prevent='del(item.id)'>删除</a>
</td>
</tr>
</thead>
</table>
</div>
</div>
<script type="text/javascript" src="../vue.js"></script>
<script type="text/javascript">
// 全局定义自定义指令
Vue.directive('focus', {
inserted: function(el) {
el.focus()
}
})
// 自定义过滤器
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);
})
// 图书列表展示功能
var vm = new Vue({
el: '#app ',
data: {
id: ' ',
name: ' ',
data: ' ',
flag: false,
books: [{
id: 1,
name: '三国演义 ',
date: 2525609975000
}, {
id: 2,
name: '水浒传 ',
date: 2525609975000
}, {
id: 3,
name: '红楼梦 ',
date: 2525609975000
}, {
id: 4,
name: '西游记 ',
date: 2525609975000
}]
},
methods: {
// 删除图书:根据id找出对应图书列表的索引
del: function(id) {
var index = this.books.findIndex(item => {
return item.id == id
})
this.books.splice(index, 1)
},
// 添加图书+修改图书时的编辑
// 通过flag来判断当前是添加还是修改时的编辑,复用添加方法
add: function() {
if (this.flag) {
// 如果为真,禁用id输入框,为修改图书的编辑功能
// 根据id跟新数组中的数据
this.books.some(item => {
if (item.id == this.id) {
item.name = this.name
// 跟新完成后, 终止循环
return true
}
})
// 编辑完表单, 要改变输入框禁用属性
this.flag = false
} else {
this.books.push({
id: this.id,
name: this.name
})
this.id = ''
this.name = ''
}
this.id = ''
this.name = ''
},
// 修改图书:先将要修改的数据展示在编辑页
modify: function(id) {
// 点击修改的时候,将状态改为禁止
this.flag = true
console.log(id);
// 根据传来的id,查出对应的图书信息
var book = this.books.filter(item => {
return item.id == id
})
console.log(book);
this.id = book[0].id
this.name = book[0].name
// 下一步开始编辑,但是编辑的时候,当前的图书id不能修改,所以禁用id输入框
// 当然,也可以根据id输入框的状态,来判断是修改状态下的编辑,还是增加状态下的编辑
}
},
// 局部定义的过滤器,自定义指令,都需要一个返回值.而且在html处是属性,在vue实例是方法,
// 所以此属性不能在vue实例的data中初始化
computed: {
total: function() {
return this.books.length;
}
},
});
</script>
</body>
</html>
要点说明
- 通过v-for进行数据循环,将数据填充到页面
- 添加操作:用到的是push方法,通过属性,属性值的方式来添加,所以push方法里面用了对象{id:this.id,name:this.name} 这里的this指的是vue,也就是vue监听到的最新的id,name
- 数据的修改分两步1:将要修改的数据展示在输入框2:进行数据的修改(修改的时候,id值是禁止修改的)
-1:将数据展示在输入框:为修改按钮绑定事件,并且传入id,在事件中利用filter(),来查找id对应的图书信息,得到的是一个数组,然后将数组的第0个索引的值,依次赋值给当前的id,当前的name
-2:利用修改状态下,禁止输入框输入这个条件,实现添加功能的复用
在添加功能里面,用if else 来判断禁用框的状态
进入修改数据的条件后,利用some(),根据id更新数组中的数据
在编辑完后,将输入框的状态变为非禁用
亲空编辑输入框的数据 - 删除操作:利用findIndex()根据id找到对应图书的索引,利用splice()来删除数据
- 利用计算属性,计算图书的总量,其实就是books数组的长度
- 定义全局指令(实现自动聚焦),全局过滤器(格式化时间,暂时没有实现)
效果展示