表格数据不固定渲染

95 阅读1分钟

刚写完这个表格数据页面,记录下,如果忘了回来翻下。

需求是:表格:1. 数据不写死,数据可随时变化(可增可删);2. 竖着删除数据

微信图片_20230420164344.png

Snipaste_2023-04-21_10-45-37.png

第一阶段:数据格式

(1)错误数据格式:

Snipaste_2023-04-20_16-54-45.png微信图片_20230421093245.png

<!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),但是这个数据是不确定的,无法知道这个键是什么

微信图片_20230421093613.png 而且这种布局3个div并列,非常明显的一个缺点,不等高。

(2)正解的数据格式:
Snipaste_2023-04-21_10-02-15.png Snipaste_2023-04-21_09-47-12.png Snipaste_2023-04-21_10-04-45.png

用 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>

第三阶段:添加删除,删除列数据

Snipaste_2023-04-21_10-45-37.png

<!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>