最近在学习vue.js,我把工作中项目里面的一个小实例用vue.js重构了下,写成一个小demo,巩固自己所学,并与大家分享,一起交流。
一、需求稿:
状态筛选栏:
筛选后:
用户操作弹出层:
1.“重试”弹出层
点击重试:状态变为“进行中”
点击删除:删除该行数据
2.“取消”弹出层
点击确定:该行数据状态变为“失败”
3.“下载”弹出层
点击下载:下载该文件(暂不做,以alert为成功提示)
二.html 结构
<div class="table-demo container" id="app">
<div class="row table-search">
<h1>vue-table小样例</h1>
</div>
<div class="row">
<table class="my-table table table-bordered">
<thead>
<tr>
<th class="list"
@click="sort"
:class="{'top':isTop,'down':!isTop}"
>任务ID</th>
<th class="list">内容</th>
<th class="list">依赖文件</th>
<th class="list">完成时间</th>
<th class="list">耗时</th>
<th class="status"
:class="{'open':isSetstatus}" @click="setStatus">
状态({{statusName}})
<ul class="slidedown">
<li @click="filterComplete('全部')">全部</li>
<li @click="filterComplete('完成')">完成</li>
<li @click="filterComplete('失败')">失败</li>
<li @click="filterComplete('进行中')">进行中</li>
</ul>
</th>
<th class="list">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in tableData">
<td>{{item.id}}</td>
<td>{{item.content}}</td>
<td>{{item.document}}</td>
<td>{{item.completeTime | conTimeFormat}}</td>
<td>{{item.time | timeFormat}}</td>
<td :class="{'red':item.status==='失败','green':item.status==='完成'
,'orange':item.status==='进行中'}">{{item.status}}</td>
<td v-if="item.status==='完成'">
<a href="##" @click="adminSet(1,index)">下载</a>
</td>
<td v-else-if="item.status==='进行中'">
<a href="##" @click="adminSet(2,index)">取消</a>
</td>
<td v-else="item.status==='失败'">
<a href="##" @click="adminSet(3,index)">重试</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="layer-box" :class="{'open':isLayer}">
<my-layer :message="layerMessage"></my-layer>
</div>
</div>
<!-- 弹出框组件 -->
<script type="text/x-template" id="layer">
<div class="layer">
<h2>标题</h2>
<div class="content">
{{message.content}}
</div>
<div class="footer">
<template v-if="message.type==='onload'">
<a href="##" @click="closed">{{message.btn1}}</a>
<a href="##" @click="onload">{{message.btn2}}</a>
</template>
<template v-else-if="message.type==='cancel'">
<a href="##" @click="closed">{{message.btn1}}</a>
<a href="##" @click="cancel">{{message.btn2}}</a>
</template>
<template v-else>
<a href="##" @click="remove">{{message.btn1}}</a>
<a href="##" @click="reset">{{message.btn2}}</a>
</template>
</div>
</div>
</script>
三.js
// 全局注册的弹出框组件
Vue.component('myLayer',{
// prop 接收数据
props: {
message: {
type: Object
}
},
// 组件的模板
template: '#layer',
methods: {
// 关闭弹出框
closed: function(){
app.isLayer = false;
},
// 下载
onload: function(){
alert('下载成功');
app.isLayer = false;
},
// 取消任务
cancel: function(){
app.tableData[app.itemIndex]['status'] = '失败';
app.isLayer = false;
},
// 删除任务
remove: function(){
app.tableData.splice(app.itemIndex,1);
app.isLayer = false;
},
// 重试任务
reset: function(){
app.tableData[app.itemIndex]['status'] = '进行中';
app.isLayer = false;
}
}
});
// 实例化vue对象
var app = new Vue({
el: '#app',
data: {
tableData: [],
isSetstatus: false,
layerMessage: {
btn1: '',
btn2: '',
content: ''
},
isLayer: false,
itemIndex: 0,
isTop: true,
statusName: '全部'
},
created: function(){
// jsonObject.body 为模拟的数据
this.tableData = jsonObject.body;
},
filters: {
// 格式化时间
conTimeFormat: function(v){
var time = new Date(parseFloat(v));
var year = time.getFullYear();
var month = time.getMonth()<10?'0'+time.getMonth():time.getMonth();
var day = time.getDate();
var hour = time.getHours();
var minutes = time.getMinutes();
var seconds = time.getSeconds();
var formatTime = year + '年' + month + '月' + day + '日'
+ ' ' + hour + '时' + minutes + '分' + seconds + '秒';
return formatTime;
},
timeFormat: function(v){
return v + 's';
}
},
methods: {
// 打开或关闭状态栏
setStatus: function(){
this.isSetstatus = !this.isSetstatus;
},
// 状态筛选
filterComplete: function(statusName){
var _this = this;
this.tableData = jsonObject.body;
var newTableData = [];
if(statusName!=='全部'){
this.tableData.forEach(function(v,i){
if(v.status === statusName){
newTableData.push(v);
}
});
this.tableData = newTableData;
}
this.statusName = statusName;
},
// 用户操作 下载 取消 重试
adminSet: function(value,index) {
var loadMessage = null;
switch(value) {
case 1:
loadMessage = {
btn1: '取消',
btn2: '下载',
content: '您确定下载此文件吗?',
type: 'onload'
}
break;
case 2:
loadMessage = {
btn1: '考虑一下',
btn2: '确定',
content: '您确定取消该任务吗?',
type: 'cancel'
}
break;
case 3:
loadMessage = {
btn1: '删除',
btn2: '重试',
content: '是否重试该任务?',
type: 'reset'
}
break;
}
this.isLayer = true;
this.layerMessage = loadMessage;
this.itemIndex = index;
},
// 任务id排序
sort: function(){
var temp;
var newTableData = [];
this.tableData.forEach(function(v,i){
newTableData.push(v);
});
if(this.isTop){
// 从大到小排序
for(var i=0;i<newTableData.length-1;i++){
for(var j=i+1;j<newTableData.length;j++){
if((newTableData[i]['id'] - newTableData[j]['id'])<0){
temp = newTableData[i];
newTableData[i] = newTableData[j];
newTableData[j] = temp;
}
}
}
this.isTop = false;
}else {
// 从小到大排序
for(var i=0;i<newTableData.length-1;i++){
for(var j=i+1;j<newTableData.length;j++){
if((newTableData[i]['id'] - newTableData[j]['id'])>0){
temp = newTableData[i];
newTableData[i] = newTableData[j];
newTableData[j] = temp;
}
}
}
this.isTop = true;
}
this.tableData = newTableData;
}
}
});
ps: 源码在我的github上:https://github.com/helsingVan/vue-demo.git
欢迎纠正以及提bug。