vue 瀑布流 + elementUI
1.在线预览2 文档结构<el-container id="index"><!-- 点击图片详情弹窗 --><!-- :open="opmethod" --><el-dialog :visible.sync="dialogVisible" :fullscreen="true" custom-class="el-dialog-aa" top="0":show
·
1.在线预览
2 文档结构
<el-container id="index">
<!-- 点击图片详情弹窗 --><!-- :open="opmethod" -->
<el-dialog :visible.sync="dialogVisible" :fullscreen="true" custom-class="el-dialog-aa" top="0"
:show-close="false" @open="opmethod">
<pic-detail ref="detailWin" :picId="picId" @closedialog="closedialog"></pic-detail>
</el-dialog>
<!-- 公共搜索头部,管理页面不显示 -->
<el-header>
<common-header @clickSearch='search'></common-header>
</el-header>
<!-- 主体瀑布流区域,无限滚动 -->
<div class="v-waterfall-content" ref="abc" v-infinite-scroll="getMoreData" infinite-scroll-disabled="disabled"
infinite-scroll-distance="10" style="overflow:auto">
<div v-for="img in waterfallList" :key="img.key" class="v-waterfall-item"
:style="{top:img.top+'px',left:img.left+'px',width:imageWidth+'px',height:img.height}">
<!-- 图片卡片 -->
<el-card shadow="hover" :body-style="{'padding':'0px','border-radius':'10px'}" @click.native="openDialog(img.id)">
<!-- 图片懒加载 -->
<el-image :src='img.src' class='image' :key='img.src' lazy>
<!-- 加载前占位 -->
<div slot="placeholder" class="image-slot">
<div :style="{height:img.height+'px',width:imageWidth + 'px',backgroundColor:img.colour}"></div>
</div>
<!-- 加载失败占位 -->
<div slot="error" class="image-slot">
<div :style="{height:img.height+'px',width:imageWidth + 'px',backgroundColor:img.colour}"></div>
</div>
</el-image>
</el-card>
</div>
</div>
</el-container>
页面布局和UI全部使用的elementUI,很多代码都是抄人家的案例。
使用到的组件有:无限滚动,图片懒加载,图片占位,卡片,图片详情Dialog
3.重点 JS
import CommonHeader from '../components/CommonHeader.vue';
import PicDetail from './pic/PicDetail.vue';
const imgurl = 'http://103.45.251.27:8888/img/';
export default {
name: 'v-waterfall',
components: {
CommonHeader,
PicDetail
},
data() {
return {
//存放计算好的数据
waterfallList: [],
//每一列的宽度
imageWidth: 200,
//多少列
waterfallImgCol: 5,
//右边距
waterfallImgRight: 20,
//下边距
waterfallImgBottom: 10,
//存放瀑布流各个列的高度
waterfallColHeight: [],
imgList: [],
//整体左偏移量,左右相同
colLeft: 0,
currentPage: 1,
//是否还有数据
noMore: false,
//搜索内容
searchKey: '',
//图片详情弹窗可见
dialogVisible: false,
//点击的图片ID
picId:'',
//随机占位色卡的颜色
suijicolour: ['#b4ffe3','#66CDAA','#acc2e6','#d7b0d8','#95abe6','#ffc47b','#b6d288','#f49586','#bcaf7a'],
};
},
created() {
//初始就加载数据
this.getMoreData();
},
mounted() {
//计算可视区域能够容纳的最大列数,向下取整
let fullWidth = this.$refs.abc.clientWidth;
if (fullWidth > 1500) {
this.imageWidth = 240;
} else if (fullWidth < 800) {
this.imageWidth = 170;
}
let maxColNum = Math.floor(fullWidth / (this.imageWidth + this.waterfallImgRight));
console.log('可视宽度:' + fullWidth + ',列数:' + maxColNum);
if (maxColNum == 0) {
maxColNum = 1;
}
let contentWhith = (this.imageWidth + this.waterfallImgRight) * maxColNum;
if ((fullWidth - contentWhith) < (this.imageWidth * 0.8)) {
maxColNum--;
contentWhith = (this.imageWidth + this.waterfallImgRight) * maxColNum;
}
console.log('计算列数:' + maxColNum);
this.waterfallImgCol = maxColNum;
//获取左边距
this.colLeft = (fullWidth - contentWhith) / 2;
console.log('总宽度:' + fullWidth + ',内容宽度:' + contentWhith + '左偏移:' + this.colLeft);
//初始化偏移高度数组
this.waterfallColHeight = new Array(this.waterfallImgCol);
for (let i = 0; i < this.waterfallColHeight.length; i++) {
this.waterfallColHeight[i] = 0;
}
},
methods: {
//搜索,从其他组件传值放到$store中的
search() {
//点击查询重置页数和瀑布流每列高度
this.currentPage = 1;
for (let i = 0; i < this.waterfallColHeight.length; i++) {
this.waterfallColHeight[i] = 0;
}
this.waterfallList = [];
this.getMoreData();
},
// 获取数据
getMoreData() {
//表单数据
let param = {
pageNo: this.currentPage++,
pageSize: 10,
orderBy: 'updateTime desc'
};
let search = this.$store.state.searchText;
console.log('查询参数:' + search);
if (search.trim().length > 0) {
param.title = search.trim();
}
console.log('查询参数:' + JSON.stringify(param));
// if(param.pageNo>10){this.noMore=true;return;}
this.$axios.get('/api/pic/query', {
params: param
}).then(response => {
// console.log('获取数据', response.data);
if (response.data.success) {
if (response.data.data.rows.length == 0) {
this.noMore = true;
} else {
this.imgPreloading(response.data.data.rows);
this.noMore = false;
}
} else {
this.$message.error(response.data.msg);
this.noMore = true;
}
}, response => {
this.$message.error('错误');
this.noMore = true;
});
},
//图片预加载
imgPreloading(moreList) {
let listLen = this.waterfallList.length;
for (let i = 0; i < moreList.length; i++) {
if(moreList[i].imgUrl.indexOf('http') > 0){
continue;
}
let aImg = new Image();
//图片渲染列表,先把高宽和占位颜色赋值直接push到waterfallList,图片的实际url等图片加载上了在赋值
let imgData = {};
imgData.height = this.imageWidth / moreList[i].width * moreList[i].height;
// console.log('第' + i + '张图片的高度是:'+imgData.height );
imgData.id = moreList[i].id;
//获取随机占位背景色
imgData.colour=this.suijicolour[i%9];
this.waterfallList.push(imgData);
aImg.onload = (e) => {
aImg.src = imgurl + moreList[i].imgUrl;
};
this.rankImg(imgData);
imgData.src = imgurl + moreList[i].imgUrl;
}
},
//瀑布流布局核心,计算高度和左偏移
rankImg(imgData) {
let {
imageWidth,
waterfallImgRight,
waterfallImgBottom,
waterfallColHeight,
waterfallImgCol,
colLeft
} = this;
//找出当前最短列的索引
let minIndex = waterfallColHeight.indexOf(Math.min.apply(null, waterfallColHeight));
//获取最短列底部高度,既下一张图片的顶部高度
imgData.top = waterfallColHeight[minIndex];
//计算左侧偏移,最短列索引*(右边距+列宽度)
imgData.left = minIndex * (waterfallImgRight + imageWidth) + colLeft;
//改变当前列高度
waterfallColHeight[minIndex] += imgData.height + waterfallImgBottom;
// console.log(imgData.key + ":" + JSON.stringify(imgData));
// console.log(waterfallColHeight);
},
//打开图片详情
openDialog(picId){
this.picId = picId;
this.dialogVisible = true;
// this.$refs.detailWin.getInfo();
},
opmethod(){
//打开详情页的回调,延迟加载详情页的数据,避免子组件的方法没找到
setTimeout(() => {
this.$refs.detailWin.getInfo();
}, 10);
},
closedialog(){
//关闭弹窗
this.dialogVisible = false;
}
},
computed: {
disabled() {
return this.noMore;
}
}
};
公共搜索头部和图片详情弹窗可以都删掉
执行顺序 :
created 加载数据,
mounted 根据浏览器宽度计算好瀑布流的列数,左右间距
imgPreloading()拿到后端返回的数据,根据图片宽和高设置好占位色卡提前加载,等待图片onload完成赋值真实src
更多推荐
已为社区贡献1条内容
所有评论(0)