2021-07-13

本文作者分享了在前端开发中的实践经验,包括文件分类部署、页面布局、自定义打印、本地存储、触底加载、返回顶部等功能的实现。还详细介绍了如何请求接口、渲染数据、使用git进行版本控制以及页面间传值。在购物车功能中,实现了商品的增删查改和全选结算。此外,文章提到了楼层滚动、轮播图的业务逻辑和优化。作者通过项目提升了命名规范、AJAX使用、阅读接口文档的能力,并在遇到问题时能通过学习和合作解决。
摘要由CSDN通过智能技术生成

1:你学会了什么 ?

  • 在开始写项目之前,先要对项目所要涉及到的内容进行分类部署。如分为:css、img、js、、view、index.html等文件。

  • 在部署好文件分类后,需要对各个页面的整体框架简单分析,在脑海中有一个大致的框架图,如何进行页面布局等。

  • 学会了自定义打印,可以设置颜色与背景等。可以更加清晰的查看打印的信息。

    console.log(`\n%c ${msg}`, 'background:#67c23a;color:#fff;padding:1px;border-radius:3px');
    
  • 本地存储,在页面通过window.localStorage.setItem('', ${})传入本地存储,通过window.localStorage.getItem('')获取本地存储的值,通过window.localStorage.removeItem('')删除你指定的本地存储的值。通过本地存储,可以在不同页面中获取到存在本地存储的值,解决了因为跳转页面获取不到所需参数的情况。

  • 触底加载和懒加载。当通过ajkx请求数据,将数据渲染在页面。查询到数据量较大时,就可以通过懒加载配合触底加载进行优化。通过判断可视页面高度、滚动高度以及当前滑动到页面可视区域的商品距离body顶部的高度结合计时器来实现懒加载的效果。通过

    // console.log(box.scrollHeight);内容的实际高度+上下padding
    // console.log(box.clientHeight);元素的可视高度
    // console.log(box.scrollTop);为容器相对于document的top的绝对偏移
    var box = document.documentElement;
        if (Math.ceil(box.clientHeight + box.scrollTop) === box.scrollHeight) {
            page++;
            getShopList(page);
        }
    

    实现触底加载的功能。page++,将page传入ajkx请求数据的函数,每页渲染30个物品,实现一页一页触底加载的效果。

  • 返回顶部,学会了一种新方法。如下:

    toTop.onclick = function () {
            window.scrollTo({
                top:0, 
                left:0,
                behavior:"smooth"  //滑动方式:平滑的滑动
            })
        }
    
  • 通过自定义属性,同样可以达到获取每个物品属性的效果

    window.localStorage.setItem('goodID',item[i].getAttribute('data-id'))
    

    通过getAttribute获取自定的属性值。

  • 如何请求接口并将获取到的数据渲染到页面。先请求所需数据的接口,将所需参数传进去,得到一个返回值。接受服务器响应的数据,然后将数据通过字符串模板渲染到页面

    function getCategory() {
            REQUEST.get('/getTypeone', {}, function (data) {
                var html = '';
                for (let i = 0; i < data.length; i++) {
                    html = html + `<li><a href='./view/classification.html'>${data[i]}</a></li>`
                }
                category.innerHTML = html;
                var categories = document.querySelectorAll('.category a');
                categories.forEach(function (item, index) {
                    item.onclick = function () {
                        window.localStorage.removeItem('shop ');
                        window.localStorage.setItem('shop', `${item.innerHTML}`)
                    }
                })
            })
        }
    
  • 每次项目写完一部分后,使用git将新写的内容传到自己的仓库中,养成每天使用git的习惯。方便自己保存自己每个阶段的代码。

  • 学会了页面间传值

    window.localStorage.setItem('goodID',item[i].getAttribute('data-id'))
    location.href = `./view/detail.html?goodId=${item[i].getAttribute('data-id')}`
    

2:你的进步有哪些 ?

  • 规范了命名要求
  • 更加熟练的使用ajkx请求接口渲染数据
  • 阅读接口文档更加清晰明白
  • 熟练掌握了通过本地存储传值取值的使用
  • 以前都是单独实现轮播图、懒加载、楼层滚动以及购物车等功能。这次全都结合起来,在一个项目里使用,让自己更加熟练的掌握了相关知识。
  • 做项目的逻辑更加清晰,不会像以前一样一开始无从下手的感觉

3:你哪里不会 ?

  • 通过点击首页的一级菜单跳转分类页渲染出二级菜单页以及二级菜单的详情。开始不太熟练本地存储,所以实现起来相当困难,但是在同组人员的辅导下,实现了这个功能,现在已经熟练掌握了。
  • 老师封装好的组件,虽然学会了如何调用和在调用的基础上对组件有一定的理解。但是在自己实现起来非常困难,可以说是无从下手,只能说可以简单理解老师的组件。
  • this,在老师封装好的组件里,有很多的this,以及this的apply,call以及bind还是不是很清楚,容易被绕晕。
  • 函数的原型链,虽然能够理解,但是还是不会封装组件,感觉还是很陌生。

4:总结项目中有那些业务,你是如合实现的 ?

  • 注册、登录:首先,声明一个正则表达式(/^[0-9a-zA-Z\u4e00-\u9fa5]{6,12}$/),首先判断是否满足正则表达式的要求。然后在账号和密码都在调用/register接口时,传给参数username和password,得到一个返回值,当code=1时。跳转登录页面,给登录页的账号与密码都绑定一个input事件,实时监听。将注册的账号密码输入后,调用/login接口,将输入的值传给username,password,得到返回值,当code=1时,跳转首页。导航栏变为首页、购物车、退出登录。

  • 购物车:点击商品时,获取详情页,点击添加购物车,获取本地存储的值,跳转购物车页面,购物车页面调用shopList接口,得到需要的数据并渲染到购物车页面。在购物车页面,实现数量的加减,价格随着数量的加减而加减,商品的删除。商品的全选与全消,商品的选中结算处理。调用商品的/add,/remove,/del接口分别得到返回值,实现购物车的添加,减少,删除功能。以下为全选全消功能代码。以及给选中的商品进行计算总件和总价。实现结算部分的选中结算功能。

    			function refresh(arr1, arr2) {
                    for (var i = 0; i < arr1.length; i++) {
                        arr1[i].checked = arr2.checked;
                    }
                }
    
                function brefresh(arr1, arr2) {
                    var isTrue = true;
                    for (var j = 0; j < arr1.length; j++) {
                        if (arr1[j].checked == false) {
                            isTrue = false;
                            break;
                        }
                    }
                    arr2.checked = isTrue;
                }
                allCheck.addEventListener("click", function (e) {
                    refresh(someInput, allCheck)
                    allCheck1.checked = allCheck.checked
                    change()
                })
                allCheck1.addEventListener("click", function (e) {
                    refresh(someInput, allCheck1)
                    allCheck.checked = allCheck1.checked
                    change()
                })
                for (let i = 0; i < someInput.length; i++) {
                    someInput[i].onclick = function (e) {
                        brefresh(someInput, allCheck)
                        brefresh(someInput, allCheck1)
                        change();
                    }
                }
    			// 获取选中商品的数量
                function getNum() {
                    var someInput = document.querySelectorAll('.shops input')
                    var arr = [];
                    for (var i = 0; i < someInput.length; i++) {
                        if (someInput[i].checked) {
                            arr.push(someInput[i].parentNode.parentNode.children[3].children[1].innerHTML)
                        }
                    }
                    return arr;
                }
                // 获取选中商品的总价
                function getPrice() {
                    var someInput = document.querySelectorAll('.shops input')
                    var arr = [];
                    for (var i = 0; i < someInput.length; i++) {
                        if (someInput[i].checked) {
                            arr.push(someInput[i].parentNode.parentNode.children[4].innerHTML)
                        }
                    }
                    return arr;
                }
                function change() {
                    var arr = getNum();
                    var arr1 = getPrice();
                    var sumN = 0;
                    var sumP = 0;
                    for (let i = 0; i < arr.length; i++) {
                        sumN += arr[i] * 1;
                    }
                    total_num.innerHTML = sumN;
                    for (let i = 0; i < arr1.length; i++) {
                        sumP += arr1[i] * 1;
                    }
                    total_price.innerHTML = sumP;
                }
    
  • 楼层滚动:通过获取元素的top的偏移量和元素本身的距离顶部的高度。实现楼层滚动的效果,以及给各个二级菜单设置点击事件,进行跳转位置。因为在点击二级菜单时,跳转了位置,有同时触发了楼层滚动事件,所以同时又实现了当前点击的二层菜单的字体颜色的改变和字体阴影的添加或删除。

    //楼层滚动
                    var hs = document.querySelectorAll(".shop h1")
                    var lis = document.querySelectorAll(".aside li")
                    window.addEventListener("scroll", function (e) {
                        for (let i = 0; i < hs.length; i++) {
                            var sheight = document.documentElement.scrollTop;
                            if (hs[i].offsetTop <= sheight + 200) {
                                for (let j = 0; j < lis.length; j++) {
                                    lis[j].classList.remove("li_color")
                                }
                                lis[i].classList.add("li_color")
                            }
                        }
                    })
                    // 侧边栏跳转
                    lis.forEach(function (item, index) {
                        item.onclick = function () {
                            document.documentElement.scrollTop = hs[index].offsetTop - 120;
                        }
                    })
    
  • 轮播图业务:

        var ul = document.querySelector(".carousel>ul");
        var ol = document.querySelector(".circle");
        for (var i = 0; i < ul.children.length; i++) {
            var li = document.createElement("li");
            ol.appendChild(li);
            li.setAttribute('index', i)
            li.onclick = function (e) {
                for (var i = 0; i < ol.children.length; i++) {
                    ol.children[i].className = "";
                }
                this.className = 'circle-bg';
                var index = this.getAttribute('index');
                num = circle = index;
                animate(ul, -index * carousel.offsetWidth);
            }
        }
        ol.children[0].classList.add("circle-bg");
        var first = ul.children[0].cloneNode(true);
        ul.appendChild(first);
        pos1.onclick = function () {
            if (flag) {
                flag = false;
                if (num == ul.children.length - 1) {
                    ul.style.left = 0;
                    num = 0;
                }
                num++;
                animate(ul, -num * carousel.offsetWidth, function () {
                    flag = true
                });
                circle++;
                circle = circle == ol.children.length ? 0 : circle;
                circleB()
            }
        }
        pos2.onclick = function () {
            if (flag) {
                flag = false;
                if (num == 0) {
                    num = ul.children.length - 1;
                    ul.style.left = -num * carousel.offsetWidth + "px";
                }
                num--;
                animate(ul, -num * carousel.offsetWidth, function () {
                    flag = true
                });
                circle--;
                circle = circle < 0 ? ol.children.length - 1 : circle;
                circleB()
            }
        }
        var timer = setInterval(function (e) {
            pos1.onclick();
        }, 2500);
        function circleB() {
            setTimeout(function () {
                for (var i = 0; i < ol.children.length; i++) {
                    ol.children[i].className = '';
                }
                ol.children[circle].className = 'circle-bg'
            }, 50)
        }
        function animate(obj, target, callback) {
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                var step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (obj.offsetLeft == target) {
                    clearInterval(obj.timer);
                    if (callback) {
                        callback();
                    }
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 20)
        }
    
    

5:总结你写的项目中有那些技术亮点并详细说明?

  • function getNum() {
                    var someInput = document.querySelectorAll('.shops input')
                    var arr = [];
                    for (var i = 0; i < someInput.length; i++) {
                        if (someInput[i].checked) {
                            arr.push(someInput[i].parentNode.parentNode.children[3].children[1].innerHTML)
                        }
                    }
                    return arr;
                }
                // 获取选中商品的总价
                function getPrice() {
                    var someInput = document.querySelectorAll('.shops input')
                    var arr = [];
                    for (var i = 0; i < someInput.length; i++) {
                        if (someInput[i].checked) {
                            arr.push(someInput[i].parentNode.parentNode.children[4].innerHTML)
                        }
                    }
                    return arr;
                }
    
                function change() {
                    var arr = getNum();
                    var arr1 = getPrice();
                    var sumN = 0;
                    var sumP = 0;
                    for (let i = 0; i < arr.length; i++) {
                        sumN += arr[i] * 1;
                    }
                    total_num.innerHTML = sumN;
                    for (let i = 0; i < arr1.length; i++) {
                        sumP += arr1[i] * 1;
                    }
                    total_price.innerHTML = sumP;
                }
    

    首先遍历所有的商品的input,判断是否为选中状态。如果选中,则添加进一个新的数组。得到一个全是选中状态的input1的数组,然后遍历新数组,相加,得到总值,赋值给底部计算的总件数的值。总价原理相同。如此,便可以实现只给选中状态的商品结算。

  • // 返回顶部
       var totop = document.querySelector('.return');
       //点击返回
       totop.onclick = function () {
           var scrollTop = window.pageYOffset;
           var timer = setInterval(() => {
               scrollTop -= 100;
               window.scrollTo(0, scrollTop);
               if (scrollTop <= 0) {
                   clearInterval(timer)
               }
           }, 25)
       }
    

    这是在以前写的返回顶部的效果代码。通过计时器以及scrollTop相结合,达到了25ms减100的返回顶部的效果

     var toTop = document.querySelector(".toTop");
        toTop.onclick = function () {
            window.scrollTo({
                top:0, 
                left:0,
                behavior:"smooth"
            })
        }
    

    而这次则通过了scrollTo的方法,极其简便的便实现了返回顶部的效果,要比之前的代码要优化很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值