js(event、拖拽、碰撞检测、缓冲运动、多属性运动、轮播图、Object、正则、闭包、ajax)

事件对象
  • 概念:当时事件发生的时候,所以跟事件相关的信息(事件类型,事件目标,鼠标位置等)都会存储在事件对象event中。
  • 获取方式:
    console.log(event); //ie chrome 火狐会报错
    console.log(window.event); //ie chrome 火狐不报错,没有值
    console.log(ev); //火狐专用(一定要在形参中传入ev)
  • 兼容处理
    var oEvent = window.event || ev
	  事件对象属性
      oDiv.onclick = function (ev) {
      //事件对象兼容
      var oEvent = window.event || ev
      console.log(oEvent);
      //事件类型
      console.log(oEvent.type);
      //事件目标
      console.log(oEvent.target || oEvent.srcElement);
      //鼠标位置,相对于屏幕
      console.log(oEvent.clientX, oEvent.clientY);
      //鼠标位置,相对于页面
      console.log(oEvent.pageX, oEvent.pageY);
      //是某按住了某些键,返回一个布尔值
      //alt
      console.log(oEvent.altKey);
      //ctrl
      console.log(oEvent.ctrlKey);
      //shift
      console.log(oEvent.shiftKey);
    }
  • 事件绑定
    • 标准浏览器元素.addEventListener(‘事件类型(不加on)’,事件处理函数,是否捕获)
      默认false冒泡 true捕获
    • IE浏览器
      元素.attachEvent(‘事件类型(加on)’,事件处理函数)
    • 区别:
      标准 addEventListener
      不加on
      是否捕获
      this——触发事件的对象
      IE attachEvent
      加on
      没有捕获
      this——window
      IE低版本浏览器,会倒序执行
    function fn1() {
      console.log(111);
    }
    function fn2() {
      console.log(222);
    }
    function fn3() {
      console.log(333);
    }
    //封装
    function on(ele, type, fun) {
      if (ele.addEventListener) { //有值,说明支持这个方法
        ele.addEventListener(type, fun)
      } else {
        ele.attachEvent('on' + type, fun)
      }
    }
    on(oDiv,'mouseover',fn1)
    on(oDiv,'mouseover',fn2)
    on(oDiv,'mouseover',fn3)
  • DOM事件流
    • 事件捕获阶段:当事件发生的时候,事件从window开始依次往子元素传递
    • 确定目标阶段:找到目标
    • 事件冒泡阶段:从事件目标开始处理事件,处理完以后依次往父元素传递,一直传到 window
      注意IE只有冒泡,没有捕获
   <div id="box1">
      <div id="box2">
        <div id="box3">
        </div>
      </div>
    </div>
    //冒泡      先触发自己,再依次触发父级
    oDiv[0].addEventListener('click', fn1) //111
    oDiv[1].addEventListener('click', fn2) //222  111
    oDiv[2].addEventListener('click', fn3) //333  222  111
    //捕获    从最顶层父级开始,依次往下传递,最后触发自己的
    oDiv[0].addEventListener('click', fn1, true) //111
    oDiv[1].addEventListener('click', fn2, true) //111  222
    oDiv[2].addEventListener('click', fn3, true) //111  222  333
  • stopPropagation
    • 概念:该方法将停止事件的传播阻止它被分派到其他document节点
    • 兼容:oEvent.stopPropagation ? oEvent.stopPropagation() : oEvent.cancelBubble = true
      //点击显示
      btn.onclick = function (ev) {
      oDiv.style.display = 'block'
      //事件对象兼容
      var oEvent = window.event || ev
      //该方法将阻止事件的传播,阻止它被分配到其他document节点
      //标准浏览器oEvent.stopPropagation()      ie低版本:oEvent.cancelBubble = true
      oEvent.stopPropagation ? oEvent.stopPropagation() : oEvent.cancelBubble = true
    }
    document.onclick = function () {
      oDiv.style.display = 'none'
    }
  • 事件取消
    • 元素.事件—————————–元素.事件=null
    • 元素.addEventListener()————元素.removeEventListener(事件类型,事件处理函数)
    • 元素.attachEvent()——————元素.detachEvent(事件类型,事件处理函数)
        oDiv[0].onclick = function(){
            console.log(111)
        }
        oDiv[0].onclick = null
        oDiv[0].addEventListener('click',fn1)
        oDiv[0].removeEventListener('click',fn1)
        oDiv[0].attachEvent('onclick',fn1)
        oDiv[0].detachEvent('onclick',fn1)
  • 取消默认行为 :浏览器给的行为
    • 元素.事件———————–return false
    • 元素.addEventListener()———————oEvent.preventDefault()
    • 元素.attachEvent()—————————oEvent.returnValue = false
    // 元素.事件
    oA.onclick = function () {
      return false
    }
    oA.addEventListener('click', function (ev) {
      //事件对象兼容
      var oEvent = window.event || ev
      oEvent.preventDefault()
    })
    oA.attachEvent('onclick',function(ev){
      //事件对象兼容
      var oEvent = window.event || ev
      oEvent.returnValue = false
    })
  • 鼠标右击事件
    • 元素.oncontextmenu
    /* 
      分析:
        1、获取元素
        2、给元素添加右击事件
        3、获取鼠标点击的位置     在这之前做事件对象兼容
        4、把这个位置赋值给div
        5、取消右击的默认事件
    */
    var oDiv = document.getElementsByTagName('div')[0]
    document.oncontextmenu = function (ev) {
      //事件对象兼容
      var oEvent = window.event || ev
      console.log(oEvent);
      //获取鼠标X轴位置
      var clientX = oEvent.clientX
      //获取鼠标Y轴位置
      var clientY = oEvent.clientY
      //赋值给div
      oDiv.style.left = clientX + 'px'
      oDiv.style.top = clientY + 'px'
      //取消默认事件(右键)
      return false
    }
  • 键盘事件
    • onkeydown 键盘按下
    • onkeypress 在键盘被按下并释放一个键时发生
    • onkeyup 键盘抬起
      document.onkeydown = function (ev) {
      //事件对象兼容
      var oEvent = window.event || ev
      console.log(oEvent);
      console.log('我的按键是:' + oEvent.key);
      console.log('我的编码是:' + oEvent.keyCode);
      //是否按了alt
      console.log(oEvent.altKey);
      //是否按了ctrl
      console.log(oEvent.ctrlKey);
      //是否按了shift
      console.log(oEvent.shiftKey);
      //判断是否按了ctrl+shift
      if (oEvent.ctrlKey == true && oEvent.shiftKey == true) {
        console.log('我按了ctrl+shift');
      }
      //判断是否按了ctrl+c
      if (oEvent.ctrlKey == true && oEvent.keyCode == 67) {
        console.log('我按了ctrl+c');
      }
    }

案例:控制div的移动(左上右下:37-38-39-40)

  <div></div>
  <script src="./ujiuye.js"></script>
  <script>
    var oDiv = document.getElementsByTagName('div')[0]
    document.onkeydown = function (ev) {
      // console.log(111);
      //事件对象兼容
      var oEvent = window.event || ev
      //获取可视区宽度
      var clientX = document.documentElement.clientWidth
      if (parseInt(getStyle(oDiv, 'left')) <= -100) {
        oDiv.style.left = clientX + 'px'
      }
      switch (oEvent.keyCode) {
        case 37:
          oDiv.style.left = parseInt(getStyle(oDiv, 'left')) - 10 + 'px';
          break;
        case 38:
          oDiv.style.top = parseInt(getStyle(oDiv, 'top')) - 10 + 'px';
          break;
        case 39:
          oDiv.style.left = parseInt(getStyle(oDiv, 'left')) + 10 + 'px';
          break;
        case 40:
          oDiv.style.top = parseInt(getStyle(oDiv, 'top')) + 10 + 'px';
          break;
      }
    }
  </script>
  • 滚轮事件
    • ie/chrome元素.onmousewheel
      • 滚动方向:oEvent.wheelDelta 下:-120 上:120
    • 火狐元素.addEventListener(‘DOMMouseScroll’,处理函数)
      • 滚动方向:oEvent.detail 下:3 上:-3
      封装滚轮方向:
      function scroll(ev) {
      //事件对象兼容
      var oEvent = window.event || ev
      if (oEvent.wheelDelta) {
        //如果能走到这里,说明是谷歌浏览器
        if (oEvent.wheelDelta > 0) {
          console.log('向上滚动');
        } else {
          console.log('向下滚动');
        }
      } else {
        //如果能走到这里,说明是火狐浏览器
        if (oEvent.detail > 0) {
          console.log('向下滚动');
        } else {
          console.log('向上滚动');
        }
      }
    }
    //谷歌浏览器
    document.onmousewheel = function(){
      scroll()
    }
    //火狐浏览器
    document.addEventListener('DOMMouseScroll',scroll)

案例:滚轮改变div的高度

      function scroll(ev) {
      //事件对象兼容
      var oEvent = window.event || ev
      //定义一个变量用来保存当前是向上滚动还是向下滚动
      var tag = true
      if (oEvent.wheelDelta) {
        //如果能走到这里,说明是谷歌浏览器
        tag = oEvent.wheelDelta > 0 ? true : false
      } else {
        //如果能走到这里,说明是火狐浏览器
        tag = oEvent.detail > 0 ? false : true
      }
      //向下滚动false,向上滚动是true

      //获取当前的高度
      var h = parseInt(getStyle(oDiv, 'height'))
      console.log(h);
      if (tag) {
        //向上滚动
        oDiv.style.height = h - 10 + 'px'
      } else {
        //向下滚动
        oDiv.style.height = h + 10 + 'px'
      }
    }
    oDiv.onmousewheel = function () {
      scroll()
    }
    oDiv.addEventListener('DOMMouseScroll', scroll)
  • 事件代理
    • 概念:事件代理(事件委托):找一个元素**(父元素)代理**,当事件发生时,由这个元素通知具体的元素去处理事件
    • 原理:将事件绑定在父元素身上,当事件发生的时候,通过事件目标获取到具体的子元素,去处理事件 (接收事件目标 oEvent.tagret || oEvent.srcElement)
    • 优点:提高性能,让后面所有子元素同样拥有效果
    oUl.onclick = function (ev) {
      //事件对象兼容
      var oEvent = window.event || ev
      //用来接收事件目标     oEvent.tagret||oEvent.srcElement
      var tagret = oEvent.tagret || oEvent.srcElement
      tagret.style.background = 'pink'
    }

    oUl.innerHTML += '<li>999</li>'
        //多个输入框各自通过滚轮增减数字
        function scroll(ev) {
            //事件处理兼容
            var oEvent = window.event || ev
            //事件代理
            var target = oEvent.tagret || oEvent.srcElement
            var tag = true
            //向上滑动,tag=true;向下滑动,tag=false
            if (oEvent.detail) {
                tag = oEvent.detail > 0 ? false : true
            } else {
                tag = oEvent.wheelDelta > 0 ? true : false
            }
            //向上滑动,值++;向下滑动,值--
            if(tag){
                target.value++
            }
            else{
                target.value--
            }
        }
        document.body.onmousewheel = function(){
            scroll()
        }
   document.body.addEventListener('DOMMouseScroll',scroll)
拖拽
    <div></div>
    <img src="../拖拽/img/123.jpg" alt="">
    <script>
        var oDiv = document.getElementsByTagName('div')[0]
        var oImg = document.getElementsByTagName('img')[0]
        drag(oDiv)
        drag(oImg)
        function drag(ele) {
            ele.onmousedown = function (ev) {
                // 事件处理兼容
                var oEvent = window.event || ev
                //当鼠标点下,获取鼠标到盒子的x,y(鼠标到屏幕的距离-盒子到屏幕的距离)
                var mouseToBoxL = oEvent.clientX - ele.offsetLeft
                var mouseToBoxT = oEvent.clientY - ele.offsetTop
                //获取屏幕可视宽高
                var clientW = document.documentElement.clientWidth
                var clientH = document.documentElement.clientHeight
                //盒子实际宽高
                var boxW = ele.offsetWidth
                var boxH = ele.offsetHeight
                //ie低版本浏览器取消图片文字拖拽默认事件:设置捕获(一次性的,鼠标抬起后需要释放捕获才能重新设置捕获)
                if (ele.setCapture) {
                    ele.setCapture()
                }
                document.onmousemove = function (ev) {
                    //事件处理兼容
                    var oEvent = window.event || ev
                    //控制范围(当盒子到左屏幕的距离<0时,设置盒子到左屏幕的距离=0;当盒子到左屏幕的距离>(屏幕宽-盒子实际宽度)时,设置盒子到左屏幕的距离=屏幕宽-盒子实际宽度)
                    // 控制范围(当盒子到上屏幕的距离<0时,设置盒子到上屏幕的距离=0;当盒子到上屏幕的距离>(屏幕高-盒子实际高度)时,设置盒子到上屏幕的距离=屏幕宽-盒子实际高度)
                    //时刻获取鼠标位置来确定盒子位置
                    var L = oEvent.clientX - mouseToBoxL
                    var T = oEvent.clientY - mouseToBoxT
                    if (L < 0) {
                        L = 0
                    } else if (L > clientW - boxW) {
                        L = clientW - boxW
                    }
                    if (T < 0) {
                        T = 0
                    } else if (T > clientH - boxH) {
                        T = clientH - boxH
                    }
                    //当鼠标移动,盒子的位置随之改变(设置定位样式为:鼠标到屏幕的距离-鼠标到盒子的距离)
                    ele.style.left = L + 'px'
                    ele.style.top = T + 'px'
                }
                document.onmouseup = function () {
                    document.onmousemove = null
                    document.onmouseup = null
                    //释放捕获
                    if (ele.releaseCapture) {
                        ele.releaseCapture()
                    }
                }
                //标准浏览器取消图片拖拽默认事件
                return false
            }
        }
碰撞检测
    <div></div>
    <p></p>
    <script>
        var oDiv = document.getElementsByTagName('div')[0]
        var oP = document.getElementsByTagName('p')[0]
        //获取大盒子各边的位置
        var bigL = oP.offsetLeft
        var bigT = oP.offsetTop
        var bigR = bigL + oP.offsetWidth
        var bigB = bigT + oP.offsetHeight
        oDiv.onmousedown = function (ev) {
            // 事件处理兼容
            var oEvent = window.event || ev
            //当鼠标点下,获取鼠标到盒子的x,y(鼠标到屏幕的距离-盒子到屏幕的距离)
            var mouseToBoxL = oEvent.clientX - oDiv.offsetLeft
            var mouseToBoxT = oEvent.clientY - oDiv.offsetTop
            //获取屏幕可视宽高
            var clientW = document.documentElement.clientWidth
            var clientH = document.documentElement.clientHeight
            //盒子实际宽高
            var boxW = oDiv.offsetWidth
            var boxH = oDiv.offsetHeight
            //ie低版本浏览器取消图片文字拖拽默认事件:设置捕获(一次性的,鼠标抬起后需要释放捕获才能重新设置捕获)
            if (oDiv.setCapture) {
                oDiv.setCapture()
            }
            document.onmousemove = function (ev) {
                //事件处理兼容
                var oEvent = window.event || ev
                //控制范围(当盒子到左屏幕的距离<0时,设置盒子到左屏幕的距离=0;当盒子到左屏幕的距离>(屏幕宽-盒子实际宽度)时,设置盒子到左屏幕的距离=屏幕宽-盒子实际宽度)
                //控制范围(当盒子到上屏幕的距离<0时,设置盒子到上屏幕的距离=0;当盒子到上屏幕的距离>(屏幕高-盒子实际高度)时,设置盒子到上屏幕的距离=屏幕宽-盒子实际高度)
                //时刻获取鼠标位置来确定盒子位置
                var L = oEvent.clientX - mouseToBoxL
                var T = oEvent.clientY - mouseToBoxT
                if (L < 0) {
                    L = 0
                } else if (L > clientW - boxW) {
                    L = clientW - boxW
                }
                if (T < 0) {
                    T = 0
                } else if (T > clientH - boxH) {
                    T = clientH - boxH
                }
                //当鼠标移动,盒子的位置随之改变(设置定位样式为:鼠标到屏幕的距离-鼠标到盒子的距离)
                oDiv.style.left = L + 'px'
                oDiv.style.top = T + 'px'
                //在移动的时候,时刻获取小盒子各边的位置
                var divL = oDiv.offsetLeft
                var divT = oDiv.offsetTop
                var divR = divL + oDiv.offsetWidth
                var divB = divT + oDiv.offsetHeight
                //判断安全区,小盒子右边<大盒子左边;小盒子下边<大盒子上边;小盒子左边>大盒子右边;小盒子上边>大盒子下边
                if (divR < bigL || divB < bigT || divL > bigR || divT > bigB){
                    oP.style.background = 'green'
                }else
                    oP.style.background = 'yellow'

            }
            document.onmouseup = function () {
                document.onmousemove = null
                document.onmouseup = null
                //释放捕获
                if (oDiv.releaseCapture) {
                    oDiv.releaseCapture()
                }
            }
            //标准浏览器取消图片拖拽默认事件
            return false
        }
    </script>
缓冲运动
        // 封装调用测试缓冲运动
        var timer
        function bufferMove(ele,attr,target){
            clearInterval(timer)
            timer = setInterval(function () {
                //获取当前位置
                var localNow = parseInt(getStyle(ele, attr))
                //速度步长:(目标位置-当前位置)/固定系数
                var step = (target - localNow) / 10
                //判断运动的方向:正向运动向上取整,负向运动向下取整
                step = step > 0 ? Math.ceil(step) : Math.floor(step)
                if (localNow == target) {
                    localNow = target
                    clearInterval(timer)
                }
                //设置div新的位置
                ele.style[attr] = localNow + step + 'px'
            }, 16)
        }
        oDiv.onclick = function(){
            bufferMove(oDiv,'top',300)
        }
多属性运动
    <div></div>
    <div></div>
    <script src="../运动函数封装/ujiuye.js"></script>
    <script>
        //多属性运动,多个属性对应相对应的目标值,可以用对象
        var oDiv = document.getElementsByTagName('div')
        var oP = document.getElementsByTagName('p')[0]
        // 封装调用测试缓冲运动
        var timer
        function bufferMove(ele, json, fn) {
            //区分不同元素的定时器id(元素.timer)
            clearInterval(ele.timer)
            ele.timer = setInterval(function () {
                //假设所有的样式都已经执行完
                var tag = true
                for (var attr in json) {
                    //获取当前位置(如果样式为透明度,则其获取到的透明浮点值*100;如果获取到的为其他样式,则当前位置为样式取整)
                    var localNow = attr == 'opacity' ? getStyle(ele, attr) * 100 : parseInt(getStyle(ele, attr))
                    //速度步长:(目标位置-当前位置)/固定系数
                    var step = (json[attr] - localNow) / 10
                    //判断运动的方向:正向运动向上取整,负向运动向下取整
                    step = step > 0 ? Math.ceil(step) : Math.floor(step)
                    //如果当前位置还没到目标值,则状态为false        
                    if (localNow != json[attr]) {
                        tag = false
                    }
                    //设置div新的样式(如果样式为透明度,则设置透明值为(当前位置+步长)/100;如果为其他样式,则设置新样式为(当前位置+步长+'px')
                    ele.style[attr] = attr == 'opacity' ? (localNow + step) / 100 : localNow + step + 'px'
                    if (tag == true) {
                        //当全部键值对完成后清除定时器
                        clearInterval(ele.timer)
                        //回调函数
                        fn && fn(ele,
                            {
                                'height': 100,
                                'width': 100,
                                'opacity': 20
                            })
                    }
                }
            }, 30)
        }
        oDiv[0].onmouseover = function () {
            bufferMove(this,
                {
                    'height': 300,
                    'width': 300,
                    'opacity': 100
                }, bufferMove)
        }

        oDiv[1].onmouseover = function () {
            bufferMove(this,
                {
                    'height': 300,
                    'width': 300,
                    'opacity': 100
                }, bufferMove)
        }
        //此时两个盒子的定时器共用一个,相互影响,需要给当前元素设置独立的定时器,万物皆对象,元素.键名(ele.timer)
    </script>
回调函数
  • 某个动作或某个事件完成后调用的函数
    一般在封装函数中,都可以设置回调函数,但这个回调函数不是必传的参数,即使传了也可以选择不用(fn && fn()
轮播图
    <script>
    var oUl = document.getElementsByTagName('ul')[0]
    var oP = document.getElementsByTagName('p')[0]
    var oSpan = document.getElementsByTagName('span')
    var wrap = document.getElementById('wrap')
    //1、 91-102 设置静态页面并设置初始样式
    var imgArr = ['./img/1.jpg', './img/2.jpg', './img/3.jpg', './img/4.jpg']
    //定义接收图片的字符串
    var str1 = ''
    //定义接收span的字符串
    var str2 = ''
    for (var i = 0; i < imgArr.length; i++) {
      str1 += '<li><img src="' + imgArr[i] + '"></li>'
      str2 += '<span>' + (i + 1) + '</span>'
    }
    oUl.innerHTML = str1 + '<li><img src="' + imgArr[0] + '"></li>'
    oP.innerHTML = str2
    oSpan[0].className = 'active'
    //定义一个n来表示当前是第几张图片
    var n = 0
    //2、设置自动轮播
    var timer1 = setInterval(autoNext, 3000)
    function autoNext() {
      /* 
        第一次移动   -960*1
        第二次移动   -960*2
        第三次移动   -960*3
      */
      //3、执行n++
      n++
      //5、判断是否为最后一张
      if (n >= imgArr.length + 1) {
        oUl.style.left = '0px'
        n = 1
      }
      //4、每次移动ul -960*n的位置
      move(oUl, 'left', 30, -960 * n)
      //7、干掉小方块所有样式
      for (var i = 0; i < oSpan.length; i++) {
        oSpan[i].className = ''
      }
      //6、设置小方块的样式
      if (n == imgArr.length) {
        // 说明当前是那张假图
        oSpan[0].className = 'active'
      } else {
        // 说明当前是正常轮播
        oSpan[n].className = 'active'
      }
    }
    wrap.onmouseover = function () {
      clearInterval(timer1)
    }
    wrap.onmouseleave = function () {
      timer1 = setInterval(autoNext, 3000)
    }
    //点击小方块
    //1)循环遍历每一个小方块
    for (var i = 0; i < oSpan.length; i++) {
      //3)设置自定义索引
      oSpan[i].index = i
      //2)给每一个小方块添加点击事件
      oSpan[i].onclick = function () {
        //4)移动ul,每次移动-960*this.index的距离
        move(oUl, 'left', 30, -960 * this.index)
        //6)干掉所有
        for (var j = 0; j < oSpan.length; j++) {
          oSpan[j].className = ''
        }
        //5)给当前这个小方块添加样式
        this.className = 'active'
        //7)改变n的值
        n = this.index
      }
    }
  </script>
面向对象的概念
  • 面向过程:我们之前按照步骤写代码就是面向过程的编程思维
  • 面向对象:使用对象时,只关注对象提供的功能不关注其内部细节
    • 遇到问题就找对象,有对象就用对象,没有对象就造对象,使用对象来解决问题
  • 面向对象的特点
    • 封装:将大量的全局变量函数封装成对象的属性和方法,从而减少全局变量,防止全局作用域的污染
    • 继承:面向对象思想实现了js中的对象的继承
    • 多态:在同一操作中,不同环境下有不同的效果(譬如js中的+:运算/字符串拼接)
  • 对象的组成
    • 属性(态)————对象中的属性
    • 方法(态)————对象中值为函数的属性
对象的创建
  • 字面量创建
    • var obj = {属性名:属性值,……….}
    • 优点:写法方便
    • 缺点:不利于创建大量对象
  • 实例化创建
    • var obj = new Object()
    • 优点:创建出来的对象类型明确
    • 缺点:不利于创建大量对象
  • 工厂模式(工厂函数)创建
    • 创建方式:
      封装一个函数
      ②在函数建一个对象
      ③将属性和方法添加到封装的函数中
      返回创建出来的对象
    • 优点:可以创建大量对象
    • 缺点:this指向不明确,this值是window,而不是创建出来的对象
  • 构造函数创建
    • 创建方式:function Fn(name){ this.name=name }
    • 实例化方式:var obj = new Fn()
    • 在new的时候执行了四个步骤
      js隐式创建空对象
      js隐式将构造函数的this赋值给隐式创建的对象
      通过this给空对象绑定属性
      js隐式返回绑定好属性的对象
    • 注意
      构造函数首字母必须大写
      不需要在构造函数内部new Object()
      属性和方法直接加在this上
      不需要return
      调用的时候必须加new(如果不加new就和普通调用函数一样)
    • 缺点:如果创建的对象有相同的属性,会浪费资源
  • 原型
    • 原型的获取方式
      构造函数.prototype
      子对象._ _ proto _ _
    • 作用
      ①可以给子对象继承自身的属性
      ②子对象可以使用原型的属性但不拥有
  • 原型创建
    • 创建方式:Fn.prototype.money = ‘5000W’
    • 实例化方式:var obj = new Fn()
    • 构造函数内不写任何属性(空构造函数),而是将所有属性写入原型中,继承给每一个子对象,最大程度节省内存空间
    • 缺点:不能传参
  • 混合创建(构造函数创建+原型创建)
    • 构造函数中定义可变的属性和方法(可以传参)
    • 原型中定义共享的属性和方法(节约内存)
  • 动态混合创建
        //字面量创建
        var stu = {'sno':1,'name':'张三','age':18}
        console.log(stu)
        console.log(stu.sno)
        //实例化创建
        var stu = new Object()
        stu.sno = 1
        stu.name = '张三'
        stu.age = 18
        console.log(stu)
        console.log(stu.sno)
        //工厂模式(工厂函数)创建
        function stu(sno,name,age){
            var person = new Object()
            person.sno = sno
            person.name = name
            person.age = age
            return person
        }
        console.log(stu(1,'张三',18))
        console.log(stu(1,'张三',18).sno)
        //构造函数创建
        function Fn(sno,name,age){
            this.sno = sno
            this.name = name
            this.age = age
        }
        var stu = new Fn(1,'张三',18)
        console.log(stu)
        console.log(stu.sno)
        //原型创建
        function Fn(){}
        Fn.prototype.sno = 1
        Fn.prototype.name = '张三'
        Fn.prototype.age = 18
        console.log(Fn.prototype)  //通过创建函数找原型
        var stu = new Fn()         //通过创建函数创建子对象
        console.log(stu.__proto__) //通过子对象找原型
        console.log(stu.sno)       //子对象继承原型的属性和方法
        //混合创建(构造函数+原型)
        function Fn(sno,name,age){
            this.sno = sno
            this.name = name
            this.age = age
        }
        Fn.prototype.course = '信息安全'
        Fn.prototype.class = '03'
        var stu = new Fn(1,'张三',18)
        console.log(stu)
        console.log(stu.course)
        console.log(stu.__proto__.constructor)//子对象的原型对应的创建函数

案例:飞机大战:

    /* 
      静态: 图片路径、X、Y
      动态: 把路径转换成图片,设置X和Y
    */
    var wrap = document.getElementsByTagName('div')[0]
    function Plane(src, x, y) {
      this.imgNode = null
      this.planeSrc = src
      this.planeX = x
      this.planeY = y
      this.init()
    }
    Plane.prototype.init = function () {
      this.imgNode = document.createElement('img')
      this.imgNode.src = this.planeSrc
      this.imgNode.style.left = this.planeX + 'px'
      this.imgNode.style.top = this.planeY + 'px'
      wrap.appendChild(this.imgNode)
    }
    var obj1 = new Plane('./image/大飞机挨打.png', 100, 100)
    var obj2 = new Plane('./image/飞机爆炸.gif', 200, 400)
    new Plane('./image/我的飞机.gif', 200, 200)

案例:选项卡

    <button>按钮一</button>
    <button>按钮二</button>
    <button>按钮三</button>
    <div class="active">11111</div>
    <div>22222</div>
    <div>33333</div>
    <script>
        function ChooseCard() {
            this.btn = document.getElementsByTagName('button')
            this.oDiv = document.getElementsByTagName('div')
            var that = this
            for (var i = 0; i < this.btn.length; i++){
                this.btn[i].index = i
                //点击按钮后改变div的样式为公共的动态方法,放在原型里面
                this.btn[i].onclick = function(){
                    //构造函数中的方法
                    that.init(this.index)
                }
            }
         }
         ChooseCard.prototype.init = function(index){
             //原型里面的this指向构造函数,目前需要获取到构造函数中的div的个数,干掉所有
             for(var j=0;j<this.oDiv.length;j++){
                 this.oDiv[j].className = ''
             }
             //此时索引因为此时点击的按钮的索引,可以传入一个参数
             this.oDiv[index].className = 'active'
         }
         new ChooseCard()
    </script>
命名空间

概念:当项目足够大,或者用了很多第三方框架,可能会出现命名不够用的情况,使用命名空间来解决这个问题

   var obj1 = {}
   var obj2 = {}
   obj1.name = 'zhangSan'
   obj2.name = 'liSi'
   console.log(obj1.name);
   console.log(obj2.name);
面向对象继承
  • 原型链继承
    • 原型链:从子对象开始Object.prototype为止中间由_ _proto _ _属性链接起来的一个链式结构就是原型链
    • 在原型链中每一个原型的属性最后都会继承给子对象
    • 原型链查找规则:当一个对象调用属性时,会先在当前对象中查找,有就用,没有 就向原型中查找,如果还没有就继续向上一级原型中查找,直到Object.prototype,如果有就用,没有就返回undefined
    • 缺点:由于继承的是原型链中的属性,因此属性的值无法修改
      原型链
        //构造奶奶函数
        function GrandMother(name,age){
            this.name = name
            this.age = age
        }
        //奶奶函数prototype找到爷爷原型
        GrandMother.prototype.money = '500w'
        //奶奶函数new了一个爸爸
        var father = new GrandMother('张三',24)
        //构造一个空的妈妈函数
        var mother = function(){}
        //妈妈函数prototype找到了爸爸原型
        mother.prototype = father
        //妈妈函数new了一个我
        var me = new mother()
        console.log(me)
        console.log(me.__proto__)
        console.log(me.__proto__.__proto__)
        //不能拥有属于我自己的名字和年龄
  • 对象冒充继承
    • call和apply:用来改变this指向
    • 用法:
      函数.call(要改变的this值,实参1,实参2,实参3………)
      函数.apply(要改变的this值,[实参1,实参2,实参3………])
    • 优势:可以随意改变属性的值
    • 缺点:不能继承原型链中的属性
      对象冒充继承
    //一代构造函数
    function First(name, age) {
      this.name = name
      this.age = age
    }

    //BadWoman
    function BadWoman() {
      console.log(this); //指向badwoman
      // First.call(this, '如花', 45)
      First.apply(this,['如花', 45])
    }

    var obj = new BadWoman()
    console.log(obj);
  • 组合(混合)式继承
    • 对象冒充+原型链继承
    • 小瑕疵:构造函数中的属性原型中也有,会有一个资源浪费的问题
      组合式继承
    /* 
      混合(组合)继承
      对象冒充+原型链
    */
    //大构造函数First
    function First(name, age) {
      this.name = name
      this.age = age
    }
    //大构造函数的原型
    First.prototype.money = '500W'
    //大构造函数的子对象
    var Second = new First('zhangSan', 18)
    //小构造函数
    function BadWoman() {
      First.apply(this, ['liSi', 6])
    }
    BadWoman.prototype = Second
    //实例化小构造函数的子对象
    var obj = new BadWoman()
    console.log(obj);
    console.log(obj.name);
    console.log(obj.age);
    console.log(obj.money);
  • 寄生混合式继承
    • 我们一般会创建一个空函数,然后这个空函数的原型指向父类的原型,再实例化这个空函数,赋给子的原型,再修改子对象constructor。将这个过程用一个函数包起来,这个函数接收两个参数,子类构造函数和父类构造函数。
      寄生混合式继承
     function fn(child, parent) {
      //child是badwoman子构造函数         parent是First父构造函数
      //1、创建空函数
      var F = function () {}
      //2、空函数的原型指向父类的原型
      F.prototype = parent.prototype
      //3、实例化这个空函数
      var obj = new F()
      //4、把实例化的空函数赋值给子原型
      child.prototype = obj
      //5、
      obj.constructor = child
    }
    //大构造函数First
    function First(name, age) {
      this.name = name
      this.age = age
    }
    //大构造函数的原型
    First.prototype.money = '500W'
    //大构造函数的子对象
    var Second = new First('zhangSan', 18)
    //小构造函数
    function BadWoman() {
      First.apply(this, ['liSi', 6])
    }
    fn(BadWoman, First)
    //实例化小构造函数的子对象
    var obj = new BadWoman()
    console.log(obj);
    console.log(obj.name);
    console.log(obj.age);
    console.log(obj.money);
  • 原型中的this指向构造函数
  • 事件中的this指向触发事件的元素
  • 一般函数this指向window
  • 构造函数this指向构造函数
  • 轮播图插件:link
  • momentjs官方文档:link
  • animate.css动画:link
  • cubic-bezier速度曲线:link
  • 阿里巴巴图标库:link
  • Font-awesome图标库:link
正则表达式
  • 正则对象RegExp
  • 概念:是对字符串操作的一种逻辑公式,就是用事先定义好的一些特殊字符,及这些特定字符的组合,组成一个‘规则字符串’,这个规则字符串用来表达对字符串的一种过滤逻辑。规定文本检索的内容,通常被用来检索、替换文本
  • 创建方式
    • 构造函数创建 :new RegExp(‘检索字符’,’修饰符’)
    • 字面量创建: /’检索字符’/’修饰符’
     //1、构造函数创建    new RegExp('检索字符','修饰符')
     var pat1 = new RegExp('hello')
     console.log(pat1);     //   /hello/
     //2、字面量创建      /检索字符/修饰符
     var pat2 = /hello/
     console.log(pat2);     //   /hello/
  • 修饰符
    • g:global 执行一个全局匹配
    • i:ignore Case 执行一个不区分大小写的匹配
    //1、g  全局
    var str = 'hello java,hello web,hello ui'
    var reg1 = /hello/
    var reg2 = /hello/g
    console.log(str.replace(reg1, '你好')); //你好 java,hello web,hello ui
    console.log(str.replace(reg2, '你好')); //你好 java,你好 web,你好 ui
    //2、i  不区分大小写
    var str = 'abcdefg'
    var reg1 = /C/
    var reg2 = /C/i
    console.log(str.search(reg1)); //-1
    console.log(str.search(reg2)); //2
  • 检索方法
    • 正则方法
      • test:检索字符串中是否包含在正则要检索的内容 (返回布尔值) reg.test(str)
      • exec:进行具体检索,检索到正则规定的内容返回一个数组 reg.exec(str)
    //test:检索字符串中是否包含正则要检索的内容(返回布尔值)
    console.log(reg1.test(str)); //true
    console.log(reg2.test(str)); //false
    //exec:进行具体检索,检索到正则规定的内容返回一个数组
    var reg3 = /e/
    console.log(reg3.exec(str)); //["e", index: 1, input: "hello world", groups: undefined]
    var reg4 = /m/
    console.log(reg4.exec(str)); //null
  • 字符串方法
    • replace替换正则匹配的字符串str.replace(reg)
    • split:按正则规定的内容拆成数组str.split(reg)
    • match返回正则匹配的内容,和exec一样str.match(reg)
    • search返回正则匹配的第一个字符串的位置,如果没有就返回 -1 str.search(reg)
    var s = 'ujiuye java'
    //replace
    var reg5 = /java/
    console.log(s.replace(reg5, 'web')); //ujiuye web
    //split
    //\s匹配空白字符、空格、制表符和换行符
    var reg6 = /\s/
    console.log(s.split(reg6)); //["ujiuye", "java"]
    //match
    var reg7 = /e/
    console.log(s.match(reg7)); //["e", index: 5, input: "ujiuye java", groups: undefined]
    //search
    var reg8 = /j/
    console.log(s.search(reg8));  //1
  • 元字符
    元字符
    //1、. 除换行符以为的任意字符
    var str = '\nweb'
    var reg = /./
    console.log(reg.exec(str)); //["w", index: 1, input: "↵web", groups: undefined]

    var str = 'abcde1234'
    var reg = /ab.....34/ig
    console.log(reg.exec(str)); //["abcde1234", index: 0, input: "abcde1234", groups: undefined]

    //2、 [ ]  匹配字符集中任意一个字符
    var str = 'm23'
    var reg = /[0-9]/ig
    console.log(reg.exec(str)); //["2", index: 1, input: "m23", groups: undefined]

    //6位银行卡密码
    var str = '369h56'
    var reg = /[0-9][0-9][0-9][a-z][0-9][0-9]/ig
    console.log(reg.exec(str)); //["369h56", index: 0, input: "369h56", groups: undefined]

    //3、 [^]匹配除字符集中的任意一个字符
    var str = "123"
    //匹配除0-9以外的任意字符
    var reg = /[^0-9]/ig
    console.log(reg.exec(str)); //null    因为123都是数字,都是0-9之内的数字

    //4、 \d 匹配数字
    var str = 'ab5'
    var reg = /\d/ig
    console.log(reg.exec(str)); //["5", index: 2, input: "ab5", groups: undefined]

    //5、 \D 匹配非数字
    var str = 'abc'
    var reg = /\D/ig
    console.log(reg.exec(str)); //["a", index: 0, input: "abc", groups: undefined]

    //6、 \w  匹配数字字母下划线
    var str = '%%%_'
    var reg = /\w/ig
    console.log(reg.exec(str)); //["_", index: 3, input: "%%%_", groups: undefined]

    //7、 \W  匹配非数字非字母非下划线
    var str = '%%%_'
    var reg = /\W/ig
    console.log(reg.exec(str)); //["%", index: 0, input: "%%%_", groups: undefined]

    //8、 \s 匹配空格
    var str = 'hello world'
    var reg = /\s/ig
    console.log(reg.exec(str)); //[" ", index: 5, input: "hello world", groups: undefined]

    //9、 \S 匹配非空格
    var str = 'hello world'
    var reg = /\S/ig
    console.log(reg.exec(str)); //["h", index: 0, input: "hello world", groups: undefined]

    //10、 \b单词边界
    var str = 'he is boy heisboy'
    var reg = /\bis\b/
    console.log(reg.exec(str)); //["is", index: 3, input: "he is boy heisboy", groups: undefined]

    //11、 \B非单词边界
    var str = 'he is boy heisboy'
    var reg = /\Bis\B/
    console.log(reg.exec(str)); //["is", index: 12, input: "he is boy heisboy", groups: undefined]
    console.log(str.replace(reg, 'mm')); //he is boy hemmboy
    var reg = /\bis\B/
    console.log(reg.exec(str)); //null

    //12、^以开头         ^a  以a开头
    var str = '123456'
    var reg = /^1\d\d\d\d\d/ig
    console.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]

    //13、$以结尾         a$  以a结尾
    var str = '123456'
    var reg = /\d\d\d\d\d6$/ig
    console.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]
    //以1开头,以6结尾
    var reg = /^1\d\d\d\d6$/ig
    console.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]
  • 量词
    量词
    //1、   ?匹配0个或者1个           f?匹配0个f或者1个f
    var str = 'abc'
    var reg = /a?/ig
    console.log(reg.exec(str)); //["a", index: 0, input: "abc", groups: undefined]

    //2、   *匹配0个或者多个          f* 匹配0个f或者多个f    尽可能多匹配
    var str = 'aaaaaaaaaabcaaaaa'
    var reg = /a*/
    console.log(reg.exec(str)); //["aaaaaaaaaa", index: 0, input: "aaaaaaaaaabcaaaaa", groups: undefined]

    //3、   +匹配至少一个           f+匹配至少一个f
    var str = 'abbbbbc'
    var reg = /b+/ig
    console.log(reg.exec(str)); //["bbbbb", index: 1, input: "abbbbbc", groups: undefined]
    //以a开头,中间放数字(至少一个数字),以数字结尾
    var str = "a1234"
    var reg = /^a\d+$/ig
    console.log(reg.exec(str)); //["a1234", index: 0, input: "a1234", groups: undefined]

    //4、   m{x,y}    匹配m,至少x次,最多y次        m{x}   匹配m,x次
    var str = '12345679'
    var reg = /^[0-9]\d{6,8}/ig
    console.log(reg.exec(str)); //["1234569", index: 0, input: "1234569", groups: undefined]
    //密码 6位数字
    var str = "123456"
    var reg = /^\d{6}$/ig
    console.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]
  • 其他
    其他
    //1、    |      或者
    var str = 'logo'
    var reg = /this|that|where|logo/ig
    console.log(reg.exec(str)); //["logo", index: 0, input: "logo", groups: undefined]

    //2、   ()      分组
    var str = "hello world hahaha hehehe"
    var reg = /(\w+) (\w+) (\w+) (\w+)/ig
    var arr = reg.exec(str)
    console.log(arr); //["hello world", "hello", "world", index: 0, input: "hello world", groups: undefined]

    console.log(RegExp.$1); //hello
    console.log(RegExp.$2); //world
    console.log(RegExp.$3); //hahaha
    console.log(RegExp.$4); //hehehe
    //需求:交换hello和world位置
    console.log(str.replace(reg, '$2 $1 $3 $4')); //world hello hahaha hehehe

    //3、  (?!^......)       预测不到后面不能是什么
    var str = '2222222'
    var reg = /(?!^\d+)/ig
    console.log(str.search(reg)); //1        //0表示符合条件      1表示不符合条件


    var str = '******'
    console.log(str.search(reg)); //0
    /* 
      ******      0  符合条件
      222222      1  不符合条件
     */
匿名函数
  • 概念:定义时未直接指定名称的函数,如果函数只需要调用一次,就可以声明匿名函数
  • 优点:节省内存空间。匿名函数可以有效的保证在页面上写入JavaScript,而不会造成全局变量的污染
    //1、普通函数
    function fn(){}
    //2、表达式函数
    var fn1 = function(){}
    //3、构造函数
    function Fn2(name){
      this.name = name
    }
    var Fn3 = function(name){
      this.name = name
    }
    //4、事件函数
    document.onclick = function(){}
    //5、回调函数
    function fn4(f){
      f&&f()
    }

	//匿名函数自执行      (函数)()
    (function(){
      console.log(111);
    })()

    //匿名函数有参数
    (function (a) {
      console.log(a); //6
    })(6)

    //匿名函数有返回值
    var f = (function (a) {
      return a * a
    })(6)
    console.log(f); //36
闭包
  • 概念:闭包就是能够读取其他函数内部变量的函数(函数里面套函数内部函数可以访问外部函数变量),在本质上,闭包是将函数内部和外部链接起来的桥梁
  • 特点:在闭包中的变量,会一直存储在内存中,类似于全局变量,避免了全局污染
  • 非必要情况下不要使用闭包,因为会一直存储在内存中,容易造成内存泄漏
    function fn1() {
      var i = 10
      function fn2() {
        console.log(i++);
      }
      return fn2
    }

    var f = fn1()
    console.log(f); //fn2这个函数
    f() //10
    f() //11
    f() //12

案例:

        var oLi = document.getElementsByTagName('li')
        //点击li打印对应的索引值
        for(var i=0;i<oLi.length;i++){
            /* oLi[i].index = i
            oLi[i].onclick = function(){
                console.log(this.index)
            } */

            /* //匿名函数
            (function(x){
                oLi[x].onclick = function(){
                    console.log(x)
                }
            })(i) */

            //闭包
            function f(x){
                oLi[x].onclick = function(){
                    console.log(x)
                }
            }
            f(i)
        }
ajax
  • Async Javascript and XML 异步js和XML代码
  • 异步:浏览器在请求数据的时候可以同时进行,不用排队等候,不会造成代码阻塞
  • 同步:浏览器在请求数据的时候不可以同时进行,需要排队等候
  • 概念:指一种创建交互式网页的网页开发技术
  • 传统的网页(不是用Ajax)如果需要更新内容,必须重载整个网页页面。通过在后台与服务器进行少量数据交互,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页 的情况下,对网页的某部分进行更新
  • ajax创建步骤
    • 实例化ajax对象var xhr = new XMLHttpRequest()
    • 建立连接xhr.open(请求方式,url地址(必传),是否异步)
      请求方式:get/post。url地址:后台服务器地址。第三个参数:默认为true(异步)false(同 步),一般不传
    • 发送请求xhr.send()
    • 接收响应数据xhr.onreadystatechange = function(){}
  • 通信状态码(ajax生命周期) xhr.readyState
    • 0:ajax对象还没创建出来
    • 1:建立起了和后台数据库的连接 open
    • 2:请求已经发送出去 send
    • 3:后台数据库接收到请求,并开始处理
    • 4后台数据库处理完毕,并将请求的数据响应给前端页面
      在本地请求数据,因为0和1持续时间过短,因此时间还没来得及触发状态码就直接变成2了
  • 网络状态码 xhr.status
    • 网络状态码整理:link
    • 200:请求响应成功,数据源是后台数据库
    • 304:请求响应成功,数据源是本地缓存
    • 403:没有权限访问
    • 404:服务器找不到请求的网页
    • 500及以上:后台代码逻辑有误
    • 503服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态
  • 获取响应的数据:xhr.responseText
  • get请求
    • 四部曲
      • 创建ajax对象
      • 建立连接
      • 发送请求
      • 通过事件监听响应状态来获取数据
    • 优点:在网络传输上速度相对较快
    • 缺点:
      • ①在提交数据时会直接显示在url地址的后面,不安全
      • get请求提交的数据量比较小,大小只有4kb左右
  • Wamp
    • windows Apache MySQL PHP
    • 这是一个服务器集成软件,安装完之后,计算机就会成为一台本地服务器
    • wamp文件夹中的www文件夹是用来存放项目的目录,我们需要使用服务器环境打开html文件,所以项目都需要存放在www文件夹中
    • 启动方式:在浏览器地址栏中输入 127.0.0.1(本地服务器)
  • post
    • 五部曲
      • 创建ajax对象
      • 建立连接
      • 设置请求头
      • 发送请求
      • 通过事件监听响应状态来获取数据
    • 请求头
      • ajax对象.setRequestHeader(“Content-type”,“application/x-www-form-url encoded”)
    • 优点:
      • 提交的数据不会显示在地址栏后面,相对较安全
      • 传输数据要比get大很多
  • json文件创建
    • ①Json文件不能添加注释
    • ②Json多余逗号要删除
    • ③数据一定要键值对形式
    • ④不能使用单引号,一定要是用双引号
    • ⑤数据由逗号分隔
    • 最外层只能有一个
    • 花括号表示保存对象
    • 方括号表示保存数组
  • 类型转换
    • eval(str) 传入一个字符串转化具体js的数据类型
    • JSON.parse(str)json类型字符串转换为json类型
    • JSON.stringify(obj) 将json类型转换为json类型字符串

封装ajax:

  <div></div>
  <script>
    var oDiv = document.getElementsByTagName('div')[0]

    function ajax(url, method, data, success) {
      //1、创建ajax对象
      var xhr = new XMLHttpRequest()
      //2、判断是get还是post
      if (method == 'get') {
        //判断data是否有值
        if (data) {
          url += '?' + data
        }
        xhr.open(method, url)
        xhr.send()
      } else {
        //建立连接
        xhr.open(method, url)
        //设置请求头
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
        //判断data是否有值
        if (data) {
          xhr.send(data)
        } else {
          xhr.send()
        }
      }
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200 || xhr.status === 304) {
            success(xhr.responseText)
          }
        }
      }
    }
    ajax('get.txt', 'post', 'username=admin', function (res) {
      console.log(res);
      oDiv.innerHTML = res
    })
  </script>
弹入弹出轮播图
  <div class="wrap">
    <div class="center">
      <ul></ul>
      <p></p>
    </div>
  </div>
  <script src="./ujiuye.js"></script>
  <script>
    var oUl = document.getElementsByTagName('ul')[0]
    var oP = document.getElementsByTagName('p')[0]
    var oLi = document.getElementsByTagName('li')
    var oSpan = document.getElementsByTagName('span')
    var wrap = document.getElementsByClassName('wrap')[0]
    ajax('banner.txt', 'get', '', function (res) {
      var arr = eval(res)
      console.log(arr);
      //定义一个字符串用来接收
      var str1 = ''
      var str2 = ''
      for (var i = 0; i < arr.length; i++) {
        str1 += '<li><img src="' + arr[i].bannerSrc + '"></li>'
        str2 += '<span></span>'
      }
      oUl.innerHTML = str1
      oP.innerHTML = str2
      //设置默认样式
      oLi[0].style.opacity = 1
      oSpan[0].className = 'active'
      wrap.style.background = arr[0].bannerBG
      //用来表示当前是第几张图片
      var bannerIndex = 0
      var timer1 = setInterval(bannerAuto, 3000)
      function bannerAuto() {
        bannerIndex++
        if (bannerIndex >= arr.length) {
          bannerIndex = 0
        }
        //上一张隐藏
        //1显示 0隐藏   2显示 1隐藏  3显示 2隐藏  4显示 3隐藏  5显示 4隐藏  0显示 0-1=-1 -1隐藏
        //bannerIndex - 1 > 0 ?  bannerIndex-1 : arr.length-1
        bufferMove(oLi[bannerIndex - 1 > 0 ? bannerIndex - 1 : arr.length - 1], {
          'opacity': 0
        })
        //下一张显示
        bufferMove(oLi[bannerIndex], {
          'opacity': 100
        })
        //改变背景
        wrap.style.background = arr[bannerIndex].bannerBG
        //改变span
        for (var i = 0; i < oSpan.length; i++) {
          oSpan[i].className = ''
        }
        oSpan[bannerIndex].className = 'active'
      }
      wrap.onmouseenter = function () {
        clearInterval(timer1)
      }
      wrap.onmouseleave = function () {
        timer1 = setInterval(bannerAuto, 3000)
      }
      //移入小span
      for (var i = 0; i < oSpan.length; i++) {
        oSpan[i].index = i
        oSpan[i].onmouseover = function () {
          //让之前的那一张隐藏
          bufferMove(oLi[bannerIndex], {
            'opacity': 0
          })
          //让对应的li显示
          bufferMove(oLi[this.index], {
            'opacity': 100
          })
          //改变小span
          for (var j = 0; j < oSpan.length; j++) {
            oSpan[j].className = ''
          }
          this.className = 'active'
          wrap.style.background = arr[this.index].bannerBG
          bannerIndex = this.index
        }
      }

    })
  </script>
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值