小米官网项目制作——javascript知识分享上

2023-11-01

目录

前言

一、整体架构

二、弹出的盒子

1.定位盒子

2.弹出效果

3.其他细节

三、下拉,展开的切换菜单

1.放置盒子

2.切换盒子

3.添加索引

4.侧边展开的盒子

四、轮播图

 1.本体的部件

2.轮播图

3.节流阀

4.其他的细节

小节

 


 

前言

       经过一些长时间的学习,我经过自己的努力,较为成功的进行了小米官网的主页和登录注册的页面的制作。这个过程更多的是对自己知识的总结和练习,实践出真理,只有做了才知道需要怎么去写代码的逻辑才可以写出我们需要的效果。今天我就给大家分享一下,小米官网主页的javascript的代码上需要书写注意的地方。我的代码也可能存在一些不成熟的操作,或者有更好的优化方式,也希望大家能多多指点我的错误,提出意见。(手下留情)


一、整体架构

       首先,我们需要去看看小米官网的内容都有什么,我们可以直接前往官网查看它的内容:小米官网。点击登录和注册的话可以跳转到这两个页面去看他们的样子。

我们可以看看,有这么一些地方是我们值得注意的,需要去书写javascript代码的地方:

1.弹出的二维码,鼠标移动过去会弹出。

2.弹出的购物车,也是鼠标移动过去会弹出。

 3.菜单栏的弹出选项,鼠标选中选项会弹出下面的盒子。

 4.侧边的导航栏,选择侧边的内容会弹出右边的盒子。

 5.轮播图,会自动轮换的图,而且可以点击切换图片。

       这五个大部分可以说是用户会最直接看到的,也是最直接会去使用的地方。入眼的观感是最重要的。这一次我们对这些部分重点讲解,来认真书写这些我们需要多多注意的代码。


二、弹出的盒子

        我们可以看到顶部导航栏的两个部分内容,都是一样的,当鼠标移动过去,实现一个弹出二维码,弹出购物车盒子的一个效果。我们来具体看看它的效果演示:

       可以看到他的触发条件是:当我们触碰到文字下载app的时候,他会弹出二维码。这个效果是如何实现的呢?让我们来仔细的分析。

1.定位盒子

       我们需要明白,盒子肯定不是平白无故就弹出来的,我们需要放置这个盒子出现在这个地方。但是我们知道,大部分元素,都是会占用页面的位置。那么用什么方法来放置盒子可以实现这样悬浮在其他盒子上面的效果呢?答案就是我们的标题:定位。我们把盒子写在下载app的下面,通过给下载app对应的元素写上相对定位的方式,把这个大的盒子定位到下载app的下面。这样我们就可以实现盒子悬浮在其他页面元素上面的效果。

2.弹出效果

       我们来观察盒子的弹出部分,首先我们可以看到,盒子弹出的时候,是像把卷纸摊开了一样,伸缩的效果。里面的内容并没有变化,只是跟着弹开的盒子显示了出来,这说明盒子并不是通过定位移动到指定位置实现的弹出效果。那么能改变这个盒子弹出效果的,我们就可以考虑使用高度的变化来实现,因此我们一开始将盒子的高度清零,当我们鼠标移动过去的时候实现高度的变化,这样我们就可以做出这样的弹出效果了。

3.其他细节

       我们看到,盒子上面还有一个小三角,我们可以通过CSS制作这个三角,通过只给边框的粗度之后,把其他边的颜色变成透明色来实现。再通过定位的方式定位到上面就可以了。之后我们需要注意的是,我们需要给盒子加上overflow:hidden的效果,防止内容跑出盒子外面。通过隐藏溢出的方式,实现内容随着盒子的高度,展示出内容的效果。这样我们的效果就做完了。这里附上使用的js代码:

    // 顶部导航栏触动效果
    app.addEventListener('mouseenter', function() {
        app0.style.display = 'block';
        app1.classList.add('change');
    });

    app.addEventListener('mouseleave', function() {
        app0.style.display = 'none';
        app1.classList.remove('change');
    });

       这里我通过使用classlist的方式,给盒子添加新的类名,我在类名里面写上高度,就可以实现获得高度和失去高度的效果。最后:盒子出来的时候,是由一个时间的缓冲的,我们可以使用transition的属性来让他的高度获得的过程,增加一个动画的时间,这样看起来就是弹出来的效果了。

同样给购物车添加上同样的效果:

    shopping.addEventListener('mouseenter', function() {
        menu.classList.add('menuchange');
        icon.style.backgroundImage = 'url(img/navgation/navgation5hover.png)';
        menubox.classList.add('menuboxchange');
    });
    shopping.addEventListener('mouseleave', function() {
        menu.classList.remove('menuchange');
        icon.style.backgroundImage = 'url(img/navgation/navgation5.png)';
        menubox.classList.remove('menuboxchange');
    });

 

       其他的变化都是一样的,需要注意的就是当我们鼠标移动到购物车这个选项上的时候,内部有文字和图片的变化,注意写上变化的颜色代码就可以实现。


三、下拉,展开的切换菜单

       这两个可以下拉,而且展开的盒子,除了显示的内容以外,还有根据选择的导航栏变化的选项,变化为对应内容菜单的方式。先让我们来观察一下效果:

       我们可以看到,选择选项的时候会显示出我们需要的内容面板,只有离开了导航栏或者展开的盒子才会伸缩回去。现在让我们来分析一下这个效果的制作:

1.放置盒子

       根据前面的经验我们知道,这些盒子肯定是需要使用定位来实现放置在我们需要的位置,而且拥有下滑的菜单效果,需要去使用和之前一样的效果。但是这是一个大量的盒子集合体,不是只是一个盒子的集合体。我们需要注意的是,我们需要把这些盒子都放进一个大的盒子里面,然后隐藏这个大的盒子,给大的盒子增加获得高度的过程和动画时间,来实现这个弹出的效果。

2.切换盒子

       如果只是选择需要的选择弹出需要的盒子,他们是一一对应的效果,这很简单。但是如果是大量的盒子和大量的选项需要一一对应,我们可以怎么做?网站开发的时候是需要效率和简洁的代码的。最开始我们如果选择一个一个去写,可以实现,但是这样非常花时间,也不够简单。所以我们需要使用for循环,一个个去遍历这个过程,实现每次触碰盒子的时候,实现这些重复的效果。

3.添加索引

        如果只是用for循环写,我们不一定能准确的选择每个盒子,而且也没办法选到盒子。因为这些盒子也可以构成一个列表,当我们选择的选择发生其他的选择的时候,没有索引,就难以实现一一对应的盒子效果。所以我们需要在循环的时候,给每一个盒子添加需要的索引。通过索引来锁定我们需要的选项,他对应的盒子,实现一个一一对应的弹出效果。

接下来让我们看看代码是怎么去实现这个效果的:

// 头部导航栏下拉菜单
    var headerNav = document.querySelector('.nav-list');
    var headerItem = headerNav.querySelectorAll('.nav_item');
    var headerList = document.querySelector('.header_nav_list');
    var listItem = headerList.querySelectorAll('.nav_list_item');
    var stop = headerNav.querySelectorAll('.nav_item1');
    for (var i = 0; i < headerItem.length; i++) {
        headerItem[i].setAttribute('index', i);
        headerItem[i].addEventListener('mouseenter', function() {
            headerList.classList.add('shadow');
            var index = this.getAttribute('index');
            for (var i = 0; i < listItem.length; i++) {
                listItem[i].style.display = 'none';
            }
            listItem[index].style.display = 'block';
        });
        headerList.addEventListener('mouseleave', function() {
            headerList.classList.remove('shadow');

        });

    }
    for (var i = 0; i < stop.length; i++) {
        stop[i].addEventListener('mouseenter', function() {
            headerList.classList.remove('shadow');
        });
    }

       我们可以看到,在for循环的开始,我记录下了每一次循环的序号,通过使用setAttribute的方法,生成了一个index的新的属性作为索引。之后,在循环触碰选项的时候,我们给这些盒子从头到尾使用getAttribute的方法获取到了这些盒子对应的属性,就是是我们需要的索引。通过排他思想的方式,选择我们需要的选项的时候,把其他的盒子隐藏,只显示我们需要的盒子。当我们选择对应的选项时,只显示我们选择的对应索引属性的盒子单位,这样就可以实现一一对应的效果了。

        需要注意的是,我们在打开下面新的盒子的时候才使用了index这个索引号码,但是我们用的不是外面循环的i,因为我们的循环在外面,他属于局部的属性,而外面的循序没办法被获取下来,所以我们可以通过增加新的属性的方式,来获取for循环序列号作为属性的数值。因此我们选择了通过设置新的属性的方式获得选项的序号循序,然后获取我们设置属性的数值,打开我们需要对应打开的盒子。

       简单的说,就是我们获取外面循环的i的数值,赋值给了里面循环的盒子,让他实现和选项匹配的效果。而可以做到这一点的,就是去生成我们创造的自定义属性,获取属性的数值,然后把他作为变量,放进我们需要的循环里面去。

4.侧边展开的盒子

我们也来看看另外一个侧边展开的盒子的效果:

       我们可以看出来基本的效果和前面的下拉菜单是一样的,所以我们也可以用一样的方式去放置索引,绑定对应的选项和盒子。

    var subList = document.querySelector('.sub_nav_list');
    var subItem = subList.querySelectorAll('.sub_list_item');
    var itemBox = document.querySelectorAll('.item_sub_list');

    for (var i = 0; i < subItem.length; i++) {
        subItem[i].setAttribute('num', i);
        subItem[i].addEventListener('mouseenter', function() {
            for (var i = 0; i < subItem.length; i++) {
                subItem[i].classList.remove('Bchange');
            }
            this.classList.add('Bchange');
            var num = this.getAttribute('num');
            for (var i = 0; i < itemBox.length; i++) {
                itemBox[i].style.display = 'none';
            }
            itemBox[num].style.display = 'block';
        });
        subItem[i].addEventListener('mouseleave', function() {
            for (var i = 0; i < subItem.length; i++) {
                subItem[i].classList.remove('Bchange');
                itemBox[i].style.display = 'none';
            }
        });
    }

       我们可以看到代码结构几乎没有太大的变化,需要注意的是获取元素的对象要是正确的,不然会出现很多bug,记得要多多检查内容。


四、轮播图

       之前我也展示了一下我自己的轮播图效果,官方使用的方式是原地进行了一个透明度的变化,也可以用那样的方式去做,不过我们自己学会的是滚动的形式的轮播图,当然是进行一个知识的复用和实践。接下来让我来讲解这个轮播图的重点:(重新录了一张动图)

 1.本体的部件

       我们首先看到,有一个跟着图片滚动的小圆点,还有一个左右箭头。关于这个小圆点,我不说你们也可以猜想到,是和上面所讲的内容一样,通过索引绑定的小圆点。当我们点击箭头的时候,可以实现下一张图片,或者点击另外一个箭头的时候,可以看到上一张图片。左右的箭头可以使用定位的方式定位到需要的位置。下面的小圆点推荐先写好样式,然后用classlist添加样式。先写好盒子定位到需要的位置,然后通过for循环,绑定需要的图片项目,然后动态的去生成小圆点。用代码来解释一下吧:

    var bullets = banner.querySelector('.bullets');
    var ol = bullets.querySelector('ol');
    var bannerWidth = bannerBox.offsetWidth;
    for (var i = 0; i < items.length; i++) {
        var li = document.createElement('li');
        li.setAttribute('number', i);
        ol.appendChild(li);
    }
    ol.children[0].className = 'Lichange';

       首先for循环需要对应的图片的循序,然后通过一样的方式去设置索引,只是这个过程里还需要创建li,插入对应的ol里面做它的子节点,添加对应的样式就可以了。

2.轮播图

       轮播图可以实现每一次移动确定的距离,而且正好是一张图片,这个过程是怎么实现的呢?首先我们需要让这些图片都浮动在一行上面,保证他们是一行的长条图片。之后我们获取图片当前的坐标,每次移动的时候,第一张图片,就获取当前第一张图片的宽度,移动(1 * 图片的宽度)的距离,第二张图片就是( 2 * 图片的宽度)这样的方式,移动每一张图片。当我们看到最后一张图片的时候,强制让最后一张图片跑回第一张图片,就可以实现这个效果。这里需要注意的是,我们看到的是四张图片,其实是五张图片,因为最后一张图片,如果直接跑回第一张图片,是会有瑕疵的,你能看出来它的变化。所以为了避免这种情况,我们把第一张图片复制,粘贴到后面,当我们到最后一张图片的时候,迅速的跳转成第一张图片,然后重新轮转,这样就很难察觉图片的变化。让我们用代码的形式看看代码吧:

    //克隆图片
    var first = bannerBox.children[0].cloneNode(true);
    bannerBox.appendChild(first);
    //滚动图片
    var nums = 0;
    var circle = 0;
    var flag = true;
    // 节流阀设置
    next.addEventListener('click', function() {
        if (flag) {
            flag = false; //关闭节流阀
            if (nums == items.length) {
                bannerBox.style.left = 0;
                nums = 0;
            }
            nums++;
            animate(bannerBox, -nums * bannerWidth, function() {
                flag = true; //开启节流阀
            });
            circle++;
            if (circle == ol.children.length) {
                circle = 0;
            }
            circleChange();
        }
    });
    prev.addEventListener('click', function() {
        if (flag) {
            flag = false;
            if (nums == 0) {
                nums = items.length;
                bannerBox.style.left = -nums * bannerWidth + 'px';
            }
            nums--;
            animate(bannerBox, -nums * bannerWidth, function() {
                flag = true;
            });
            circle--;

            circle = circle < 0 ? ol.children.length - 1 : circle;
            circleChange();
        }
    });

    function circleChange() {
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        ol.children[circle].className = 'Lichange';
    }
    var timer = setInterval(function() {
        next.click();
    }, 3000);

3.节流阀

        我们可以看到上面的代码里面塞着一个节流阀。这个节流阀是什么呢?我们可以看到一个true和false的判定,节流阀就是一个开关,为的是控制这个行为动作。我们可以看到在animate这个函数之下,后面又调用了一次函数,这是一个回调函数的形式,为的是可以在前面的函数调用结束之后,再去执行下一个函数。最开始前面写入了flag = true,为的是可以让if语句调用,调用的时候,我们先让flag = false,实现关闭这个动作的操作,那么之后我们重复执行这个函数,都不会发生任何变化。上面的if语句结束之后,才轮到了下一个函数animate,当animate执行结束之后,再去调用flag = true,这样就可以重新打开节流阀,让上面if的语句可以被执行。这样的操作可以让我们轮播图不会因为用户的点击疯狂的轮转,只会按照规则一张张的滚到指定的位置才会继续滚动。

4.其他的细节

其实前面生成的小li里面,还有这样的一段代码演示:

        li.addEventListener('click', function() {
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            this.className = 'Lichange';

            var number = this.getAttribute('number');

            nums = number;
            circle = number;
            animate(bannerBox, -nums * bannerWidth);
        });

       这个代码可以让我们点击小li的时候,实现跳转到我们需要的图片的效果。做法其实和上面的代码是一样的,获取需要的索引之后,根据索引的号去移动需要的图片。但是我的代码其实缺少一个步骤,相信大家都会明白的。就是没有加上节流阀。这个过程会让我去点击li的时候,会不经过开关的快速跳转,另外,我的li在点击的时候,没有去清楚定时器等等的操作,会导致点了li之后,加速轮播图的跳转。因此大家可以在我的代码的基础上,去改良这个代码。也可以吧前面的代码包装起来,放进去调用。另外下面还有一些鼠标触动的效果,那些效果推荐用css做,因为都是同样的盒子,写hover的效果会更简单。最末尾还有一个我们熟知的效果,不是很难的代码,这里就展示给大家了,大家自行研究。

    //尾巴
    var wx = document.querySelector('.wx');
    var img = document.querySelector('.wx_img');

    wx.addEventListener('mouseenter', function() {
        img.style.display = 'block';
    })
    wx.addEventListener('mouseleave', function() {
        img.style.display = 'none';
    });


小节

       这一次我讲了重点的三个内容,弹出窗口,下拉菜单,轮播图。这三个可以说是存在着相关相对应的效果。我们可以看到承接着上一个的内容,下面的内容也会有好的构思和想法。希望大家可以多多实践代码,去写出更加清晰结构清楚的好的javascript代码。另外要多注意自己获取的元素是否是我们自己需要的元素,多用console.log打印看看。感谢大家的收看,下周会更新下一个内容。

 

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

小米官网项目制作——javascript知识分享上 的相关文章

随机推荐

  • 用pandas进行数据分析实战

    安装pandas模块包 载入练习数据 在pandas中 常用的载入函数是read csv 除此之外还有read excel和read table table可以读取txt 若是服务器相关的部署 则还会用到read sql 直接访问数据库 但
  • 机器学习基础:核密度估计(Machine Learning Fundamentals: Kernel Density Estimation)

    在概率密度估计过程中 如果我们队随机变量的分布是已知的 那么可以直接使用参数估计的方法进行估计 如最大似然估计方法 然而在实际情况中 随机变量的参数是未知的 因此需要进行非参数估计 核密度估计是非参数估计的一种方法 也就是大家经常听见的pa
  • 关于LLVM IR和Valgrind 中间语言区别

    1 LLVM和Valgrind简介 LLVM Low Level VirtualMachine 是伊利诺伊州立大学香槟分校的ChrisLattner主持开发的一个编译器框架 随着ChrisLattner去苹果公司 LLVM作为苹果公司官方支
  • pymongo使用update_many方法批量更新记录

    使用的主要函数是 coll update many 当需要对同一批数据进行更新的时候 可以用这个函数 使用时 coll update many 筛选这一批数据需要查询的内容 字典类型 set 更新的内容 字典类型 使用方法如示例代码 示例代
  • 从0搭建Hyperledger Fabric2.5环境

    Hyperledger Fabric 2 5环境搭建 一 Linux环境准备 root登录 yum y install git curl docker docker compose tree yum y install autoconf a
  • NSNumber NSValue与NSDate 详解

    我们在编码中 很多时候需要将C里面原生的数据封装成对象 这样可以用NSDictionary或者NSArray来存取访问 尤其是一些做适配的情况下 这种封装是不可避免的 Objective C提供了不少类可以帮助我们 比较常见的是NSNumb
  • [转载]Stanford华人教授李飞飞写给她学生的一封信,如何做好研究以及写好PA

    De mystifying Good Research and Good Papers By Fei Fei Li 2009 03 01 Please remember this 1000 computer vision papers ge
  • 算法——动态规划算法

    动态规划的核心思路 动态规划的解题核心主要分为两步 第一步 定义问题 有的问题过于抽象 或者过于啰嗦干扰我们解题的思路 我们要做的就是将题干中的问题转化成一系列同类问题的某个解的情况 比如说 题目 求一个数列中最大连续子序列的和 我们要将这
  • tomcat部署项目

    今天总算是把部署tomcat部署项目的几种方式实验了一下 一 1 下载 Tomcat 服务器 官网下载地址 http tomcat apache org 2 启动并部署 Tomcat 服务器 解压 tomcat 安装包到一个非中文目录下 配
  • 微服务架构详解

    一 微服务架构的由来 在微服务架构出现之前 最常用的架构就是单体架构 俗称 一个jar war 包打天下 在一个jar包工程中 采用MVC架构 分为表现层 业务层 数据访问层 所有的业务模块 都放在这个工程中集成 如下图所示 随着软件行业规
  • DS18B20温度传感器

    1 DS18B20 单线数字温度传感器 即 一线器件 其具有独特的优点 采用单总线的接口方式 与微处理器连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯 单总线具有经济性好 抗干扰能力强 适合于恶劣环境的现场温度测量 测量
  • 【前端】ant design中树形控件的父子节点受控实现

    前言 1 ant design的树形控件里面先设置好checkStrictly属性 即checkable 状态下节点选择完全受控 父子节点选中状态不再关联 这样的话 onCheck函数中的checkedKeys参数打印出来它是一个有chek
  • conda添加清华镜像源

    Anaconda 是一个用于科学计算的 Python 发行版 支持 Linux Mac Windows 包含了众多流行的科学计算 数据分析的 Python 包 Anaconda 安装包可以到 清华镜像源下载anaconda 下载 TUNA
  • 异步赠书:10月Python畅销书升级

    2018年最新活动 免费赠书 1 关注微信号 异步图书 2 邀请10位好友关注10天后 填写下方表单登记信息 即可免费获得异步图书一本 异步社区选书网址 www epubit com 点击登记免费图书邮寄信息 活动已结束 最新活动地址 ht
  • LeetCode 1689. 十-二进制数的最少数目

    如果一个十进制数字不含任何前导零 且每一位上的数字不是 0 就是 1 那么该数字就是一个 十 二进制数 例如 101 和 1100 都是 十 二进制数 而 112 和 3001 不是 给你一个表示十进制整数的字符串 n 返回和为 n 的 十
  • idea 通过访问路径快速定位到Controller方法

    目录 问题原因 解决方案 RestfulToolkit插件 使用方式 windows MAC 扩展 效果展示 问题原因 我们在调试 或者某个接口出现bug首先知道和拿到的一般是接口路径 系统运行久了 模块会很多 接口也会很多 找起来很麻烦
  • Strus2+Spring整合笔记

    1 拷贝Struts2 jar包和Spring jar包到 WEB INF lib目录下 2 配置Strust2核心控制器 配置文件 3 为第三步的Spring提供配置文件 4 添加Struts2 Spring整合的插件包 5 在appCt
  • 虚拟IP是什么?

    要是单讲解虚拟 IP 理解起来很困难 所以干脆把 动态 IP 固定 IP 实体 IP 与虚拟 IP都讲解一下 加深理解和知识扩展 实体 IP 在网络的世界里 为了要辨识每一部计算机的位置 因此有了计算机 IP 位址的定义 一个 IP 就好似
  • 2023-5-16第十六天

    permanent永久的 temporary instruction教授 传授 impart教授 initiate教授 接纳 reside居住于 resident居民 recover恢复 找回 laternate交替的 轮流的 interp
  • 小米官网项目制作——javascript知识分享上

    目录 前言 一 整体架构 二 弹出的盒子 1 定位盒子 2 弹出效果 3 其他细节 三 下拉 展开的切换菜单 1 放置盒子 2 切换盒子 3 添加索引 4 侧边展开的盒子 四 轮播图 1 本体的部件 2 轮播图 3 节流阀 4 其他的细节