JavaScript瀑布流的实现你学会了吗

目录
  • 瀑布流的核心
    • 案例
  • 注意点
    • (1)服务器加载网络图片的meta标签
    • (2)瀑布流执行的判断依据
    • (3)函数的节流
    • (4)服务器配置更改
  • 运行结果
  • 总结

瀑布流的核心

1,  根据 ajax请求的响应体结果 动态渲染生成页面

请求地址 请求方式 参数键名 都是 后端程序定义的

前端 只能根据需求 定义 携带的具体的参数数据

响应体数据是后端程序返回的数据结果

只能获取数据结果 不能修改数据结果

可以根据 响应体数据结果 动态渲染生成页面内容

可以使用 三元运算符 给标签定义属性等

2,  瀑布流 再次 发起请求的判断依据

上卷高度 + 视窗窗口高度 + 预留高度 > 最矮ul占位高度

3,  函数的节流

同时触发 多次执行 相同的函数程序

只需要触发执行 第一次 函数程序的调用

原理:

  • 定义一个 开关变量
  • 变量储存原始数据

执行判断

  • 如果 变量 存储原始数据  变量赋值其他数据
  • 如果 变量 存储其他数据  执行 return 终止之后程序的执行

当 函数的所有程序都触发执行结束

变量 赋值原始值 可以再次触发 新的函数

案例

这里用某糖网站作为案例,调用某糖网站的接口,仿一个简单的网页。

代码

<!DOCTYPE html>
<html lang="en">

<head>
    <!-- 服务器加载网络图片的meta标签 -->
    <meta name="referrer" content="never">

    <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;
        }

        .btn {
            width: 300px;
            margin: 50px auto;
        }

        ul,
        ol,
        li {
            list-style: none;
        }

        img {
            display: block;
            width: 100%;
            height: 100%;
        }

        a,
        a:hover,
        a:active {
            text-decoration: none;
        }

        .box {
            width: 1200px;
            margin: 0 auto;
        }

        .box::after {
            display: block;
            content: "";
            clear: both;
        }

        .box ul {
            width: 260px;
            float: left;
            margin: 0 20px;
        }

        .box ul li {
            width: 100%;
            display: flex;
            flex-direction: column;
            border: 2px solid #000;
            margin: 0 0 15px 0;
        }

        .box ul li .imgBox {
            width: 100%;

        }

        .box ul li .contentBox {
            width: 100%;
            padding: 15px;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .box ul li .contentBox p {
            display: flex;
            justify-content: flex-start;
            align-items: center;
        }

        .box ul li .contentBox p:nth-child(1) {
            margin: 10px 0;
        }

        .box ul li .contentBox p:nth-child(2) {
            margin: 10px 0;
        }

        .box ul li .contentBox p:nth-child(2) span {
            margin: 0 10px 0 0;
        }

        .box ul li .contentBox p:nth-child(2) span i {
            margin: 0 10px 0 0;
        }

        .box ul li .contentBox p:nth-child(3) span:nth-child(1) {
            display: block;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            overflow: hidden;
            margin: 0 10px 0 0;
        }
    </style>

</head>

<body>
    <div class="btn">
        <button>美食菜谱</button>
        <button>美妆造型</button>
        <button>家居生活</button>
        <button>人物明星</button>
    </div>

    <!-- div中的内容是 动态生成的 -->
    <div class="box"></div>

    <script src="../../ajax.js"></script>
    <script>
        // 定义全局变量 存储相关的数据信息
        let start;
        let time;
        let keyword;

        // 获取父级div标签
        const oBox = document.querySelector('.box');

        // 定义全局变量 存储 要使用的数据
        let oUls;
        let flag = true;

        // 获取 所有的button按钮
        const oBtns = document.querySelectorAll('button');
        // 循环遍历 给 所有的button标签 添加 点击事件
        oBtns.forEach(item => {
            item.addEventListener('click', function () {
                // 默认第一次显示的是从索引下标是0开始的第一条数据
                start = 0;

                // 获取关键词
                keyword = this.innerHTML;

                // 向 div标签中写入 4个ul空标签
                oBox.innerHTML = "<ul></ul><ul></ul><ul></ul><ul></ul>";

                // 获取 所有的ul标签对象
                oUls = oBox.querySelectorAll('ul');

                // 调用执行 async await 和 promise执行的 ajax请求
                setPage();
            })
        })

        // 定义 页面滚动监听事件
        window.addEventListener('scroll', function () {
            // 获取 占位数据数值

            // 页面上卷高度
            let scrollTop = document.documentElement.scrollTop;

            // 视窗窗口占位高度
            let winHeight = document.documentElement.clientHeight;

            // 设定预留高度
            let height = 500;

            // 获取最矮ul标签对象
            // 循环结束 minUl 变量中 存储 最矮ul标签对象
            let minUl = oUls[0];
            for (let i = 0 + 1; i <= oUls.length - 1; i++) {
                // 如果 minUl 变量中 存储的 ul标签 高度 大于 oUls[i]循环遍历的ul标签的占位
                // 变量minUl 中 存储 oUls[i] 循环遍历的ul标签
                if (minUl.offsetHeight > oUls[i].offsetHeight) {
                    minUl = oUls[i];
                }
            }

            // 执行判断
            if (scrollTop + winHeight + height > minUl.offsetHeight) {
                // 再次发起请求 动态渲染生成新的页面内容

                /*
                    因为 scroll事件 鼠标滚动一次 多次触发 scroll事件
                    也就是 鼠标滚动一次 多次触发执行 setPage() 函数
                    也就是 鼠标滚动一次 多次触发执行 新的 ajax请求
                    因为 ajax请求是异步程序 结果就是 多次触发的ajax请求 执行的是相同的请求参数
                    获取的 响应体结果 是 相同的响应体结果

                    实际项目中 多次请求 只需要执行 第一次请求

                */

                // 判断变量储存的数据 防止多次调用函数
                if (flag) {
                    flag = false;
                } else {
                    return;
                }

                // 再次调用函数 发起新的请求 动态渲染生成新的页面
                setPage();
            }
        })

        // 使用 async 定义 异步请求函数程序
        async function setPage() {
            // 获取 时间对象 和 时间戳
            const t = new Date();
            time = t.getTime();

            // 发起请求时 根据需求 设定 ajax请求携带的参数数据
            // response中存储的是响应体数据
            const response = JSON.parse(await myPromiseAjax('/dt', 'get', `include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=${keyword}&start=${start}&_=${time}`));

            console.log(response);

            // 给下一次 请求 赋值起始数据的索引下标
            start = response.data.next_start;

            // 获取 24条数据的数组
            const arr = response.data.object_list;

            // 循环遍历 数组中的24个单元
            arr.forEach(item => {
                // 根据数组单元的数据 生成 li标签
                let str = `
                    <li>

                    <div class="imgBox" style="height:${260 * item.photo.height / item.photo.width}px">
                        <img src="${item.photo.path}" alt="">
                    </div>
                    <div class="contentBox">
                        <p>${item.msg}</p>
                        <p>
                            <span style="${item.like_count === 0 ? 'display:none' : ''}">
                                <i>点赞</i>${item.like_count}
                            </span>
                            <span style="${item.favorite_count === 0 ? 'display:none' : ''}">
                                <i>收藏</i>${item.favorite_count}
                            </span>
                        </p>
                        <p>
                            <span>
                                <img src="${item.sender.avatar}" alt="">
                            </span>
                            <span>
                                ${item.sender.username} <br>
                                发布到 <a href="JavaScript:;">${item.album.name}</a>
                            </span>
                        </p>
                    </div>
                </li>`;

                // 每生成一个li 就要拼接写入最矮的ul标签中

                // 获取最矮的ul标签
                let minUl = oUls[0];
                for (let i = 0 + 1; i <= oUls.length - 1; i++) {
                    // 如果 minUl 变量中 存储的 ul标签 高度 大于 oUls[i]循环遍历的ul标签的占位
                    // 变量minUl 中 存储 oUls[i] 循环遍历的ul标签
                    if (minUl.offsetHeight > oUls[i].offsetHeight) {
                        minUl = oUls[i];
                    }
                }
                // 循环结束minUl 中 存储的是 最矮的ul标签对象
                // 向 最矮的ul标签中 拼接写入 li标签
                minUl.innerHTML += str;
            })

            // 当请求执行结束 当新的页面内容生成完毕
            // 可以再次发起新的请求 给 变量赋值原始数据
            flag = true;
        }

    </script>
</body>

</html>

ajax代码

// 封装一个promise程序执行 ajax请求
// 参数1    请求的url地址
// 参数2    请求的方式
// 参数3    携带的参数怇
function myPromiseAjax( url , type = 'get' , data = '' ){
    // 创建一个 promise 对象
    const p = new Promise(function( fulfilled , rejected ){
        // 执行异步ajax请求
        const xhr = new XMLHttpRequest() ;

        if( type.toLowerCase() === 'get' ){
            // get请求方式
            xhr.open( 'get' , `${url}?${data}` );
            xhr.send();

        }else{
            // post请求方式
            xhr.open( 'post' , url );
            xhr.setRequestHeader('Content-Type' , 'application/x-www-form-urlencoded');
            xhr.send(data);
        }

        // 接收 请求结果
        xhr.onreadystatechange = function(){
            // 当 ajax状态码是 4 时 判断 http状态码
            if( xhr.readyState === 4 ) {

                // 如果 http状态码 是 200 - 299
                if( /^2\d{2}$/.test( xhr.status ) ){
                    // 请求成功
                    fulfilled( xhr.response );  

                }else if( /^(4|5)\d{2}$/.test( xhr.status )  ){
                    // 请求失败
                    rejected( xhr.statusText );

                }
            }
        }

    });

    // return 返回这个promise对象
    return p;
}

注意点

(1)服务器加载网络图片的meta标签

(2)瀑布流执行的判断依据

(3)函数的节流

(4)服务器配置更改

运行结果

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • JavaScript实现瀑布流布局的3种方式

    前言 今天逛闲鱼的时候观察到每一行的高度不是相同的,经了解才知道原来这是一种瀑布流布局,感觉挺有意思,于是决定研究一下,在网上也找了一些方案,实现瀑布流大概有3种方式. 一.JS 实现瀑布流 思路分析 1.瀑布流布局的特点是等宽不等高. 2.为了让最后一行的差距最小,从第二行开始,需要将图片放在第一行最矮的图片下面,以此类推. 3.父元素设置为相对定位,图片所在元素设置为绝对定位.然后通过设置 top 值和 left 值定位每个元素. 代码实现 <!DOCTYPE html> <html

  • 使用js实现瀑布流效果

    本文实例为大家分享了js实现瀑布流效果的具体代码,供大家参考,具体内容如下 源码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewpo

  • js实现瀑布流布局(无限加载)

    本文实例为大家分享了js实现瀑布流布局的具体代码,供大家参考,具体内容如下 1.实现瀑布流布局思路 准备好数据之后 . 绑定滚动事件 . 判断页面是否到底(滚动的距离+可是区域的高度 == 最后一个元素的top) . 加载新数据,渲染新页面 .重新执行瀑布流效果 2.代码(更换图片路径之后可直接运行) <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Doc

  • JS实现图片瀑布流效果

    本文实例为大家分享了JS实现图片瀑布流的具体代码,供大家参考,具体内容如下 过程: 1.创建一个放所有图片的模块bigblock. 2.获取这个大模块,追加一个子元素块来放小图. 3.封装一个函数list(n)来存放50张图片,并且将每张图追加放入空数组ele[]中. 4.封装一个函数set_position(),来确定每个图片的位置,用到了offsetHeight,offsetTop,offsetWidth等属性,同时给最大块也设置动态的高度,随着加载的图片数量增多,最大块的高度也随着增高.

  • 如何用JS实现网页瀑布流布局

    前言: 瀑布流 又称瀑布流式布局,是比较流行的一种网站页面布局方式.即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置. 什么是瀑布流布局: 先看效果: 图片多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置. 为了方便理解,在此先给上html.css代码 不完整html代码: <div id="container"> <d

  • js实现瀑布流触底动态加载数据

    本文实例为大家分享了js实现瀑布流触底动态加载数据的具体代码,供大家参考,具体内容如下 // onScrollEvent 滚动条事件 <div class="box" ref="box" @mousewheel="onScrollEvent"> //每一个方块内的内容start <div class="boxItemStyle" v-for="(userTag, i) in dataSource&q

  • JavaScript瀑布流的实现你学会了吗

    目录 瀑布流的核心 案例 注意点 (1)服务器加载网络图片的meta标签 (2)瀑布流执行的判断依据 (3)函数的节流 (4)服务器配置更改 运行结果 总结 瀑布流的核心 1,  根据 ajax请求的响应体结果 动态渲染生成页面 请求地址 请求方式 参数键名 都是 后端程序定义的 前端 只能根据需求 定义 携带的具体的参数数据 响应体数据是后端程序返回的数据结果 只能获取数据结果 不能修改数据结果 可以根据 响应体数据结果 动态渲染生成页面内容 可以使用 三元运算符 给标签定义属性等 2,  瀑

  • javascript瀑布流式图片懒加载实例解析与优化

    之前写过一版图片"懒加载"的文章,刚好周末在整理文件的时候,大概又看了一遍之前写的代码发现有很多可以优化的地方. 这篇文章主要就是结合上篇<javascript瀑布流式图片懒加载实例>再来看看图片"懒加载"的一些知识. 图片"懒加载"的主旨: 按照需要加载图片,也就是说需要显示的时候再加载图片显示,减少一次性加载的网络带宽开销. 先来看一段代码: var conf = { 'loadfirst': true, 'loadimg': t

  • 解析javascript瀑布流原理实现图片滚动加载

    先科普下瀑布流吧 瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早采用此布局的网站是Pinterest,逐渐在国内流行开来.国内大多数清新站基本为这类风格,像美丽说.淘宝网都有使用. 这是我实现的一个效果,就是怎么滚动都加载不玩.就跟瀑布一样流啊流! 这里的实现方式我们只说Js实现方法 实现原理: 对容器中已有数据块元素进行第一次计算1 容器总宽度 2 列宽度  3 最小列数 ,得到列数

  • javascript瀑布流式图片懒加载实例

    最近项目使用到了"懒加载",现在更新一般,因为平时主要使移动端的开发所以库文件使用的是zepto.js .当然也可以和jQuery 通用. 代码如下: /** * Created by zhiqiang on 2015/10/14. * hpuhouzhiqiang@gmail.com * 图片的懒加载 **/ function loadImgLazy(node) { var lazyNode = $('[node-type=imglazy]', node), mobileHeight

  • 详解javascript实现瀑布流列式布局

    本文介绍了javascript瀑布流列式布局的相关内容,分享给大家供大家参考,具体内容如下 JS原理 上面说了,列式布局简直算是完虐绝对式布局. 绝对式布局,简直就像10元/天 的搬砖工.而列式布局就是站在那看他搬砖的监工. 同样都是搬砖的,一个卖苦力,一个秀智商.简直了!!! 听了逼逼,我们来直面一下惨淡的人生. 列式布局的原理其实和绝对式布局没有太大的却别. 同样也有3个部分, 一是页面加载自适应,二是滑动加载,三是响应式布局. 分别讲解: 1.加载自适应 我们先看一下代码吧: var $

  • 详解javascript实现瀑布流绝对式布局

    瀑布流也应该算是流行几年了吧.首先是由Pinterest掀起的浪潮,然后国内设计如雨后春笋般,冒出很多瀑布流的例子,比如,蘑菇街,Mark之(不过最近涉黄,好像被喝茶了),还有淘宝的 "哇哦". 这些都是很棒的例子, 今天我们就聊一聊瀑布流. 一.绝对式布局: JS实现原理 其实瀑布式主要的难点就在于,如果将图片整齐的排列在对应的列下,以及什么时候开始刷新加载图片. 而图片整齐的排列的主要逻辑和算法即,先获取容器内可以放多少列,然后,通过计算,存放第一列的高度,再遍历剩下(除第一列的元

  • javascript实现瀑布流自适应遇到的问题及解决方案

    这几天看了Amy老师的用javascript实现瀑布流,我跟着把代码敲出来.发现这样写只能第一次载入时适应屏幕,以后改变窗口大小就不能做到自适应了. 于是我想到了用window.onresize来使得瀑布流函数从新加载来达到目的, 复制代码 代码如下: window.onload=function(){     //瀑布流函数     waterfall('content','box');     //模拟数据加载     var dataInt = {"data":[{"s

  • Jquery瀑布流插件使用介绍

    瀑布流布局浅析 浅谈个人在瀑布流网页的实现中遇到的问题和解决方法 折腾:瀑布流布局(基于多栏列表流体布局实现) javascript 瀑布流.各大瀑布流简析与建议 因为自己用jquery比较多,便萌生了把瀑布流做成插件的想法,图片就借用迅雷UED上的那些美图吧. 先看看Demo 把代码放出来吧 复制代码 代码如下: ;(function($){ var //参数 setting={ column_width:204,//列宽 column_className:'waterfall_column'

  • 基于JavaScript实现瀑布流效果

    本文实例为大家分享了js实现瀑布流效果的具体代码,供大家参考,具体内容如下 前端内容: 使用JavaScript和四个div,将照片放入四个div中 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .container { width: 1000px

  • javascript自适应宽度的瀑布流实现思路

    这样的布局并不陌生,从2011年Pinterest创立以来,中国互联网就迅速掀起了一股模仿Pinterest的热潮,国内有众多网站采用瀑布流的布局方式,例如花瓣网.美丽说等等.而事实上在中国互联网,模仿一些在国外被人看好的模式(当然,你也可以说是山寨或抄袭,呵呵!!)向来都是一个不错的idea. OK,现在进入正题.这里主要介绍瀑布流的一种实现方法:绝对定位(css)+javascript+ajax+json.简单一点如果不做滚动加载的话就是绝对定位(css)+javascript了,ajax和

随机推荐