刚写完这个表格数据页面,记录下,如果忘了回来翻下。
需求是:表格:1. 数据不写死,数据可随时变化(可增可删);2. 竖着删除数据
第一阶段:数据格式
(1)错误数据格式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #ffffff;
}
ul,
li {
list-style: none;
}
a {
text-decoration: none;
cursor: pointer;
}
.table {
display: flex;
width: 800px;
margin: 100px auto;
}
.table p {
font-size: 18px;
padding-bottom: 20px;
}
.table p:not(:first-child) {
border-top: 2px solid rgba(0,0,0,.1);
}
.table-box:nth-child(2) {
margin: 0 20px;
}
</style>
</head>
<body>
<section id="box" class="table">
<template v-for="item in datas" :key="item.id">
<div class="table-box">
<p class="class-a">{{item.a}}</p>
<p class="class-b">{{item.b}}</p>
<p class="class-d1">{{item.d1}}</p>
<p class="class-d2">{{item.d2}}</p>
<p class="class-d2">{{item.d2}}</p>
<p class="class-d2">{{item.d2}}</p>
</div>
</template>
</section>
<script src="https://lib.baomitu.com/vue/latest/vue.global.min.js"></script>
<script>
const App = {
data() {
return {
datas: [
{
id: 0,
a: 'a',
b: 'b',
c: 'c',
d1: 'd1',
d2: 'd2',
d3: 'd3',
d4: 'd4'
},
{
id: 1,
a: ['aaa', '11'],
b: '/product/b',
c: ['$199', '$200'],
d1: 'ddddd',
d2: 'eeeeee',
d3: 'ttttt',
d4: 'hhhhhh'
},
{
id: 2,
a: ['uuuuu', '6666'],
b: '/product/uuuu',
c: ['$999', '$869'],
d1: 'p1p1p1pp1pppppppppppppppppp',
d2: 'k1k1k1kk1k1kkkkkkkkkkkkkkkkkk哈哈哈哈哈哈哈哈哈哈哈哈',
d3: 'o1o1oo1o1o',
d4: 'r1rr1rr1r1rr1'
}
]
}
},
computed: {
datasLength() {
return this.datas[0].length
},
datasItemLength() {
return this.datas.length
}
},
}
const app = Vue.createApp(App);
app.mount("#box");
</script>
</body>
</html>
这种数据格式有个问题,在循环渲染的时候是写死键的(item.a、item.b、item.c、item.d1、item.d2、item.d3、item.d4),但是这个数据是不确定的,无法知道这个键是什么。
而且这种布局3个div并列,非常明显的一个缺点,不等高。
(2)正解的数据格式:
用 table 进行渲染,3个数据(菜单、第一列,第二列)都会等高,渲染 tr 有数据的 7 行 , td 有数据的 3 列 (即 数组的总长 有 3,每一项数组里的子 有 7 ),循环数据时,用 class 判断 对应的 class-名称,这个是为了添加不同的div添加私有样式 (即 class-a、class-b、class-c、class-d1、class-d2、class-d3、class-d4)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #ffffff;
}
ul,
li {
list-style: none;
}
a {
text-decoration: none;
cursor: pointer;
}
table {
margin: 100px auto;
width: 500px;
}
</style>
</head>
<body>
<section id="box">
<table border="1">
<tr v-for="(item, index) in datasLength">
<td v-for="(coms, cidx) in datasItemLength">
<div class="items-cont" :class="datas[cidx][index].tyep">
{{datas[cidx][index].cont}}
</div>
</td>
</tr>
</table>
</section>
<script src="https://lib.baomitu.com/vue/latest/vue.global.min.js"></script>
<script>
const App = {
data() {
return {
datas: [
[
{ tyep: 'class-a', cont: 'a' },
{ tyep: 'class-b', cont: 'b' },
{ tyep: 'class-c', cont: 'c', },
{ tyep: 'class-d1', cont: 'd1' },
{ tyep: 'class-d2', cont: 'd1' },
{ tyep: 'class-d3', cont: 'd1' },
{ tyep: 'class-d4', cont: 'd1' }
],
[
{ tyep: 'class-a', cont: ['aaa', '11'] },
{ tyep: 'calss-b', cont: '/product/b' },
{ tyep: 'calss-c', cont: ['$199', '$200'] },
{ tyep: 'class-d1', cont: 'ddddd' },
{ tyep: 'class-d2', cont: 'eeeeee' },
{ tyep: 'class-d3', cont: 'ttttt' },
{ tyep: 'class-d4', cont: 'hhhhhh' }
],
[
{ tyep: 'class-a', cont: ['uuuuu', '6666'] },
{ tyep: 'class-b', cont: '/product/uuuu' },
{ tyep: 'class-c', cont: ['$999', '$869'] },
{ tyep: 'class-d1', cont: 'p1p1p1pp1pppppppppppppppppp' },
{ tyep: 'class-d2', cont: 'k1k1k1kk1k1kkkkkkkkkkkkkkkkkk哈哈哈哈哈哈哈哈哈哈哈哈' },
{ tyep: 'class-d3', cont: 'o1o1oo1o1o' },
{ tyep: 'class-d4', cont: 'r1rr1rr1r1rr1' }
]
]
}
},
computed: {
datasLength() {
return this.datas[0].length
},
datasItemLength() {
return this.datas.length
}
},
}
const app = Vue.createApp(App);
app.mount("#box");
</script>
</body>
</html>
第二阶段:精简版代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #ffffff;
}
ul,
li {
list-style: none;
}
a {
text-decoration: none;
cursor: pointer;
}
table {
margin: 100px auto;
width: 500px;
}
</style>
</head>
<body>
<section id="box">
<table border="1">
<tr v-for="(item, index) in datasLength">
<td v-for="(coms, cidx) in datasItemLength">
<!-- <div class="items-cont" :class="datas[cidx][index].tyep">
{{datas[cidx][index].cont}}
</div> -->
<component
:class="datas[cidx][index].tyep"
:is="datas[cidx][index].tyep"
:model="datas[cidx][index]"
:datas="datas"
:cidx="cidx">
</component>
</td>
</tr>
</table>
</section>
<template id="class-a">
<div>{{model.cont}}</div>
</template>
<template id="class-b">
<div>{{model.cont}}</div>
</template>
<template id="class-c">
<div>{{model.cont}}</div>
</template>
<template id="class-d1">
<div>{{model.cont}}</div>
</template>
<template id="class-d2">
<div>{{model.cont}}</div>
</template>
<template id="class-d3">
<div>{{model.cont}}</div>
</template>
<template id="class-d4">
<div>{{model.cont}}</div>
</template>
<script src="https://lib.baomitu.com/vue/latest/vue.global.min.js"></script>
<script>
const App = {
data() {
return {
datas: [
[
{ tyep: 'class-a', cont: 'a' },
{ tyep: 'class-b', cont: 'b' },
{ tyep: 'class-c', cont: 'c', },
{ tyep: 'class-d1', cont: 'd1' },
{ tyep: 'class-d2', cont: 'd1' },
{ tyep: 'class-d3', cont: 'd1' },
{ tyep: 'class-d4', cont: 'd1' }
],
[
{ tyep: 'class-a', cont: ['aaa', '11'] },
{ tyep: 'class-b', cont: '/product/b' },
{ tyep: 'class-c', cont: ['$199', '$200'] },
{ tyep: 'class-d1', cont: 'ddddd' },
{ tyep: 'class-d2', cont: 'eeeeee' },
{ tyep: 'class-d3', cont: 'ttttt' },
{ tyep: 'class-d4', cont: 'hhhhhh' }
],
[
{ tyep: 'class-a', cont: ['uuuuu', '6666'] },
{ tyep: 'class-b', cont: '/product/uuuu' },
{ tyep: 'class-c', cont: ['$999', '$869'] },
{ tyep: 'class-d1', cont: 'p1p1p1pp1pppppppppppppppppp' },
{ tyep: 'class-d2', cont: 'k1k1k1kk1k1kkkkkkkkkkkkkkkkkk哈哈哈哈哈哈哈哈哈哈哈哈' },
{ tyep: 'class-d3', cont: 'o1o1oo1o1o' },
{ tyep: 'class-d4', cont: 'r1rr1rr1r1rr1' }
]
]
}
},
computed: {
datasLength() {
return this.datas[0].length
},
datasItemLength() {
return this.datas.length
}
},
}
const app = Vue.createApp(App);
app.component('class-a', {
props: ['model'],
template: '#class-a',
})
app.component('class-b', {
props: ['model'],
template: '#class-b',
})
app.component('class-c', {
props: ['model'],
template: '#class-c',
})
app.component('class-d1', {
props: ['model'],
template: '#class-d1',
})
app.component('class-d2', {
props: ['model'],
template: '#class-d2',
})
app.component('class-d3', {
props: ['model'],
template: '#class-d3',
})
app.component('class-d4', {
props: ['model'],
template: '#class-d4',
})
app.mount("#box");
</script>
</body>
</html>
第三阶段:添加删除,删除列数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #ffffff;
}
ul,
li {
list-style: none;
}
a {
text-decoration: none;
cursor: pointer;
}
table {
margin: 100px auto;
width: 500px;
}
table tr:first-child td:first-child button {
display: none;
}
</style>
</head>
<body>
<section id="box">
<table border="1">
<tr v-for="(item, index) in datasLength">
<td v-for="(coms, cidx) in datasItemLength">
<!-- <div class="items-cont" :class="datas[cidx][index].tyep">
{{datas[cidx][index].cont}}
</div> -->
<component
:class="datas[cidx][index].tyep"
:is="datas[cidx][index].tyep"
:model="datas[cidx][index]"
:datas="datas"
:cidx="cidx">
</component>
</td>
</tr>
</table>
</section>
<template id="class-a">
<div>
{{model.cont}}
<button @click="remove">删除</button>
</div>
</template>
<template id="class-b">
<div>{{model.cont}}</div>
</template>
<template id="class-c">
<div>{{model.cont}}</div>
</template>
<template id="class-d1">
<div>{{model.cont}}</div>
</template>
<template id="class-d2">
<div>{{model.cont}}</div>
</template>
<template id="class-d3">
<div>{{model.cont}}</div>
</template>
<template id="class-d4">
<div>{{model.cont}}</div>
</template>
<script src="https://lib.baomitu.com/vue/latest/vue.global.min.js"></script>
<script>
const App = {
data() {
return {
datas: [
[
{ tyep: 'class-a', cont: 'a' },
{ tyep: 'class-b', cont: 'b' },
{ tyep: 'class-c', cont: 'c', },
{ tyep: 'class-d1', cont: 'd1' },
{ tyep: 'class-d2', cont: 'd1' },
{ tyep: 'class-d3', cont: 'd1' },
{ tyep: 'class-d4', cont: 'd1' }
],
[
{ tyep: 'class-a', cont: ['aaa', '11'] },
{ tyep: 'class-b', cont: '/product/b' },
{ tyep: 'class-c', cont: ['$199', '$200'] },
{ tyep: 'class-d1', cont: 'ddddd' },
{ tyep: 'class-d2', cont: 'eeeeee' },
{ tyep: 'class-d3', cont: 'ttttt' },
{ tyep: 'class-d4', cont: 'hhhhhh' }
],
[
{ tyep: 'class-a', cont: ['uuuuu', '6666'] },
{ tyep: 'class-b', cont: '/product/uuuu' },
{ tyep: 'class-c', cont: ['$999', '$869'] },
{ tyep: 'class-d1', cont: 'p1p1p1pp1pppppppppppppppppp' },
{ tyep: 'class-d2', cont: 'k1k1k1kk1k1kkkkkkkkkkkkkkkkkk哈哈哈哈哈哈哈哈哈哈哈哈' },
{ tyep: 'class-d3', cont: 'o1o1oo1o1o' },
{ tyep: 'class-d4', cont: 'r1rr1rr1r1rr1' }
]
]
}
},
computed: {
datasLength() {
return this.datas[0].length
},
datasItemLength() {
return this.datas.length
}
},
}
const app = Vue.createApp(App);
app.component('class-a', {
props: ['model', 'datas', 'cidx'],
template: '#class-a',
methods: {
remove() {
this.datas.splice(this.cidx, 1)
}
}
})
app.component('class-b', {
props: ['model'],
template: '#class-b',
})
app.component('class-c', {
props: ['model'],
template: '#class-c',
})
app.component('class-d1', {
props: ['model'],
template: '#class-d1',
})
app.component('class-d2', {
props: ['model'],
template: '#class-d2',
})
app.component('class-d3', {
props: ['model'],
template: '#class-d3',
})
app.component('class-d4', {
props: ['model'],
template: '#class-d4',
})
app.mount("#box");
</script>
</body>
</html>