CLI组件化列表信息完整功能实现
<template>
<div>
<BugHeader :bugList="bugList" :saveBugCallBack="saveBugCallBack"></BugHeader>
<BugList :updateDescCallBack="updateDescCallBack" :selectAllRollback="selectAllRollback" v-show="bugList.length" :bugList="bugList" :modifyResolvedCallBack="modifyResolvedCallBack" :deleteByIdCallBack="deleteByIdCallBack"></BugList>
<BugFooter :cleanResolved="cleanResolved" v-show="bugList.length" :bugList="bugList" :deleteByIdCallBack="deleteByIdCallBack"></BugFooter>
</div>
</template>
<script>
import BugHeader from "./components/BugHeader.vue";
import BugList from "./components/BugList.vue";
import BugFooter from "./components/BugFooter.vue";
export default {
name : "App",
components : {BugHeader,BugList,BugFooter},
data(){
return {
bugList : [
{id : 1,desc : "Bug描述信息100",resolved : true},
{id : 2,desc : "Bug描述信息200",resolved : false},
{id : 3,desc : "Bug描述信息300",resolved : true},
]
}
},
methods : {
// 因为我们不能直接动props的数据
// 那我们就传递一个方法过去进行修改
saveBugCallBack(bug){
this.bugList.unshift(bug);
},
// 一键全选或反选
selectAllRollback(checked){
this.bugList.forEach((bug) => {
bug.resolved = checked;
});
},
// 修改选中状态
modifyResolvedCallBack(id)
{
this.bugList.forEach((bug) => {
if(bug.id === id){
bug.resolved = !bug.resolved;
}
});
},
// 删除数组的元素
deleteByIdCallBack(id)
{
this.bugList = this.bugList.filter((bug) => {
return bug.id !== id;
});
},
// 清除以选中
cleanResolved(){
this.bugList = this.bugList.filter((bug) => {
return bug.resolved === false;
});
},
// 更新描述信息
updateDescCallBack(id,newDesc){
this.bugList.forEach((bug) => {
if(bug.id === id)
{
bug.desc = newDesc;
return;
}
});
}
}
}
</script>
<style>
.button{
display: inline-block inline;
zoom: 1;
padding: 6px 20px;
margin: 0;
cursor: pointer;
border: 1px solid #bbb;
overflow: visible;
font: bold 13px arial, helvetica, sans-serif;
text-decoration: none;
white-space: nowrap;
color: #555;
background-color: #ddd;
background-image: -webkit-gradient(linear, to right top, to right bottom, form(rgba(255,255,255,1)), to(rgba(255,255,255,0)));
background-image: -webkit-linear-gradient(to bottom, rgba(255,255,255,1), rgba(255,255,255,0));
background-image: -moz-linear-gradient(to bottom, rgba(255,255,255,1), rgba(255,255,255,0));
background-image: -ms-linear-gradient(to bottom, rgba(255,255,255,1), rgba(255,255,255,0));
background-image: -o-linear-gradient(to bottom, rgba(255,255,255,1), rgba(255,255,255,0));
background-image: linear-gradient(to bottom, rgba(255,255,255,1), rgba(255,255,255,0));
-webkit-transition: background-color .2s ease-out;
-moz-transition: background-color .2s ease-out;
-ms-transition: background-color .2s ease-out;
-o-transition: background-color .2s ease-out;
transition: background-color .2s ease-out;
background-clip: padding-box; /* Fix bleeding */
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 0 rgba(0, 0, 0, .3), 0 2px 2px -1px rgba(0, 0, 0, .5), 0 1px 0 rgba(255, 255, 255, .3) inset;
-webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, .3), 0 2px 2px -1px rgba(0, 0, 0, .5), 0 1px 0 rgba(255, 255, 255, .3) inset;
box-shadow: 0 1px 0 rgba(0, 0, 0, .3), 0 2px 2px -1px rgba(0, 0, 0, .5), 0 1px 0 rgba(255, 255, 255, .3) inset;
text-shadow: 0 1px 0 rgba(255,255,255, .9);
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.button:active{
background: #e9e9e9;
position: relative;
top: 1px;
text-shadow: none;
-moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .3) inset;
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .3) inset;
box-shadow: 0 1px 1px rgba(0, 0, 0, .3) inset;
}
.button.red{
color: #fff;
text-shadow: 0 1px 0 rgba(0,0,0,.2);
background-image: -webkit-gradient(linear, to right top, to right bottom, from(rgba(255,255,255,.3)), to(rgba(255,255,255,0)));
background-image: -webkit-linear-gradient(to bottom, rgba(255,255,255,.3), rgba(255,255,255,0));
background-image: -moz-linear-gradient(to bottom, rgba(255,255,255,.3), rgba(255,255,255,0));
background-image: -ms-linear-gradient(to bottom, rgba(255,255,255,.3), rgba(255,255,255,0));
background-image: -o-linear-gradient(to bottom, rgba(255,255,255,.3), rgba(255,255,255,0));
background-image: linear-gradient(to bottom, rgba(255,255,255,.3), rgba(255,255,255,0));
}
.button.red{
background-color: #ca3535;
border-color: #c43c35;
}
.button.red:hover{
background-color: #ee5f5b;
}
.button.red:active{
background: #c43c35;
}
.button.green{
background-color: #57a957;
border-color: #57a957;
}
.button.green:hover{
background-color: #62c462;
}
.button.green:active{
background: #57a957;
}
</style>
<template>
<tr>
<td><input type="checkbox" :checked="bug.resolved" @change="$event => modifyResolved(bug.id)"></td>
<!-- <td><input type="checkbox" v-model="bug.resolved"></td>尽管没报错,但是props的数据不建议修改 -->
<td>
<span @click="enterEdit(bug)" v-show="!bug.editState" class="desc">{{ bug.desc }}</span>
<input @blur="updateDesc(bug,$event)" ref="inputDesc" v-show="bug.editState" type="text" v-model="bug.desc"/>
</td>
<td><button class="samll red button" @click="$event => deleteById(bug.id)">删除</button></td>
</tr>
</template>
<script>
export default {
name : "BugItem",
props : ['bug',"modifyResolvedCallBack","deleteByIdCallBack","updateDescCallBack"],
methods : {
modifyResolved(id){
this.modifyResolvedCallBack(id);
},
deleteById(id){
this.deleteByIdCallBack(id);
},
// 进入编辑状态
enterEdit(bug){
if(bug.hasOwnProperty("editState")){
bug.editState = true;
}
else{
// 如果后期要给属性动态添加属性,且这个属性是响应式的
this.$set(bug,"editState",true);
// 获取文本框获得焦点
// Vue原理是整个方法执行完成之后才会渲染dom,为了提高效率
// 因此我们通过延时的方式让dom先完成渲染,我们再执行focus就可以获取焦点了
// 第一种方案
// setTimeout(() => {
// this.$refs.inputDesc.focus();
// });
// 第二种方案,使用VUE提供的API完成这个效果
// 这个方法的原理是,代码执行完成dom渲染完成之后,再执行这个回调函数
this.$nextTick(function(){
this.$refs.inputDesc.focus();
});
}
},
updateDesc(bug,e){
let newDesc = e.target.value.trim();
// 非空校验
if(!newDesc) return;
if(newDesc != "" && newDesc === bug.desc){
this.updateDescCallBack(bug.id,newDesc);
}
bug.editState = false;
}
}
}
</script>
<style scoped>
/* item */
table tbody tr:nth-child(odd){
background-color: #eee;
}
table tbody tr:hover{
background-color: #ccc;
}
table tbody tr td:first-child{
color: #f40;
}
td{
border: 1px solid #999;
text-align: center;
padding: 5px 0;
}
.desc {
cursor: pointer;
}
</style>
<template>
<div>
<table>
<thead>
<tr>
<th class="c1">全选<input type="checkbox" v-model="All"/></th>
<th>bug描述</th>
<th class="c2"></th>
</tr>
</thead>
<tbody>
<BugItem v-for="bug in bugList" :key="bug.id" :bug="bug" :updateDescCallBack="updateDescCallBack" :deleteByIdCallBack="deleteByIdCallBack" :modifyResolvedCallBack="modifyResolvedCallBack"></BugItem>
</tbody>
</table>
</div>
</template>
<script>
import BugItem from "./BugItem.vue";
export default {
name : "BugList",
components : {BugItem},
props : ["bugList","modifyResolvedCallBack","deleteByIdCallBack","selectAllRollback","updateDescCallBack"],
methods : {
// selectAll(e){
// // console.log(e.target.checked);
// this.selectAllRollback(e.target.checked);
// }
},
computed : {
count(){
let count = 0;
this.bugList.forEach((bug) => {
if(bug.resolved === true){
count++;
}
});
return count;
},
All : {
get(){
return this.bugList.length === this.count && this.bugList.length > 0;
},
set(value){
this.selectAllRollback(value);
}
}
}
}
</script>
<style scoped>
/* list */
table{
width: 760px;
border-collapse: collapse;
}
table caption{
font-size: 1em;
font-weight: bold;
margin: 1em 0;
}
.c1,.c2{
width: 100px;
}
th {
border: 1px solid #999;
text-align: center;
padding: 5px 0;
}
table thead tr{
background-color: #008c8c;
color: #fff;
}
</style>
<template>
<div>
<textarea cols="105" rows="4" v-model.lazy="desc" placeholder="请输入BUG的描述信息"></textarea>
<br>
<button @click="saveBug()" class="small green button">保存</button>
</div>
</template>
<script>
export default {
name : "BugHeader",
data(){
return {
desc : ""
}
},
methods : {
saveBug()
{
if(this.desc.trim() != ""){
// 获取信息
let id = this.bugList.length + 1;
// 创建Bug对象
let Bug = {id : id,desc : this.desc,resolved : false};
// 添加到bugList数组中
// 不行,不能修改props
// this.bugList.unshift(Bug);
this.saveBugCallBack(Bug);
this.desc = "";
}
}
},
props : ["saveBugCallBack","bugList"]
}
</script>
<style scoped>
/* header */
.header {
margin-bottom: 20px;
margin-top: 20px;
}
</style>
<template>
<div class="footer">
<button @click="clean()" class="small red button">清除已解决</button>
<h3>当前BUG总量{{ bugList.length }}个,已解决{{ resolvedCount }}个</h3>
</div>
</template>
<script>
export default {
name : "BugFooter",
data(){
return {
TNumber : 0,
SNumber : 0
}
},
methods : {
clean(){
// 第一种方式
// this.bugList.forEach((bug) => {
// if(bug.resolved === true){
// this.deleteByIdCallBack(bug.id);
// }
// });
// 第二中方式
this.cleanResolved();
}
},
props : ["bugList","deleteByIdCallBack","cleanResolved"],
computed : {
resolvedCount(){
// 这种是普通的计数器方式实现
// let count = 0;
// this.bugList.forEach((bug) => {
// if(bug.resolved === true){
// count++;
// }
// });
// return count;
// 使用ES6数组的reduce方式对数组条件进行统计
// 回调函数的调用次数和元素数量有关
const count = this.bugList.reduce((a,b) => {
return a + (b.resolved ? 1 : 0);
},0);
return count;
}
}
}
</script>
<style scoped>
/* footer */
.footer{
margin-top: 10px;
}
.footer span{
font-size: 12px;
}
</style>
标签:VUE,CLI,框架,background,id,bugList,rgba,bug,255
From: https://blog.51cto.com/u_16322355/8746952