美文网首页前端Web前端之路饥人谷技术博客
整理前端面试题(十四): 常用组件的实现思想

整理前端面试题(十四): 常用组件的实现思想

作者: 熠辉web3 | 来源:发表于2017-09-08 23:57 被阅读351次
    components.png

    一.上拉刷新数据的原理

    • 一个父盒子内部套一个可以scroll的子盒子
    • 给子盒子设置touchstart事件,将子盒子e.targetTouches[0].pageY的值存到变量touchStart
    • 给子盒子设置touchmove事件,根据手指滑动的距离去改变子盒子的top:scroll.style.top = scroll.offsetTop + touch.pageY-touchStart + 'px';
    • 给子盒子设置touchend事件,获取子盒子scrollTop的值,如果大于一定的值,发送ajax请求获取新的数据, 创建DOM元素insertBefore到子盒子中.
    • 详细实现代码如下:
    <style>
        div{
            position: absolute;
            top:0px;
            bottom:0px;
            width:100%;
            left:0px;
            overflow: hidden;
        }
        li{
            list-style-type: none;
            height:35px;
            background: #ccc;
            border-bottom: solid 1px #fff;
            text-align: left;
            line-height: 35px;
            padding-left:15px;
        }
        ul{
            width:100%;
            margin-top:0px;
            position: absolute;
            left:0px;
            padding:0px;
            top:0px;
        }
        </style>
        
    <div class="outerScroller">
        <ul class = 'scroll'>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
        </ul>
    </div>
    <script>
       var scroll = document.querySelector('.scroll');
       var outerScroller = document.querySelector('.outerScroller');
       var touchStart = 0;
       var touchDis = 0;
       outerScroller.addEventListener('touchstart', function(event) { 
            var touch = event.targetTouches[0]; 
            // 把元素放在手指所在的位置 
               touchStart = touch.pageY; 
               console.log(touchStart);
            }, false);
       outerScroller.addEventListener('touchmove', function(event) { 
            var touch = event.targetTouches[0]; 
            console.log(touch.pageY + 'px');  
            //改变子盒子的top值
            scroll.style.top = scroll.offsetTop + touch.pageY-touchStart + 'px';
            console.log(scroll.style.top);
            touchStart = touch.pageY;
            touchDis = touch.pageY -touchStart;
            }, false);
       outerScroller.addEventListener('touchend', function(event) { 
            touchStart = 0;
            var top = scroll.offsetTop;
            console.log(top);
            if(top>70)refresh();
            if(top>0){
                var time = setInterval(function(){
                  scroll.style.top = scroll.offsetTop -2+'px';
                  if(scroll.offsetTop<=0)clearInterval(time);
                },1)
            }
        }, false);
       function refresh(){
        for(var i = 10;i>0;i--)
            {
                var node = document.createElement("li");
                node.innerHTML = "我是被你刷出来的";
                scroll.insertBefore(node,scroll.firstChild);
            }
       }
    </script>
    

    二.请说说实现分页的简单步骤

    • 根据数据总量每页显示的数量计算出页数
    • 根据页数动态生成分页的按钮,将其页码保存在自定义标签中
    • 给页码按钮的父盒子添加其代理事件, 获取自定义标签中的页码,根据页码计算出当前的起始数据发送ajax请求获取数据,动态渲染页面.
    • 给左右箭头按钮的父盒子添加其代理事件,设置变量count,每次点击对count进行计算后得到页码发送ajax请求(同上一步),注意判断第一页和最后一页不能再点击的情况
    • 具体的模拟实现如下:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>js分页</title>
    <style type="text/css">
    body { margin: 0; padding: 0; }
    .pagination { color: #333; text-align: center; margin: 8px; }
    .pagination span { color: #999; margin: 0 1px; padding: 3px 6px; border: 1px solid #ccc; }
    .pagination span.on { background-color: #337ab7; color: #fff; font-weight: bold; border: 1px solid #333; }
    .pagination a { color: #00f; text-decoration: none; }
    .pagination a span { border: 1px solid #66c; color: #33f; }
    #pager { margin: 20px; padding: 4px; }
    #content { text-align: center; }
    </style>
    </head>
    
    <body>
    <div id="pager"></div>
    <div id="content"></div>
    <script>
        var currentPage = 1; // 当前页码, 从1开始
        var pageSize = 5; // 每页显示记录数
        var maxButtons = 10; // 显示的分页按钮数量
        var totalNumber = 30; // 记录总数
        var totalPage = parseInt(Math.ceil(totalNumber / pageSize)); // 总页数
        initPage();
    
        function initPage() {
            //循环生成数组
            var arr = [];
            for (var o = 0; o < totalNumber; o++) {
                arr.push(o);
            }
            //每一页第一个li
            var rangeStartitem = (currentPage - 1) * pageSize;
            //开始页
            var rangeStart = Math.max(1, currentPage - parseInt(maxButtons / 2));
            //最后一页
            var rangeEnd = Math.min(totalPage, rangeStart + maxButtons - 1);
            
            var constr = pageCon(arr, rangeStartitem, pageSize);
            
            var divcontent = document.getElementById("content");
            divcontent.innerHTML = constr;
            
            //创建分页模板
            var str = "";
            str += "<div class='pagination'>";
            str += "当前第" + currentPage + "页"
            //如果总页数大于1
            if (totalPage > 1) {
                //当前页不是第一页
                if (currentPage != 1) {
                    str += '<a href="#!"  data-num="1"><span>|<</span></a>';
                    str += '<a href="#!"  data-num="' + (currentPage - 1) + '"><span><<</span></a>';
                } else {
                    //如果是第一页,禁用上一页按钮
                    str += '<span>|<</span>';
                    str += '<span><<</span>';
                }
                //中间页码
                for (var i = rangeStart; i <= rangeEnd; i++) {
                    //如果是当前页的话,就禁用当前页的按钮
                if (i == currentPage) {
                    str += '<span class="on">' + i + "</span>";
                } else {
                    //否则就可以点击该页
                    str += '<a href="#"  data-num="' + i + '"><span>' + i + "</span></a>";
                }
                }
                //当前页不是总页,即是最后一页
                if (currentPage != totalPage) {
                    str += '<a href="#"  data-num="' + (currentPage + 1) + '"><span>>></span></a>';
                    str += '<a href="#"  data-num="' + totalPage + '"><span>>|</span></a>';
                } else {
                    //如果是最后页,禁用下一页
                    str += '<span>>></span>';
                    str += '<span>>|</span>';
                }
            }
                                                
            str += ' 一共' + totalPage + '页, ' + totalNumber + '条记录 </div>';
            
            var divpager = document.getElementById("pager");
            divpager.innerHTML = str;
            //获取所有生成的页面链接
            var listTag = divpager.getElementsByTagName('a');
            //绑定li事件
            for (var i = 0; i < listTag.length; i++) {
                listTag[i].onclick = function() {
                    var currentPage = this.getAttribute('data-num');
                    nowcurrentPage(currentPage);
                    return false;
                };
            }
        }
        //传递页面
        function nowcurrentPage(currentPage) {
            this.currentPage = currentPage;
            initPage();
        }
        
        //生成每页的数据
        function pageCon(arr, rangeStartitem, len) {
            var constr = '';
            for (var i = rangeStartitem; i < rangeStartitem + len; i++) {
                constr += "<li>"+ arr[i] + "</li>";
            }
            return constr;
        }
    </script>
    </body>
    </html>
    

    三.轮播图的实现思路

    • 一个父盒子用做container
    • 在container下有个ul, 其宽度为其所以li的总宽度
    • ul设置overflow:hidden属性,让其只显示当前的li
    • 通过setInterval改变其ulleft的值,实现自动轮播
    • 给左右箭头和小点添加点击事件
    • 具体代码实现如下:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            * {
                padding: 0;
                margin: 0;
                list-style: none;
                border: 0;
            }
    
            .all {
                width: 500px;
                height: 200px;
                padding: 7px;
                border: 1px solid #ccc;
                margin: 100px auto;
                position: relative;
            }
    
            .screen {
                width: 500px;
                height: 200px;
                /*overflow: hidden;*/
                position: relative;
            }
    
            .screen li {
                width: 500px;
                height: 200px;
                overflow: hidden;
                float: left;
            }
    
            .screen ul {
                position: absolute;
                left: 0;
                top: 0px;
                width: 3000px;
            }
    
            .all ol {
                position: absolute;
                right: 10px;
                bottom: 10px;
                line-height: 20px;
                text-align: center;
            }
    
            .all ol li {
                float: left;
                width: 20px;
                height: 20px;
                background: #fff;
                border: 1px solid #ccc;
                margin-left: 10px;
                cursor: pointer;
            }
    
            .all ol li.current {
                background: yellow;
            }
    
            #arr {
                display: none;
            }
    
            #arr span {
                width: 40px;
                height: 40px;
                position: absolute;
                left: 5px;
                top: 50%;
                margin-top: -20px;
                background: #000;
                cursor: pointer;
                line-height: 40px;
                text-align: center;
                font-weight: bold;
                font-family: '黑体';
                font-size: 30px;
                color: #fff;
                opacity: 0.3;
                border: 1px solid #fff;
            }
    
            #arr #right {
                right: 5px;
                left: auto;
            }
        </style>
    </head>
    <body>
    <div class="all" id='box'>
        <div class="screen">
            <ul>
                <li>![](images/1.jpg)</li>
                <li>![](images/2.jpg)</li>
                <li>![](images/3.jpg)</li>
                <li>![](images/4.jpg)</li>
                <li>![](images/5.jpg)</li>
            </ul>
            <ol>
                <!-- 动态创建的小方块,添加在这里,样式已经给写好了-->
            </ol>
        </div>
        <div id="arr"><span id="left"><</span><span id="right">></span></div>
    </div>
    <script>
        //1 获取元素
        var box = document.getElementById("box");
        var screenBox = box.children[0];//可视区域
        var imgWid = screenBox.offsetWidth;//图片宽度
        var ul = screenBox.children[0];//运动的ul
        var lisUl = ul.children;//所有的图片
        var ol = screenBox.children[1];//小方块的父盒子
        var lisOl = ol.children;//上来取值是没有内容的,动态添加后,由于是动态数组,后期可以直接操作
        var arrBox = box.children[1];
        var arrLeft = arrBox.children[0];
        var arrRight = arrBox.children[1];
    
        //添加一个pic用来count图片的数量
        var pic = 0;
    
        //动态添加盒子
        for (var i = 0; i < lisUl.length; i++) {
            var li = document.createElement("li");
            li.innerText = i + 1;
            ol.appendChild(li);
        }
    
        //给第一个盒子增加效果
        lisOl[0].className = "current";
    
        //给盒子增加简单的点击切换效果
        //遍历所有的lisOl,为其添加事件
        for (var i = 0; i < lisOl.length; i++) {
            //设置一个索引值
            lisOl[i].index = i;
            //每个添加事件
            lisOl[i].onclick = function () {
                //更改对应的属性
                for (var i = 0; i < lisOl.length; i++) {
                    lisOl[i].className = "";
                }
                this.className = "current";
                pic = this.index;
                //移动图片
                animate(ul, -this.index * imgWid);
            }
        }
    
    
        //克隆第一张图片,放入到ul的最后位置
        ul.appendChild(lisUl[0].cloneNode(true));
    
        //给两端的箭头添加点击事件
    
        //给右边的箭头添加事件
        arrRight.onclick = function () {
            if(pic == lisUl.length - 1){
                ul.style.left = 0 + "px";
                pic = 0;
            }
            pic++;
            //点击按钮的时候,对相应ol中的li进行变色
            //首先清除对应的className
            for (var i = 0; i < lisOl.length; i++) {
                lisOl[i].className = "";
            }
            //接下来对当前的ol中的li添加属性
    
            //进行条件判断
            if(pic == lisUl.length - 1){
                pic = 0;
            }
    
            lisOl[pic].className = "current";
    
            //点击的时候,移动位置
            animate(ul, -pic * imgWid);
        };
    
    
        //给左边的箭头添加事件
        arrLeft.onclick = function () {
            if(pic == 0){
                ul.style.left = -(lisUl.length - 1)*imgWid + "px";
                pic = -(lisUl.length - 1);
            }
            pic--;
            //点击的时候,移动位置
            animate(ul, -pic * imgWid);
        };
    
        var timer  = null;
        //放在最后
        //给screenoBox添加移入移出时间,一旦移入,我们就需要show出两端箭头
        box.onmouseover = function () {
            arrBox.style.display = "block";
            clearInterval(timer);
        }
        box.onmouseout = function () {
            arrBox.style.display = "none";
            timer = setInterval(function () {
                arrRight.click();
            },2000)
        }
    
    
        function animate(tag, target) {
            clearInterval(tag.timer);//防止加速
            tag.timer = setInterval(function () {
                //1 标签当前位置的获取
                var leader = tag.offsetLeft;
                //2 设置运动的步长
                var step = 15;
                step = leader > target ? -step : step;
    
                if (Math.abs(leader - target) > Math.abs(step)) {//设置运动的目标位置
                    //3 套用运动公式: 当前位置(新) = 当前位置(旧) + 步长
                    leader = leader + step;
                    //4 设置给标签的left
                    tag.style.left = leader + "px";
                } else {
                    tag.style.left = target + "px";
                    clearInterval(tag.timer);//运动结束,清除定时器
                }
            }, 20);
        }
    </script>
    </body>
    </html>
    
    

    相关文章

      网友评论

      本文标题:整理前端面试题(十四): 常用组件的实现思想

      本文链接:https://www.haomeiwen.com/subject/vexojxtx.html