Vue uses Bootstrap, axios and lifecycle functions to achieve list effects

1. Project construction

1.1 Use vist to create a vue project, import bootstrap, axios package

npm init vite-app table-demo
cd table-demo
npm i
npm i axios bootstrap

insert image description here
Then delete all the default styles of vue

1.2 Create a background file

Create a new folder, enter the command line to initialize, and then create server.js in it

mkdir table-demo-server
cd table-demo-server
npm init -y
npm i express
node server

insert image description here
The data comes from the background, we simulate a background effect below, and expose the goodData object to the outside world

const express=require('express')
//引入express
const app=express()
app.all("*", function (req, res, next) {
    
    
    //设置允许跨域的域名,*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin", "*");
    //允许的header类型
    res.header("Access-Control-Allow-Headers", "content-type");
    //跨域允许的请求方式
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
    if (req.method.toLowerCase() == 'options')
        res.send(200);  //让options尝试请求快速结束
    else
        next();
})
const goodData={
    
    "status":0,"message":"获取商品列表成功","data":[{
    
    "id":1,"goods_name":"Teenmix/天美意夏季专柜同款金色布女鞋6YF18BT6","goods_price":298,"tags":["舒适","透气"],"inputVisible":false,"inputValue":""},{
    
    "id":2,"goods_name":"奥休斯(all shoes) 冬季保暖女士休闲雪地靴 舒适加绒防水短靴 防滑棉鞋子","goods_price":89,"tags":["保暖","防滑"],"inputVisible":false,"inputValue":""},{
    
    "id":3,"goods_name":"初语秋冬新款毛衣女 套头宽松针织衫简约插肩袖上衣","goods_price":199,"tags":["秋冬","毛衣"],"inputVisible":false,"inputValue":""},{
    
    "id":4,"goods_name":"佐露絲蕾丝衫女2020春秋装新款大码女装衬衫上衣雪纺衫韩版打底衫长袖","goods_price":19,"tags":["雪纺衫","打底"],"inputVisible":false,"inputValue":""},{
    
    "id":5,"goods_name":"熙世界中长款长袖圆领毛衣女2022秋装新款假两件连衣裙女107SL170","goods_price":178,"tags":["圆领","连衣裙"],"inputVisible":false,"inputValue":""},{
    
    "id":6,"goods_name":"烟花烫2021秋季装新品女装简约修身显瘦七分袖欧根纱连衣裙 花央","goods_price":282,"tags":["秋季新品","显瘦"],"inputVisible":false,"inputValue":""},{
    
    "id":7,"goods_name":"韩都衣舍2021韩版女装秋装新宽松显瘦纯色系带长袖衬衫NG8201","goods_price":128,"tags":["韩都衣舍","长袖衬衫"],"inputVisible":false,"inputValue":""},{
    
    "id":8,"goods_name":"预售纤莉秀大码女装胖妹妹秋装2020新款圆领百搭绣花胖mm休闲套头卫衣","goods_price":128,"tags":["预售","卫衣"],"inputVisible":false,"inputValue":""},{
    
    "id":9,"goods_name":"莎密2022夏改良旗袍裙连衣裙修身复古时尚日常短款礼服旗袍","goods_price":128,"tags":["莎密","礼服"],"inputVisible":false,"inputValue":""},{
    
    "id":10,"goods_name":"南极人秋冬韩版七彩棉加绒加厚一体保暖打底裤p7011","goods_price":128,"tags":["南极人","打底裤"],"inputVisible":false,"inputValue":""}]}
app.get('/goodsData',(req,res)=>{
    
    
    res.send(goodData)
})
app.listen(4000,()=>console.log('app is running at port 4000...'))

node serverRun it to see if it is successful. The method of inspection is to enter in the browser to http://localhost:4000/goodsDatacheck the effect first, and I will analyze it later

insert image description here

2. Foreground file

Go directly to the code and analyze it

2.1 Parent component - App.vue

<template>
<!--    .container>.row>.col-md-12>h1+hr+table.table-->
    <div class="container">
        <div class="row">
            <div class="col-md-12">
                <h1>App根组件</h1>
                <hr>
                <MyTable :data="goodsList">
                    <template #theader>
                        <th>序号</th>
                        <th>商品名称</th>
                        <th>价格</th>
                        <th>标签</th>
                        <th>操作</th>
                    </template>
                    <template #tbody="{row,index}">
<!--                        接收父级传来的row和index-->
                        <td>{
   
   {index+1}}</td>
                        <td>{
   
   {row.goods_name}}</td>
                        <td>{
   
   {row.goods_price}}</td>
                        <td>
<!--                            {
    
    {row.tags}}-->
                            <span aaa class="badge btn-warning text-dark" v-for="item in row.tags" :key="item">
                                {
   
   {item}}
                            </span>
                        </td>
                        <td>
                            <button class="btn btn-danger btn-sn">删除</button>
                        </td>
                    </template>
                </MyTable>
            </div>
        </div>
    </div>
    <MyTable :data="aaa">
        <template #theader>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
        </template>
        <template #tbody="{row,index}">
            <td>{
   
   {index+1}}</td>
            <td>{
   
   {row.name}}</td>
            <td>{
   
   {row.age}}</td>
        </template>
    </MyTable>

</template>

<script>
    import axios from 'axios'
    //axios跟后台要数据功能
    import MyTable from "./components/my-table/MyTable.vue";
    export default {
      
      
        name: 'App',
        components: {
      
      
            MyTable
        },
        data() {
      
      
            return {
      
      
                goodsList: [],
                aaa:[
                    {
      
      id:0,name:'小明',age:18},
                    {
      
      id:0,name:'小红',age:18},
                    {
      
      id:0,name:'小刚',age:18},
                ]
            }
        },
        created() {
      
       //生命周期函数
            this.getGoodsData()
        },
        methods:{
      
      
            async getGoodsData(){
      
      
                const result = await axios.get('http://localhost:4000/goodsdata')
                console.log(result.data.data)
                this.goodsList = result.data.data
            }
        }
    }
</script>
<style>
     .text-dark[aaa]{
      
      margin-right: 10px}
</style>

2.1.1 Flow direction of parent component data

Lines 59-69: data() returns two data streams goodlistand aaa
we will ask, isn’t the goodlist empty? Why is there data in it?
Let's look down at lines 72-79. We use getGoodsData()the method to find the data from the background and assign it to the goodlist. Although the goodlist is not directly assigned in the code, there is actually data in it. which
asyncis an asynchronous operation

Lines 51 and 57: import and register axios

Line 53: Introduce subcomponent Son.vue

Line 8: We will bind goodsListwith :data, and the subcomponent can get the value of goodList as long as it is introduced using prop. The same is true for line 35

#headerLines 9 and 16: Two slots are inserted 语法糖, which is equivalent to v-slot:header, #header and #body call the slots of subcomponents respectively. It is worth mentioning here that line 16 #tbody is followed by two values ​​{row, index}, detailed in the subcomponent

Lines 23 and 82: a special symbol such as aaa is added to the span tag. There are multiple elements, so it is displayed in a loop, and a css style is set for it to make the elements separated by a certain distance.

Line 35: We found that aaait is also bound :data, and goodsList is also bound: data, which shows that the parent component reuses a child component, but why is the displayed content different in the end? Because the format of the value passed by the parent component to the child component is the same, but the value is different, which means that the child component is just a shell, and the content is filled in by the parent component

2.2 Subcomponent-Son.vue

<template>
    <table class="table table-responsive table-striped">
        <thead>
<!--        组件的复用性-->
        <tr>
            <slot name="theader"></slot>
        </tr>
        </thead>
        <tbody>
        <tr v-for="(item,index) in data" :key="item.id">
            <slot name="tbody" :row="item" :index="index">
            </slot>
        </tr>
        </tbody>
    </table>

</template>

<script>
    export default {
      
      
        name: "MyTable",
        props:{
      
      
            data:{
      
      
                type:Array,
                required:true,
                default:[]
            }
        }
    }
</script>

<style scoped>

</style>

2.2.1 Flow direction of subcomponent data

Lines 22-28: props gets the data of the parent component and sets the validation format

Line 10, set the data in the loop data, v-for="(item,index) there are two parameters here, itemwhich are the main body of the data and indexthe index of the data

Lines 6 and 11: two slots serving the parent component. It is worth mentioning that line 11 corresponds to line 16 of the parent component and sets two parameters.

3. Background file server.js

Let me put the background code again, it looks more convenient

const express=require('express')

const app=express()

app.all("*", function (req, res, next) {
    
    
    //设置允许跨域的域名,*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin", "*");
    //允许的header类型
    res.header("Access-Control-Allow-Headers", "content-type");
    //跨域允许的请求方式
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
    if (req.method.toLowerCase() == 'options')
        res.send(200);  //让options尝试请求快速结束
    else
        next();
})


const goodData={
    
    "status":0,"message":"获取商品列表成功","data":[{
    
    "id":1,"goods_name":"Teenmix/天美意夏季专柜同款金色布女鞋6YF18BT6","goods_price":298,"tags":["舒适","透气"],"inputVisible":false,"inputValue":""},{
    
    "id":2,"goods_name":"奥休斯(all shoes) 冬季保暖女士休闲雪地靴 舒适加绒防水短靴 防滑棉鞋子","goods_price":89,"tags":["保暖","防滑"],"inputVisible":false,"inputValue":""},{
    
    "id":3,"goods_name":"初语秋冬新款毛衣女 套头宽松针织衫简约插肩袖上衣","goods_price":199,"tags":["秋冬","毛衣"],"inputVisible":false,"inputValue":""},{
    
    "id":4,"goods_name":"佐露絲蕾丝衫女2020春秋装新款大码女装衬衫上衣雪纺衫韩版打底衫长袖","goods_price":19,"tags":["雪纺衫","打底"],"inputVisible":false,"inputValue":""},{
    
    "id":5,"goods_name":"熙世界中长款长袖圆领毛衣女2022秋装新款假两件连衣裙女107SL170","goods_price":178,"tags":["圆领","连衣裙"],"inputVisible":false,"inputValue":""},{
    
    "id":6,"goods_name":"烟花烫2021秋季装新品女装简约修身显瘦七分袖欧根纱连衣裙 花央","goods_price":282,"tags":["秋季新品","显瘦"],"inputVisible":false,"inputValue":""},{
    
    "id":7,"goods_name":"韩都衣舍2021韩版女装秋装新宽松显瘦纯色系带长袖衬衫NG8201","goods_price":128,"tags":["韩都衣舍","长袖衬衫"],"inputVisible":false,"inputValue":""},{
    
    "id":8,"goods_name":"预售纤莉秀大码女装胖妹妹秋装2020新款圆领百搭绣花胖mm休闲套头卫衣","goods_price":128,"tags":["预售","卫衣"],"inputVisible":false,"inputValue":""},{
    
    "id":9,"goods_name":"莎密2022夏改良旗袍裙连衣裙修身复古时尚日常短款礼服旗袍","goods_price":128,"tags":["莎密","礼服"],"inputVisible":false,"inputValue":""},{
    
    "id":10,"goods_name":"南极人秋冬韩版七彩棉加绒加厚一体保暖打底裤p7011","goods_price":128,"tags":["南极人","打底裤"],"inputVisible":false,"inputValue":""}]}
app.get('/goodsData',(req,res)=>{
    
    
    res.send(goodData)
})

app.listen(4000,()=>console.log('app is running at port 4000...'))

3.1 The background is open to the outside world

Lines 5-16 are very important to solve cross-domain problems.
Lines 19-22: Do you remember the empty space before goodList[]? It is obviously empty but has a value. This is the root of goodList, and goodsData is assigned to goodList

4. Effect

insert image description here

Guess you like

Origin blog.csdn.net/weixin_52249641/article/details/124144246