实战案例之瀑布流效果

2023-10-30

前言

从服务器获取需要展示的数据(图片大小不一致,大中,中,小), 

每次从服务器获取三条数据,依次插入到三列中[每一列的宽度是一样的] 弊端:可能导致某一列特别的高,而某一列特别的矮

瀑布流:需求分析

  • 最终期望三列的高度差距应该是不大的才可以,
  • 最开始数据绑定完,不去加载真实的图片(提高页面首次渲染速度),等到数据绑定完成后,开始加载真实图片,(只加载可视窗口中的),随着页面的滚动在去加载出现在可视窗口中的,
  • 当滚动到页面底部,在从服务器获取50条数据,继续绑定到页面中实现下拉加载更多的效果

思路:第一次取出三条数据,直接按顺序,依次插入到三列中即可,第二次取出三条数据,最高的数据应该插入到最矮的列中

三条数据排序 小-->大,三列按高度排序 大-->小

下拉加载更多: 真实页面高度scrollHeight  卷去的高度scrollTop 一屏幕高度

一屏的高度+卷去的高度=真实页面高度,到底步了可以加载更多了

主体结构

三列             : 图片占位盒子          底部盒子

<body>
	<div class="container clearfix">
		<div class="column">
			<!-- <div class="card">
				<a href="#">
					<div class="lazyImageBox" style="height: 180px;">
						<img src="" alt="" data-image="images/1.jpg">
					</div>
					<p>泰勒·斯威夫特(Taylor Swift),1989年12月13日出生于美国宾州,美国歌手、演员。2006年出道,同年发行专辑《泰勒·斯威夫特》,该专辑获得美国唱片业协会的白金唱片认证</p>
				</a>
			</div> -->
		</div>
		<div class="column"></div>
		<div class="column"></div>
	</div>
	<div class="loadMore"></div>

	<!-- IMPORT JS -->
	<script src="js/index.js"></script>
</body>

css样式

每一列的宽度为240 注意;有10的padding值 图片大小实际为230

 height: xxx;  如果是需要进行图片延迟加载,在图片不显示的时候,我们要让盒子的高度等于图片的高度,这样才能把盒子撑开(服务器返回给我们的数据中,一定要包含图片的高度和宽度)

html,
body {
	background: #D6D7DB;
}

.container {
	box-sizing: border-box;
	margin: 20px auto;
	width: 760px;
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
}

.container .column {
	box-sizing: border-box;
	width: 240px;
}

.card {
	margin-bottom: 10px;
	padding: 5px;
	background: #FFF;
	box-shadow: 3px 3px 10px 0 #222;
}

.card a {
	display: block;
}

.card a .lazyImageBox {
	/* height: xxx;  如果是需要进行图片延迟加载,在图片不显示的时候,我们要让盒子的高度等于图片的高度,这样才能把盒子撑开(服务器返回给我们的数据中,一定要包含图片的高度和宽度) */
	background: url("../images/default.gif") no-repeat center center #F4F4F4;
	overflow: hidden;
}

.card a .lazyImageBox img {
	width: 100%;
	opacity: 0;
	transition: opacity .3s;
}

.card a p {
	margin-top: 5px;
	color: #000;
	font-size: 12px;
	line-height: 20px;
}

.loadMore {
	height: 100px;
}

JS

 false:同步获取数据「当前数据没有获取到之前,其余的事情是不进行处理的」,但是真实项目中都应该用异步获取,再基于promise/async/await等异步方案进行管理

 注意:基于VSCODE预览的项目的时候,不能再使用OPEN IN BROWSER这种模式了,因为这种模式是file://协议,不支持AJAX的请求;我们可以安装Live Server插件,基于Open With Live Server来预览,这样就可以了!!这种模式会再本地创建一个Web服务 http://127.0.0.1:5500/,基于这个服务就可以访问本地的数据了!!

扫盲

  •  JSON.stringify:把JSON格式的对象(对象)变为JSON格式字符串,
  • JSON.parse:把JSON格式的字符串变为JSON格式的对象(对象)

JSON数据格式:常用于客户端和服务器端的数据获取

相对于普通对象来讲,JSON格式的对象也是对象,只不过会把属性名都基于“”包起来而已

       //JSON格式对象
        let obj = {
            "name": "lisa",
            "age": 12
        };
        // JSON.stringify: 把JSON格式的对象(对象)变为JSON格式字符串
        console.log(JSON.stringify(obj));

        // JSON格式对象变为字符串后,称之为JSON格式的字符串
        let str = '{"name":"lisa","age":12}';
        // JSON.parse:把JSON格式的字符串变为JSON格式的对象(对象)
        console.log(JSON.parse(str));

数组排序

sort:b-a降序,a-b升序

        // 数组排序
        let arr = [10, 13, 24, 5];
        arr.sort((a, b) => {
            // b 当前循环这一项
            // a 当前这一项的后一项
            // 返回一个小于零的值,则a/b两项交换位置
            return b - a;
        });
        console.log(arr);

代码


// 节流函数
function throttle(func, wait = 500) {
    let timer = null,
        previous = 0;
    return function anonymous(...params) {
        let now = new Date(),
            remaining = wait - (now - previous);
        if (remaining <= 0) {
            clearTimeout(timer);
            timer = null;
            previous = now;
            func.call(this, ...params);
        } else if (!timer) {
            timer = setTimeout(() => {
                clearTimeout(timer);
                timer = null;
                previous = new Date();
                func.call(this, ...params);
            }, remaining);
        }
    };
}

let container = document.querySelector('.container'),
    columns = document.querySelectorAll('.column'),
    lazyImageBoxs = [];
//把类数组集合变为数组集合,使用数组方法
columns = Array.from(columns)

//基于ajax服务器获取数据
const queryData = () => {
    let data = [];
    let xhr = new XMLHttpRequest;
    xhr.open('GET', '../data.json', false);
    xhr.onreadystatechange = () => {
        if (xhr.readyState === 4 && xhr.status === 200) {
            //JSO格式字符串
            data = JSON.parse(xhr.response)
        }
    }
    xhr.send();
    return data;
};

//根据获取的数据完成页面的数据绑定
const bindHTML = data => {
    // 页面渲染的时候,图片按照宽230px渲染,服务器返回的图片大小:宽300*高433,所以为了保证图片不变形,我们需要把获取的数据中的图片宽高,按照真实的比例进行缩放  
    // A->渲染  B->服务器  A-W/A-H=B-W/B-H => A-H=A-W/(B-W/B-H)
    data = data.map(item => {
        let AW = 230,
            BW = item.width,
            BH = item.height,
            AH = AW / (BW / BH);
        item.width = AW;
        item.height = AH;
        return item;
    });

    // 每三个为一组进行数据遍历
    for (let i = 0; i < data.length; i += 3) {
        // group:当前循环获取的三条数据&把数据按照图片的高度排序 小->大
        let group = data.slice(i, i + 3);
        group.sort((a, b) => a.height - b.height);

        // 把当前页面中的三列按照高度进行排序 大->小
        columns.sort((a, b) => b.offsetHeight - a.offsetHeight);

        // 按照排好序的结果,分别把数据插入到指定的列中
        group.forEach((item, index) => {
            // 根据当前数据动态创建一个CARD
            let card = document.createElement('div');
            card.className = 'card';
            card.innerHTML = `<a href="${item.link}">
                <div class="lazyImageBox" style="height: ${item.height}px;">
                    <img src="" alt="" data-image="${item.pic}">
                </div>
                <p>${item.title}</p>
            </a>`;

            // 创建的CARD追加到指定的列中
            columns[index].appendChild(card);
            // 数据绑定完成后,才可以获取到所有图片延迟加载所在的盒子
            lazyImageBoxs = Array.from(container.querySelectorAll('.lazyImageBox'));
        });
    }
}

//单张图片的延迟加载
const lazyImgFunc = lazyImageBox => {
    let img = lazyImageBox.querySelector('img'),
        dataImage = img.getAttribute('data-image');
    img.onload = () => {
        img.style.opacity = 1;
    };
    img.src = dataImage;
    lazyImageBox.isLoad = true;
};
// 依次遍历每一个图片所在的盒子,所有符合条件的(出现在视口中的)都去做延迟加载
const lazyImageBoxsFunc = () => {
    let B = document.documentElement.clientHeight;
    lazyImageBoxs.forEach(lazyImageBox => {
        if (lazyImageBox.isLoad) return;
        let A = lazyImageBox.getBoundingClientRect().bottom;
        if (A <= B) {
            lazyImgFunc(lazyImageBox);
        }
    });
};
 开始加载页面:获取数据、数据绑定、等待1000MS(再或者页面滚动的时候)做图片延迟加载
let data = queryData();
bindHTML(data);
setTimeout(lazyImageBoxsFunc, 1000)
window.onscroll = throttle(() => {
    // 图片延迟加载
    lazyImageBoxsFunc();

    // 下拉加载更多数据
    let HTML = document.documentElement;
    if ((HTML.clientHeight + HTML.scrollTop + 100) >= HTML.scrollHeight) {
        let data = queryData();
        bindHTML(data);
    }
});

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实战案例之瀑布流效果 的相关文章

  • 将鼠标悬停时的鼠标光标更改为锚状样式

    如果我将鼠标悬停在div鼠标光标将更改为 HTML 锚点中的光标 我怎样才能做到这一点 假设你的div has an id myDiv 将以下内容添加到您的 CSS 中 这cursor pointer指定光标应与用于锚点 超链接 的手形图标
  • socket.io 的良好初学者教程? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Eslint errorring 导入没有扩展名的 jsx

    我正在尝试在 es6 中导入 jsx 文件而不需要 jsx 扩展名 import LoginErrorDialog from LoginErrorDialogView Not import LoginErrorDialog from Log
  • 如何修改每个JSON对象javascript

    我想修改里面的每个 JSON 值cooldown object cooldown user 1 This user2 0 This 在 Javascript 中使用 for 语句 我研究了好几个小时 只找到了内部的 blocks Edit
  • 如何在react-bootstrap中禁用表单提交的

    在下面的代码片段中 我有许多文本类型的输入表单 如果用户点击 我似乎会得到相同的合成事件 就像他们按下提交按钮一样 我想忽略作为表单提交 只允许一个人按下 提交 按钮 我删除了一些表单组以减少示例 在所有情况下 按钮或 ENTER 键 e
  • 如何将内联 JavaScript 与 Express/Node.js 中动态生成的内容分开?

    对于具有几年 Web 开发经验但没有找到答案的人来说 这是一个有点菜鸟的问题程序员堆栈交换 or Google 我决定在这里问一下 我在用Express网络框架Node js 但这个问题并不特定于任何 Web 框架或编程语言 以下是从数据库
  • 带有淘汰赛js的隐形recaptcha

    我正在完成隐形验证码 但我在实现它时遇到问题 谷歌开发人员页面中的代码显示它应该是这样的
  • 可以在初始 DOM 解析期间/之前修改 DOM 吗?

    是否可以在初始 DOM 解析期间或之前修改 DOM 或者我是否必须等到 DOM 被解析和构建之后才能与其交互 更具体地说 是否有可能阻止 DOM 中的脚本元素使用用户脚本 内容脚本或 Chrome 或 Firefox 中的类似脚本运行 在解
  • Bootstrap按钮加载+Ajax

    我正在使用 Twitter Bootstrap 的按钮加载状态 http twitter github com bootstrap javascript html buttons http twitter github com bootst
  • 如何将函数附加到弹出窗口关闭事件(Twitter Bootstrap)

    我做了一些搜索 但我只能认为我可以将事件附加到导致其关闭的按钮 https stackoverflow com questions 13205103 attach event handler to button in twitter boo
  • 尝试将数据存储在点击器网站中

    我正在尝试存储一个名为的变量score无论何时刷新 您都会一次又一次地使用它 我不明白的是它的代码是什么 我尝试了一些方法 但似乎都不起作用 这是我的答题器网站 但是当我尝试使用 JavaScript 来存储它时 它不起作用window o
  • 检查 jQuery 1.7 中是否存在基于文本的选择选项

    所以我有以下 HTML 片段
  • DataTables row.add 到特定索引

    我正在替换这样的行项目 var targetRow entity row dataTable targetRow closest table dataTable DataTable dataTable row targetRow remov
  • 将 UMD Javascript 模块导入浏览器

    你好 我正在对 RxJS 进行一些研究 我可以通过在浏览器中引用它来使用该库 如下所示 它使用全局对象命名空间变量 Rx 导入 我可以制作可观察的东西并做所有有趣的事情 当我将 src 更改为指向最新的 UMD 文件时 一切都会崩溃 如下所
  • 有没有办法在 onclick 触发时禁用 iPad/iPhone 上的闪烁/闪烁?

    所以我有一个有 onclick 事件的区域 在常规浏览器上单击时 它不会显示任何视觉变化 但在 iPad iPhone 上单击时 它会闪烁 闪烁 有什么办法可以阻止它在 iPad iPhone 上执行此操作吗 这是一个与我正在做的类似的示例
  • Vuejs 2:去抖动不适用于手表选项

    当我在 VueJs 中反跳此函数时 如果我提供毫秒数作为原语 它就可以正常工作 但是 如果我将其提供为对 prop 的引用 它会忽略它 这是道具的缩写版本 props debounce type Number default 500 这是不
  • Vue 和 Vuex:处理依赖的计算属性

    我的应用程序是一个使用 Vuex 在 Vue 中构建的精简电子表格 关键组件是TableCollection Table and Row The TableCollection有一个包含多个的数组Table对象 每个Table有一个包含多个
  • 代码镜像错误:未捕获错误:扩展集中无法识别扩展值([对象对象])

    全部 我目前正在从事一个React Electron项目 该项目的目标是完成一个Markdown编辑器 当我配置codemirror 该程序报告错误说 Uncaught Error Unrecognized extension value
  • Javascript - 水波纹效果

    我需要 JS 上的脚本 它将以 水波纹 样式更改 images html 抱歉 6MB GIF 文件 http fcuunited ru temp listening2 gif http fcunited ru temp listening
  • 使用 MongoDB 和 Nodejs 插入和查询日期

    我需要一些帮助在 mongodb 和 nodejs 中按日期查找记录 我将日期添加到抓取脚本中的 json 对象 如下所示 jsonObj last updated new Date 该对象被插入到 mongodb 中 我可以看到如下 la

随机推荐

  • matplotlib中堆积图、分块图、气泡图的绘制

    本文介绍matplotlib中堆积图 分块图 气泡图的绘制 堆积图的绘制 堆积图常用于综合展示不同分类的指标趋势以及它们的总和的趋势 比如说 我们想看一下5名同学期末的总分情况 同时 我们又想看一下这5名同学的各科成绩以及它们各自的占比 这
  • uni-app——小程序实现本地图片的上传以及身份证的智能识别

    文章目录 前言 一 示例图 二 实现过程 1 完成提交图片的api地址 2 获取本地图片 3 将本地图片上传至开发者服务器 三 具体实现代码 四 身份证的智能识别 总结 前言 上传本地图片的功能很常见 那么具体该如何实现呢 一 示例图 二
  • 顶尖程序员的五种思维模式

    一 勇于研究你不懂的代码 通过研究不同的代码 从而熟悉不同的代码结构和设计模式 二 精通代码调试 几乎所有的代码都不是一遍写好 学会怎么去调试代码 三 重视能够节约时间的工具 工具是很重要的 它们能帮我们节省大量的时间 四 优化你的迭代速度
  • python调用自己写的py文件

    目录 python如何调用自己写的py文件呢 如果是不同目录怎么调用呢 如果需要调用的多个文件在多个目录呢 关于 init py的解释 关于sys path的解释 python如何调用自己写的py文件呢 同一个目录下直接写import xx
  • IP地址网段表示法

    http blog sina com cn s blog 4a1d691b010004qx html 1 IP地址 共分为四类 A B C D类 各类范围详见RFC参考 2 子网掩码 子网掩码的作用是用来表示IP地址中的多少位用来表示主机号
  • 23种设计模式之模板模式

    文章目录 概述 模版模式的优缺点 优点 缺点 模版模式的使用场景 模板模式的结构和实现 模式结构 模式实现 总结 概述 模板模式指 一个抽象类中 有一个主方法 再定义1 n个方法 可以是抽象的 也可以是实际的方法 定义一个类 继承该抽象类
  • 深入学习jquery源码之jQuery的构造函数与实例化

    深入学习jquery源码之jQuery的构造函数与实例化 创建jQuery对象的整个流程如下 1 调用 方法 2 调用jQuery prototype init 构造函数 3 根据选择器不同返回不同的jQuery对象 4 不同jQuery对
  • java web中servlet详解_javaWeb之Servlet详解

    Servlet详解 1 servlet简单介绍 servlet是javaweb三大组件之一 他与filter listener 共同组成了javaweb的三大组件 Servlet Server Applet 是Java Servlet的简称
  • 成员变量和局部变量

    成员变量和局部变量的区别 1 成员变量是独立于方法外的变量 局部变量是类的方法中的变量 成员变量 包括实例变量和类变量 用static修饰的是类变量 不用static修饰的是实例变量 所有类的成员变量可以通过this来引用 2 局部变量 包
  • arthas底层实现原理剖析

    前言 经常在应用的启动或者运行过程中需要动态的查看数据 或者实时的验证我们写的代码的结构与执行过程 此时需要一种工具能够动态的检测程序运行的状态 内存数据 线程情况 最好能够动态的替换代码实时生效 方便我们从日志或者其他埋点断言我们的猜测
  • 机器视觉解决方案 首选诺威特

    机器视觉解决方案 首选诺威特 诺威特简介 诺威特 NOVTEC 成立于2003年 总部位于江苏苏州 是专业从事测试解决方案的高科技企业 为企业和研究机 构提供大量高端的测试仪器设备解决方案 使用人工智能Artificial intellig
  • QT 使用QZXing生成,解析二维码跟条码

    1 下载QZXing库 为什么要下载QZXing库 而不直接使用编译好的库文件 因为每个人使用的编译环境是不一样的 使用的编译器也不尽相同 不同编译器编译出来的库放到不同编译器下则不一定能够使用 至少我是这么理解的 使用别人的也经常出现崩溃
  • 【华为OD机试】告警抑制【2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 语言限定 C clang11 C clang 11 Pascal fpc 3 0 2 Java jav
  • vbs中遍历子目录寻找特定文件

    转载 https blog csdn net hywerr article details 70228086 递归函数如下 Function FileExsitInDirectory fso As Object filename As St
  • 64位操作系统(WIN10)+32位LabVIEW(2020)+64位MySQL,Windows10系统下用32位ODBC连接MySQL

    1 首先得安装 Connector ODBC 就是MySQL的ODBC驱动 这个是与应用程序相关的 而不是与操作系统相关的 也就是说 不管你的系统是X64还是X86 只要你的应用程序是X86的那么 Connector ODBC 就要安装X8
  • cordova环境搭建以及打包apk

    1 安装node JS 2 安装ant 载连接 http ant apache org 下载完成之后解压到你想安装的目录 比如D ant 然后将目录添加到系统变量里 步骤如下 右击我的电脑 点击属性 左侧菜单点击高级系统设置 在弹窗中点击环
  • 【发现】国产007里面星爷挖子弹时看的电影~~~~

    Educating Mandy 春潮烂漫海棠红 影片名称 Educating Mandy 春潮烂漫海棠红 主演女优 Traci Lords 翠希 劳艾德 呵呵 今天逛论坛的时候看到了 转载于 https www cnblogs com bo
  • 动物识别专家系统(Java实现已开源)

    动物识别专家系统 产生式系统 问题定义 系统实现 规则 事实和产生式的表示 类的设计 匹配顺序 推理机 结果演示 源代码 产生式系统 规则库 规则库是用于描述相应领域内知识的产生式集合 它是产生式系统求解问题的基础 其中对领域知识表达的完整
  • RabbitMQ之Work Queues

    工作队列 又称任务队列 的主要思想是避免立即执行资源密集型任务 而不得不等待它完成 相反我们安排任务在之后执行 我们把任务封装为消息并将其发送到队列 在后台运行的工作进 程将弹出任务并最终执行作业 当有多个工作线程时 这些工作线程将一起处理
  • 实战案例之瀑布流效果

    前言 从服务器获取需要展示的数据 图片大小不一致 大中 中 小 每次从服务器获取三条数据 依次插入到三列中 每一列的宽度是一样的 弊端 可能导致某一列特别的高 而某一列特别的矮 瀑布流 需求分析 最终期望三列的高度差距应该是不大的才可以 最