vue多个虚拟列表(两个为例)+标签组件

本文档展示了如何实现一个虚拟列表,包括一个带有自定义标签的组件。组件包括姓名、年份、地址和简介,还提到了性别图片的优化,建议添加点击展开事件。同时,虚拟列表通过分段显示大量数据,提高滚动性能。文章还介绍了如何处理两个组件的滚动事件,确保同步滚动。代码示例中涉及Vue.js和CSS样式设计。
摘要由CSDN通过智能技术生成

自定义标签组件,未添加文本溢出 点击展开事件,有空加上,若添加悬停展开,可在.intro添加:hover悬停事件,但为自动调整高度,待改进,性别图片可以进一步处理,可以添加传入sex选择性别图片,图片见下方:

<template>
<div  class="label">
    <div class="left">
        <img :src="url" alt="未加载" class="image" >
    </div>
    <div class="right">
        <div class="top"> 
            <p class="data">{{name}}</p>
            <p class="year">{{year}}</p>
            <img src="../../static/image/male.png" class="sex"></img>
            <p class="address">{{address}}</p>
        </div>
        <div class="segmentation"></div>
        <div class="bottom">
        <p class="intro">{{introduction}}</p>
        </div>
    </div>
</div>
</template>
<script>
export default {
    props:{
        url:{
            type:String,
            default:()=>{
                return " "
            }
        },
        year:{
            type:Number,
            default:()=>{
                return 0
            }

        },
        introduction:{
            type:String,
            default:()=>{
                return "hello world ";
            }
        },
        name:{
            type:String,
            default:()=>{
                return "姓名";
            }
        },
        address:{
            type:String,
            default:()=>{
                return "省份/市"
            }
        }

    },
    data(){
        return{
            
        }
    },
    
    created(){
        //console.log(this.url);

    },
    methods:{

    }
    
}
</script>

<style>
.label{
    margin-bottom: 9px;
    width:500px;
    display:flex;
}
.left{
    display: inline;
    float: left;
    width: 100px;
    height: 101px;
    margin-right: 20px;
}
.image{
    height: 100px;
    width: 100px;
    /* 图片在p中垂直居中 */
    vertical-align: middle;
    /* 圆形 */
    border-radius: 100%;

}
.segmentation{
    /* 分割线 */
    height: 1px;
    /* border: 1px solid #909399; */
    background-color: #909399;
}
.right{
    width:300px;
    height: 101px;
}
.top{
    height: 50px;
    width:300px;
    text-align: left;
    display: flex;
    display: -webkit-flex;
    align-items: center;

}
.bottom{
    height: 50px;
    width: 300px;
}
.data{
    line-height: 50px;
    height: 50px;
    width: 100px;
    display: inline-block;
    text-align: left;

}
.year{
    margin-right: 25px;

}
.sex{
    width: 25px;
    height: 25px;
    vertical-align: center;
    
}
.address{
    margin-left: 25px;
}
.intro{
    height: 50px;
    text-overflow: ellipsis;
    overflow: hidden;
    /* 限制显示两行,溢出隐藏 */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

</style>

虚拟列表,两个组件绑定同一个滚动事件(后来发现多次一举,本文的还不如单独写两个事件)绑定同一个事件可以传入点击参数e,e的target及src都可以查看点击的是哪一个组件,两个模块一个是上篇文章虚拟表格,一个是基于标签的虚拟列表,后一个采用三个div实现,一个大的div包含两个小的div,一个小的div隐藏,高度为所有标签总高度,以此生成相应高度的滚动条,另一个小的div高度设为显示高度(显示标签数*单个标签高度,最好显示高度稍微小于内容高度,这样使用较为流畅),后一个div进行吸顶灯,采用粘性定位或者绝对定位+偏移,粘性定位不稳定,绝对定位要动态计算偏移量,代码仅供参考:

<template>
<div style="display:flex">
    <div id="tableContain" class="contain" ref="contain"  @scroll="scrollListener">
        <div class="table1" ref="table1"></div>
            <el-table
            ref="showTable"
            class="showTable"
            :data="tableData"
            height="850px"
            border
            style="width: 750px">
                <el-table-column
                prop="index"
                label="序号"
                width="180">
                </el-table-column>
                <el-table-column
                prop="date"
                label="日期"
                width="180">
                </el-table-column>
                <el-table-column
                prop="name"
                label="姓名"
                width="180">
                </el-table-column>
                <el-table-column
                prop="address"
                label="地址">
                </el-table-column>
            </el-table>
    </div>
    <div  id="labelContain" class="contain" style="margin-left:20px" ref="labelContain" @scroll="scrollListener">
        <div class="table1" ref="label1"></div>
        <div class="showTable" ref="showLable">
            <data-label :url="url" :year="item.num" v-for="item in labelData" :key="item.num"></data-label>
        </div>
    
    </div>
    </div>
</template>

<script>
import dataLabel from "./dataLabel";
export default {
  components: { dataLabel },
    data(){
        return {
            rowNum:20,
            tableData:[{
                index:1,
                date:"周一",
                name:"zxy",
                address:"cdut"
            }],
            list:[],
            rowHeight:40,
            labelHeight:100,
            labelData:[{num:0,url:"https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"}],

            strat:0,
            end:20,
            labelNum:10,
            url:"https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png",
            showList:[],
            //url:"../../static/image/5.png",
        }
    },
    created(){
        for(var i=0;i<1000;i++){
            this.list.push({
                index:i,
                date:"周一",
                name:"zxy",
                address:"cdut"});
            this.showList.push({num:i,url:this.url});      
        }
        //计算滚动容器高度
         console.log(this.list);   
         console.log(this.showList); 

    },
    mounted(){
            this.$refs.contain.style.height = this.rowHeight * this.rowNum + 'px';
            //计算总的数据需要的高度,构造滚动条高度
            this.$refs.table1.style.height = this.rowHeight * this.list.length + 'px';

            this.$refs.labelContain.style.height = this.labelHeight * this.labelNum + 'px';
            this.$refs.label1.style.height = this.labelHeight * this.showList.length + 'px';
            

            this.$refs.contain.addEventListener("scroll",this.scrollListener);
            this.$refs.labelContain.addEventListener("scroll",this.scrollListener);
    },
    methods:{          
            scrollListener(e){       
                //console.log(e);                                                            
                //获取滚动高度
                let scrollTop = e.target.scrollTop;
                //开始的数组索引
                
                
                //绝对定位对相对定位的偏移量
                //this.$refs.showTable.style.top = this.start * this.rowHeight + 'px';
                
                // console.log(e.target);
                // console.log(e.target.id);
                if(e.target.id=="tableContain"){
                    this.start = Math.floor(scrollTop / this.rowHeight);
                    //结束索引
                    this.end = this.start + this.rowNum;
                    this.tableData=this.list.slice(this.start, this.end);
                    this.$refs.showTable.style.top = this.start * this.labelHeight + 'px';
                }else if(e.target.id=="labelContain"){
                    this.start = Math.floor(scrollTop / this.labelHeight);
                    //结束索引
                    this.end = this.start + this.labelNum;
                    this.labelData=this.showList.slice(this.start, this.end);
                    //绝对定位对相对定位的偏移量
                    this.$refs.showLable.style.top = this.start * this.labelHeight + 'px';
                    //console.log(this.labelData);
                    
                }
                console.log("show:  "+this.start+" "+this.end);
                
            }

    }
    
}

</script>

<style>
.contain{
    overflow: auto;
    position: relative;
    height:900px;
    width:800px;
    border: 1px solid #c1c1c1;
}
.table1{
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    z-index: -1; 
}
.el-table__row{
    height:40px;
}
.showTable{
    left: 0;
    right: 0;
    top: 0;
    position: absolute;
}
</style>

效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值