补充css&&如何优雅的编写JS | 青训营

72 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

CSS

定位装饰

作用:实现盒子叠在一起用(浮动是使垂直布局的块级元素变成水平)。可以让盒子始终固定在屏幕的某个位置 使用步骤:

image.png

image.png

静态定位static

一般不加position都是静态定位

相对定位relative

相对于自己之前的位置移动,注意!原来的位置还是自己的,不会被其他占据,显示模式不会改变,行还是行,块还是块

image.png

实现:position:relative(por快捷输入),需要配合方位属性实现移动(水平,垂直各自选一个),不然是不会移动的。 如果left和right都有,以left为准,如果top和botton都有,以top为准

绝对定位absolute

相对于父级进行移动, 原来的位置会被其他盒子占据,显示模式会被改变,变成行内块(一行内可共存,宽高生效) 注意!!!先找已定位的父级,若有,则以它为参照物,若没有,则以浏览器窗口为参照物

子绝父相

就是子级采用绝对定位,父级采用相对定位。

     这样做,父级不会脱离标准流,它原来的位置不会被占据,不会导致页面混乱,而子级又可以相对父级移动。

各司其职

结构(html)、表现(css)、行为(js)分离

例子:深夜模式交换 transition(过渡):要过渡的属性 花费时间 运动曲线 何时开始

组件封装

组件是指web页面上一个个包含模板(html)、功能(js)和样式(css)的单元,好的组件具备封装性、正确性、扩展性、复用性

组件设计原则

封装性、正确性、扩展性、复用性

实现组建的步骤

结构设计、展现效果、行为设计

三次重构

插件化、模板化、抽象化(抽象出一个简单的组件框架)

PC端轮播图编写

 <style>
        .one{
            width: 200px;
            height: 200px;
            background-color: aqua;
            position:absolute;
            margin-top: 100px;
        }
        .two{
            width: 200px;
            height: 200px;
            background-color: blueviolet;
            position:absolute;
        }
    </style>
</head>
<body>
    <div class="one">
    </div>
<button class="four">点击回到400</button>
<button class="eight">点击回到800</button>
    <!-- <span class="two"></span> -->
    <script>
        //动画原理就是
        //1.设置一个定时器
        //2.写改变位置的函数,也就是它和左边的距离
        //定时器每隔一段时间就会调用一次,不断改变左值,达到移动的效果
        var one=document.querySelector('.one');
        var four=document.querySelector('.four');
        var eight=document.querySelector('.eight');
        //callback,为回调函数,其实就相当于,把函数当作参数传入当前函数,
        //当前函数执行完成后,会实现该函数
        function animate(obj,target,callback)
        {
          //为了防止多次点击产生多个定时器,所以每次先清除以前的定时器
          clearInterval(obj.timer)
          //注意obj是一个对象,我们可以给这个对象添加属性,所以这里不用var timer,
            obj.timer=setInterval(function(){
            
                //加math.ceil是向上取整,这样就能保证,我们到达了指定位置,而不是有小数,和目标距离差一点
            var step=(target-obj.offsetLeft)/10
            //当我们在多个目标之间移动的时候,由于step会出现负值的情况,
            //但是我们是数字大小往上取整,所以需要先判断step大小,正数向上,负数向下取整,才能保证最后我们到达目标位置
            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';
       }, 15);
        }
 
        four.addEventListener('click',function(){
            animate(one,400,function(){
                one.style.backgroundColor='pink'
            });
        })
        eight.addEventListener('click',function(){
            animate(one,800);
        })
 </script>
</body>
</html>
无缝滚动

想要实现播放最后一张图片的时候,回到第一张。所以我们在最后再次添加第一张图片,同时,由于执行速度很快,我们虽然在最后一张,但是我们让其回到了第一张,以此来实现无缝滚动

想要动态生成最后一张图片,并且不会影响到我们小圆圈的生成数量,这里我们在动态创建完成小圆圈之后,克隆第一张图片,添加ul到最后

克隆:cloneNode(),括号里面写true为深克隆,false为浅克隆

两个小bug

①移动方向和右键点击方向不一致,造成图片出现错误

就是要保证点击小圆圈的同时,也注意修改num,num要是当前的角标值—index。因为num在右键点击过程中,控制移动距离,相当于li点击中的index。

②小圆圈应该出现位置和右键点击方向不一致

因为circle控制小圆点变化情况,只有点击右键的时候circle才会变化。所以当我们点击li之后,circle没有变化,会导致小圆圈出现错误。所以我们也需要获取当前li的index,保证小圆圈和li出现对的上,circle=index;

实现自动播放功能

这里相当于自动点击右键,所以我们而没必要重写一遍动画

此时我们使用手动调用右键点击事件——arrowright.click()

节流阀

完成代码

<!DOCTYPE html>
<html lang="zh-CN">
 
<head>
  <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>轮播图</title>
  <style>
    /* 设置外边距为0 */
    body,
    ul,
    ol {
      margin: 0;
      padding: 0;
    }
/* 设置左右箭头格式 */
    a {
      position: absolute;
      text-decoration: none;
     
      font-size: 100px;
      /* 这里是层级的意思 */
      z-index: 2;
      display: none;
     
    }
 
    a:nth-child(1) {
        color: bisque;
        top: 250px;
      left: 0px;
    }
 
    a:nth-child(2) {
        color: bisque;
        top: 250px;
      right: 0px;
    }
/* 样式为none,就不会出现小圆点,数字等前面的格式 */
    ul,
    ol {
      list-style: none;
    }
 
    .focus {
      position: relative;
      width: 1000px;
      height: 600px;
      overflow: hidden;
      margin: auto;
    }
 
    ul {
      position: absolute;
      width: 500%;
    }
 
    img{
    float: left;
      width: 1000px;
      height: 600px;
     }
 
 
    ol {
      position: absolute;
      bottom: 10px;
      left: 104px;
      margin: auto;
    }
/* 小圆点样式 */
    ol li {
      float: left;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      background-color: #fff;
      margin-left: 5px;
      box-sizing: border-box;
      padding: 1px soild #fff;
    }
/* 当前小圆点样式 */
    .current {
      background-color: transparent;
      border: 2px solid #fff;
    }
  </style>
</head>
 
<body>
  <div class="focus">
    <!-- 左右两个可以切换的箭头 -->
    <a href="#" class="arrowleft">&lt</a>
    <a href="#" class="arrowright">&gt</a>
    <ul>
      <li><img src="./风景图1.jpeg" alt=""></li>
      <li><img src="./风景图2.jpeg" alt=""></li>
      <li><img src="./风景图3.jpeg" alt=""></li>
      <li><img src="./风景图4.jpeg" alt=""></li>
    </ul>
    <ol>
      
    </ol>
  </div>
 
  <script>
    //动画函数
    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';
       }, 15);
        }
 
    // 获取左右两个箭头
    var arrowleft=document.querySelector('.arrowleft');
    var arrowright=document.querySelector('.arrowright');
    //获取整个大盒子
    var focus=document.querySelector('.focus');
    var focusWidth=focus.offsetWidth;//盒子长度,方面一会儿实现动画效果
  
    //当鼠标进入的时候就显示左右箭头
    focus.addEventListener('mouseenter',function(){
        arrowleft.style.display='block';
        arrowright.style.display='block';
        clearInterval(timer)//停止自动播放
        timer=null;//清除定时器
    })
   //当鼠标离开时,就隐藏左右箭头
   focus.addEventListener('mouseleave',function(){
        arrowleft.style.display='none';
        arrowright.style.display='none';
        timer=setInterval(function(){
        arrowright.click();
 
 },2000)
        
    })
   
    var ul=focus.querySelector('ul');
    var ol=focus.querySelector('ol');
    var num=0;
    var circle=0
    for(var i=0;i<ul.children.length;i++)
    {
       //创建li
       
       var li=document.createElement('li');
       //插入进ol
      li.setAttribute('index',i);//添加属性,获得下标,便于计算移动距离
      ol.appendChild(li);
      //排他思想,使点击的小圆点能够显示不同的样式
      li.addEventListener('click',function()
      {
          for(var i=0;i<ol.children.length;i++)
          {
            ol.children[i].className='';
          }
          this.className='current';
          
          //动画效果实现
          var index=this.getAttribute('index');     
          num=index;
          circle=index;
          //解决上述bug
          animate(ul,-index*focusWidth);  
      })
    }
    //由于打开页面时,我们就处在第一个界面,所以第一个小圆圈要为current
    ol.children[0].className='current';
    var first=ul.children[0].cloneNode(true);
    ul.appendChild(first); 
   
    //右侧点击
    var flag=true;//节流阀
    arrowright.addEventListener('click',function(){
    if(flag)
  {
          flag=false;
          //无缝滚动
          if(num==ul.children.length-1)
          {
            ul.style.left=0;
            num=0
          }
          num++;
          circle++;
          animate(ul,-num*focusWidth,function(){
            flag=true;//打开节流阀,必须在此函数执行完毕之后,才会进行,就相当于必须看完当前动画,才可以进行下一次点击
           
          });
          if(circle==4)
          {
            circle=0;
          }
          for(var i=0;i<ol.children.length;i++)
          {
            ol.children[i].className='';
          }
          ol.children[circle].className='current';
          //为什么这里的角标不直接用num,因为num是图片数量,图片数量和小圆点数量不符合。如果我们使用num,在第五张时,由于小圆点不存在此角标,所以所有的小圆点都不会变化下一次num变成了2,所以跳转显示第一张图片时小圆点都一样,只有当又开始第二张,第三张,小圆点才会变成current
    }
 })
 
 //左侧按钮
 arrowleft.addEventListener('click',function(){
    if(flag)
    {
      flag=false;
      if(num==0)
    {
      num=ul.children.length-1;
      ul.style.right=-num*focusWidth;
      //注意负号,因为是ul左侧距离div的距离
      
    }
    num--;
    circle--;
    animate(ul,-num*focusWidth,function()
    {
      flag=true;
    });
    
    if(circle<0)
    {
      circle=ol.children.length-1;
    }
    for(var i=0;i<ol.children.length;i++)
      {
        ol.children[i].className='';
      }
    ol.children[circle].className='current';
    }
    
 })
 
 //自动播放
 var timer=setInterval(function(){
  //这里我们发现,相当于自动点击了右侧按钮
  arrowright.click();
 
 },2000)
   </Script>
</body>
 
</html>

过程抽象

  • 用来处理局部细节控制的一些方法
  • 函数式编程思想的基础应用

总结

今天的内容有点难了,有点跟不上,不过对于js代码规范的地方让人醍醐灌顶,因为直接并没有注意到自己写的代码的规范性,只考虑到功能是否实现,对于代码规范,也便于日后的维护,在思考过程当中,也能优化我们的代码