19.JS基础(五)

上一篇:18.JS基础(四)

JavaScript学习

BOM

BOM:Browser Object Model 浏览器 对象 模型

  • BOM提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window
  1. JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C
  2. BOM缺乏标准,BOM最初是Netscape浏览器标准的一部分
  3. 直到HTML5发布,W3C将 BOM 主要内容纳入了 HTML5 规范之中
  4. BOM是为了操作浏览器对象出现的API,window是其核心对象

原生对象与宿主对象

原生对象(本地对象):native object

  • ECMA所定义的对象
  • Number、String、Boolean、Object、Array、Function、Date、RegExp、内置对象(如 Math不需要实例化)、Error …

宿主对象:host object( 如 window、BOM、DOM )

  • 什么是宿主?
  • web的运行环境,即操作系统、浏览器
  • 宿主提供的对象 -> 宿主对象

window对象

window对象是浏览器中的Global对象

  • window.open() 方法打开一个页面,返回一个新窗口
var newWindow = window.open(URL,name,specs)
URL:打开页面的URL,没有指定URL将打开新的空白窗口
name:_blank  新窗口打开,默认
      _self  当前页面打开
      ......
specs:一个逗号分隔的项目列表。支持以下值:
            width=pixels    height=pixels  
	最小值为100
            left=pixels        top=pixels    ......
示例 window.open('','_blank','left=200,top=100,width=400,height=200');
  • window.close() 方法用于关闭浏览器窗口(只能关闭新打开的窗口)

  • window.resizeTo(width,height) 调整窗口大小

  • window.resizeBy(width,height) 调整窗口大小

  • 注:此功能在一些标签型浏览器中无效

  • window.scrollX 获取页面水平方向滚动的像素值

  • window.scrollY 获取页面垂直方向滚动的像素值

  • window.scrollTo(x,y) 方法可把页面内容滚动到指定的坐标

可以用来做固定窗口返回顶部操作

<botton id="btn">按钮</botton>
<script>
    btn.onclick = function (){
    window.scrollTo(0,0)//返回顶部
}  
</script>
  • window.screenLeft 属性返回窗口相对于屏幕的X坐标

  • window.screenTop 属性返回窗口相对于屏幕的Y坐标

  • window.screenX 属性返回窗口相对于屏幕的X坐标

  • window.screenY 属性返回窗口相对于屏幕的Y坐标

  • window.setInterval ( 函数/名称 , 毫秒数 )

    • 表示每经过一定的毫秒后,执行一次相应的函数(重复)

      //每隔两秒执行一次回调函数(重复执行)
      
      var timer1 = setInterval(function (){
      
        console.log( 12345 )
      
      },2000)
      
      console.log( timer1 )//1 计时器编号 计时器ID
      
    • 清除计时器:clearInterval(计时器编号/计时器ID)

      clearInterval(timer1)
      
  • window.setTimeout ( 函数/名称 , 毫秒数 )

    • 表示经过一定的毫秒后,只执行一次相应的函数(不重复)

      // 两秒一行执行一次回调函数(不重复执行)
      
      var timer2 = setTimeout(function (){
      
        console.log( 5678 )
      
      },2000)
      
      console.log( timer2 )//2 计时器编号 计时器ID
      
    • 清除计时器:clearTimeout( )

      clearTimeout(timer2)
      

    例题

    #box{
        width: 100px;
        height: 100px;
        position: absolute;
        left: 10px;
        top: 50px;
        background-color: red;
    }
    
    <div id="box"></div>
    <button id="btn">按钮</button>
    
    <script>
    btn.onclick = function (){
        var num = 10
        var timer = setInterval(function (){
            num += 5
            box.style.left = num + 'px'
            if (num >= 1000) {
                // 走到1000清楚计时器
                clearInterval(timer)
            }
        },30);
    }
    </script>
    
  • 提示框 alert (“ ”);

    • 用户必须先关闭该消息框然后才能继续进行操作

      alert('你傻吗?') // 警告弹窗
      
  • 确认框 confirm(“ ”);

    • confirm(“需要确认的内容”);

    • 选择“确定”返回true

    • 选择“取消”返回false

      var res = confirm('您输入的内容未保存,您确定要离开码?') // 确认弹窗
      
  • 输入框 prompt(“ ”,“ ”);

    • prompt(“对话框的提示文本”,“默认的输入文本”);

    • 单击取消,则返回 null;单击确认,则返回输入的文本

      var res = prompt('请输入内容','') // 输入弹窗
      

history对象

history对象包含有关用户的访问历史记录

  • length 返回浏览器历史列表中的 URL 数量

  • forward() 加载 history 列表中的下一个 URL

  • back() 加载 history 列表中的上一个 URL

  • go() 加载 history 列表中的某个具体页面

    • history.go(-1) 后退一页

    • history.go(1) 前进一页

  • 练习:

    • 由页面a跳转到页面b,5秒后自动返回页面a,也可点击立即返回

      //页面a
      <botton id="bot">点击</botton>
          <script>
                      bot.onclick = function(){
                          location.href = "./72 历史记录跳转2.html"
                      }
          </script> 
      
      //页面b
      <body>
          你猜不猜啊
          <botton id="but">点击</botton>
          <script>
                  but.onclick = function(){
                      location.href(history.go(-1))
                   }
                      var times = 5 ;
                           var mm = setInterval(function(){
                              times -=1;
                              console.log(times + "s后返回上一页")
                               if(times <=0){
                              location.href(history.go(-1))
                              clearInterval(mm)
                          }
                          },1000)
          </script>
      </body>
      

location对象

location对象包含有关当前页面的URL信息

  • host 属性设置或返回主机名和当前 URL 的端口号

  • port 属性设置或返回当前 URL 的端口号

  • href 属性设置或返回完整的 URL ……

    console.log( location.href )// 当前页面的URL地址location.href = './myblog.html' // 跳转到指定页面location.href = 'https://www.baidu.com/' // 跳转到指定页面
    
  • search 属性设置或返回URL查询字符串

    console.log( location.search )
    
  • assign() 方法加载新的文档

  • reload()方法重新加载当前文档(刷新)

    btn1.onclick = function(){
                    windon = location.reload()       //慎用
                }
    
  • replace() 方法用新的文档替换当前文档---->刷新

navigator对象

navigator对象用于提供与用户浏览器相关的信息

  • appCodeName 属性返回浏览器的代码名

  • appName 属性返回浏览器的名称

  • cookieEnabled 属性返回指明浏览器中是否启用cookie的布尔值

  • platform 属性返回运行浏览器的操作系统平台

  • appVersion 属性返回浏览器的平台和版本信息

  • userAgent 属性返回用户浏览器发送服务器的user-agent头部的值

识别浏览器

var str1=window.navigator.userAgent;
var str2=window.navigator.appVersion;

结合indexOf( )和toLowerCase( )方法可识别用户浏览器

screen对象

screen对象包含有关客户端显示屏幕的信息

  • width 属性返回显示器屏幕的宽度
  • height 属性返回显示器屏幕的高度
  • availHeight 属性返回显示屏幕的高度 (除 Windows 任务栏之外)
  • availWidth 属性返回显示屏幕的宽度 (除 Windows 任务栏之外)

document对象

  • document 对象是 Window 对象的一部分
  • 可通过 window.document 属性对其进行访问
  • 每个载入浏览器的 HTML 文档都会生成 document 对象
  • document 对象与它所包含的各种节点构成了早期的文档对象模型(DOM 0级)
  • document:包含整个 HTML 文档,可被用来访问文档内容及其所有页面元素

DOM

  • DOM:Document Object Model 文档 对象 模型
  • DOM是针对HTML和XML文档的API
  • DOM描绘了一个层次化的节点树,即HTML文档中的所有内容都是节点(node)
  • DOM树中的所有节点均可通过JS进行访问,允许开发人员添加、移除、修改和查询页面的某一部分

在这里插入图片描述

节点类型

  1. 整个文档是一个文档节点
  2. 每个HTML元素是元素节点
  3. HTML元素内的文本是文本节点(回车也是文本节点)
  4. 每个HTML的属性是属性节点
  5. 注释是注释节点

获取元素节点

  1. document.getElementById(‘’); 单个元素
  2. document.getElementsByName(‘’); 元素集合(表单元素)
  3. document.getElementsByTagName(‘’); 元素集合
  4. document.getElementsByClassName(‘类名’); 元素集合
  5. document.querySelector(‘css选择器’); 单个元素
  6. document.querySelectorAll(‘css选择器’); 元素集合
  • 元素集合的 length 属性表示集合中元素的个数

元素节点的值

  • innerHTML 设置或返回元素标签内的所有内容(包含html)
  • innerText 设置或返回元素标签内的所有内容(不包含html)
  • value 设置或返回表单元素的值
  • textContent 设置或返回指定节点的文本内容(IE678不支持)

元素节点的样式

  • 元素节点都有一个style属性,style是一个样式对象,用于访问或设置css样式
  • dom.style.属性 = 值;
  • dom.style.cssText = ‘属性:值; 属性:值;’
  • dom.className = ‘类名’

nodeType 属性

返回一个整数,这个数值代表节点的类型

  • 元素节点 返回 1
  • 属性节点 返回 2
  • 文本节点 返回 3
  • 注释节点 返回 8
  • 文档节点 返回 9

nodeName 属性

返回节点的名称

  • 元素节点的 nodeName 是标签名称 ( 大写 )
  • 属性节点的 nodeName 是属性名称
  • 文本节点的 nodeName 永远是 #text
  • 注释节点的 nodeName 永远是 #comment
  • 文档节点的 nodeName 永远是 #document

tagName 属性

返回元素节点的标签名

  • 在 HTML 中,tagName 属性的返回值始终是大写的

nodeValue 属性

返回节点的值

  • 对于元素节点,nodeValue 返回值是 undefined 或 null
  • 对于文本节点,nodeValue 返回文本内容
  • 对于属性节点,nodeValue 返回属性值
  • 对于注释节点,nodeValue 返回注释内容
  • 对于文档节点,nodeValue 返回 null
    元素节点使用innerHTML、innerText、value取值

节点关系

  • 节点之间的关系,通常用家庭中的辈分关系来描述
  • 祖先 -> 父辈 -> 子女(兄弟姐妹) -> 子孙

在这里插入图片描述

  1. parentNode:返回父节点

  2. children:返回所有元素子节点

  • IE678 可以获取到注释节点,在IE678这样获取的时候注意不要写注释
  1. childNodes:所有子节点 ,IE678与高版本浏览器返回值不一样
  • 高版本浏览器返回文本节点(回车),IE678返回元素节点
  1. nextSibling:下一个兄弟节点
  2. previousSibling:上一个兄弟节点
  3. firstChild : 第一个子节点
  4. lastChild:最后一个子节点
  • 高版本浏览器返回元素节点,IE678不支持
  1. nextElementSibling
  2. previousElementSibling
  3. firstElementChild
  4. lastElementChild

节点方法

案例:
<div class="box">
        <p class="p1">好玩的游戏!</p>
        <p>
                用户名:<input type="text" value="oppo" class="p2">
        </p>
        <p>1</p>
        <p>2</p>
        <p>3</p>
        <ul>
            <li class="list1" haha="哈哈">list1</li>
            <li class="list2">list2</li>
            <li class="list3">list3</li>
        </ul>
    </div>
//在js中操作HTML,先声明
var ul = document.querySelector(".box ul")
  1. createElement(“标签名”) 创建元素节点

         var list = document.createElement("li")
    
  2. createTextNode(“”) 创建文本节点

    var txt=document.createTextNode('-list25-');
    
  • 父元素调用

    1. appendChild(node) : 末尾插入一个节点node

      ul.appendChild(list) 
      
    2. insertBefore(newNode,target) : target之前插入节点node

      ul.insertBefore(list,ul.children[2])
      
    3. removeChild(node) : 移除某个子节点

      ul.removeChild(ul.children[1])
      
    4. replaceChild(newNode,oldNode) : newNode替换oldNode

      ul.replaceChild(list,ul.children[2])
      
  1. cloneNode(boolean) : 复制一个节点

    • true:深复制,复制节点及其整个子节点树

      var list1 = ul.cloneNode(true)
      
    • false : 浅复制,只复制节点本身

      var list2 = ul.cloneNode(false)
      
    • 注:不会复制添加到DOM节点中的JS属性,例如事件处理程序等

  2. getAttribute(“name”) 获取节点上name属性的值

    //ul的第一个li元素上的自定义属性hehe
    console,log(ul.children[0].getAttribute("hehe"))  //输出 呵呵
    
  3. setAttribute(“name”,“value”) 设置节点上name属性的值为value

    ul.children[0].setAttribute("haha",哈哈)//添加新属性与值
    ul.children[0].setAttribute("hehe",呵呵)//修改原有属性的值
    
  4. removeAttribute(“name”) 删除节点上的name属性

    ul.children[0].removeAttribute("class")//删除自动属性
    ul.children[0].removeAttribute("haha")//删除自定义的属性
    
  5. getAttributeNode(“type”) 获取节点上type属性节点

    console.log(ul.children[0].getAttributeNode("haha")) //输出:haha="哈哈"
    
  6. dom.remove() 删除dom节点(IE不支持)

    
    

    拓展:

    1. dom对象自带属性,可以直接访问

      console.log( boxs[0].id )
      
      console.log( boxs[0].className )
      
      console.log( boxs[0].title )
      
    2. 元素自定属性不能直接访问

      console.log( boxs[0].hehe )// undefined
      console.log( boxs[0]['data-index'] )// undefined
      
    3. html和body可以不获取直接用

    document.documentElement == document.querySelector('html')
    
    document.body == document.querySelector('body')
    

documentFragment

  • documentFragment是一个文档碎片,是一种‘轻量级节点’,是一个虚拟的节点对象

  • documentFragment的nodeType值为11,nodeName的值为#document-fragment

  • 通常作为仓库来使用,不存在DOM树上,将多个需要插入的新节点放在文档碎片上,再插入文档中可以优化DOM操作

  • 虚拟的节点对象,包含节点的所有属性和方法

  • 创建一个文档碎片(空容器)
    var fragment = document.createDocumentFragment()

  • 将新节点插入文档碎片
    fragment.appendChild(newNode)

  • 将文档碎片插入box节点中
    box.appendChild(fragment)

    例题:在ul中插入30个li

    <ul class="ul">
        <!--<li>商品1</li>
    		<li>商品2</li>
    		<li>商品3</li> -->
    </ul>
    <script>
        // 获取ul节点
        var ul = document.querySelector(".ul");
    	//创建li元素节点
    	var list = document.createElement("li");
    	//给list新节点赋值
    list.innertext = "商品X";
    	//创建一个文档碎片
        var wap = document.createDocumentFragment();
    	//插30个,需要循坏
    	for(var i = 0;i < 30;i++){
            //在最后一个li插入新的list节点
            wap.appendChild(list)
        }
    </script>
    

获取元素样式

在js中元素的样式有两种:行间样式与非行间样式

// 1. 行间样式:
<div id="box1" style="width:300px; height:100px;"></div>
console.log(box1.style.width);

// 2. 非行间样式:
#box2 {width: 200px; height: 50px;}
<div id="box2"></div>
console.log(box2.style.width);
  1. getComputedStyle:获取样式(IE678除外)
  • 如:getComputedStyle(dom对象,参数).样式
  • 第一个参数是要获取样式的元素对象
  • 第二个参数可以传递任何数据,通常为false或null或空
  1. currentStyle:IE678获取样式的方法
  • 如:dom.currentStyle.样式

练习:

  • 自己封装获取元素样式的函数(注意兼容问题)

    // 如何解决兼容问题?
    // 获取元素样式(兼容IE678)
    function getStyle(dom,style){
        if (dom.currentStyle) {
            //  IE678
            return dom.currentStyle[style]
        } else {
            // 非IE678
            return getComputedStyle(dom)[style]
        }
    }
    
    console.log( getStyle(box1,'height') )
    console.log( getStyle(box2,'height') )
    

offset/client系列属性

  • offsetLeft:获取对象左侧与定位父级之间的距离(默认是body)

  • offsetTop:获取对象上侧与定位父级之间的距离(默认是body)

  • offsetWidth:获取元素自身的宽度(包含边框和 padding)

  • offsetHeight:获取元素自身的高度(包含边框和 padding)

  • offsetParent:返回元素的定位父级

  • clientWidth:获取元素自身的宽度(不含边框)

  • clientHeight:获取元素自身的高度(不含边框)

  • clientLeft、clientTop:获取元素内容到边框的距离,效果和边框宽度相同,很少使用

  • document.body.offsetWidth body的宽度(包含边框)

  • document.body.offsetHeight body的高度(包含边框)

  • document.body.clientWidth body的宽度(不含边框)

  • document.body.clientHeight body的高度(不含边框)

  • document.documentElement.offsetWidth html文档的宽

  • document.documentElement.offsetHeight html文档高度

  • document.documentElement.clientWidth 浏览器可视区宽度(不含滚动条位置)

  • document.documentElement.clientHeight 浏览器可视区高度(不含滚动条位置)

其他

  • window.innerWidth 浏览器可视区宽度(含滚动条位置)

  • window.innerHeight 浏览器可视区高度(含滚动条位置)

  • document.documentElement.scrollWidth 网页正文全文宽,包括滚动条未见区域

  • document.documentElement.scrollHeight 网页正文全文高,包括滚动条未见区域

事件

  • 事件指的是文档或者浏览器窗口中发生的一些特定交互瞬间
  • 事件是可以被 JavaScript 侦测到的行为
  • 事件可以提高网页的交互性
  • 事件通常与函数配合使用,当事件发生时执行对应的函数
  • 事件驱动(事件触发时,驱动函数执行)

常见的事件类型

  • blur 元素失去焦点,方法 blur()

    user.onblur = function (){//失去焦点时触发
    
      console.log( '失去焦点' )
    
    }
    
  • focus 元素获得焦点,方法 focus()

    user.onfocus = function (){//获得焦点时触发
    
      console.log( '获得焦点' )
    
    }
    
  • input 用户输入时触发

    user.oninput = function (){// 用户输入时触发
    
      console.log( '输入值' )
    
    }
    
  • change 用户改变域的内容(值改变时触发)

    user.onchange = function (){// 输入的值改变时触发
    
      console.log( '值改变' )
    
    }
    
  • ###click 鼠标左键点击某个对象

    document.onclick = function (){
    
      console.log( '右击事件' )
    
    }
    
  • dblclick 鼠标双击某个对象

    documeny.ondblclick = function(){
        console.log('双击事件')
        
    }
    
  • contextmenu 鼠标点击右

    document.oncontextmenu = function (){
    
      console.log( '右击事件' )
    
    }
    
  • keydown 键盘某个键被按下(所有键)

    document.onkeydown = function (){
    
      console.log( '键盘按键按下' )
    
    }
    
  • keypress 键盘某个键被按下(不包括系统功能键,如箭头键,ctrl,F1,F2等)
     document.onkeydown = function (){
     
       console.log( '键盘按键按下' )
     
     }
    
  • keyup 键盘某个键被松开
    document.onkeyup = function (){
    
      console.log( '键盘按键抬起' )
    
    }
    
  • mousedown 某个鼠标按键被按下
    document.onmousedown = function (){
    
      console.log( '鼠标按下' )
    
    }
    
  • mousemove 鼠标在某元素上移动
    document.onmousemove = function (){
    
      console.log( '鼠标在某元素上移动' )
    
    }
    
  • mouseup 某个鼠标按键被松开
    document.onmouseup =function(){
    
    	console.log('鼠标松了')
    
    }
    
  • mouseenter 鼠标进入某元素
    user.onmouseenter = function (){
    
      console.log( '鼠标进入' )
    
    }
    
  • mouseleave 鼠标从某元素移开
    user.onmouseleave = function (){
    
      console.log( '鼠标离开' )
    
    }
    
  • mouseover 鼠标移到某元素之上(冒泡)
    user.onmouseover = function (){
    
      console.log( '鼠标进入' )
    
    }
    
  • mouseout 鼠标从某元素移开(冒泡)
    user.onmouseout = function (){
    
      console.log( '鼠标离开' )
    
    }
    
  • submit form提交时触发
    这个事件是form表单的
    // 当我们点击input登录时,触发的是form元素的submit事件
    
    form.onsubmit = function (){
    
      console.log( '表单提交' )
    
    }
    
  • load 某个页面或图像被完成加载
    var img = document.querySelector('img')
    
    //console.log( img.clientWidth )// 0
    
    img.onload = function (){
    
      console.log( '图片加载完成时触发' )
    
      console.log( img.clientWidth )// 1200
    
    }
    

事件模型

  • 事件模型主要讲的是事件的注册、解除及事件的流向/执行顺序
  • JavaScript中的两种事件模型:DOM 0级事件模型 和 DOM 2级事件模型

DOM 0级事件模型

  • DOM0级事件模型是早期的事件模型,所有的浏览器都支持

  • 注册事件:在事件类型前面加on,如:onclickonmouseover

  • 解除事件:dom.onclick = null

    var remove = document.querySelector('.remove')
    remove.onclick = function (){
        console.log( '移除事件' )
        btn1.onclick = null // 移除btn的点击事件
    
  • 在DOM 0级事件模型中,每个DOM对象只能注册一个相同类型的事件,注册多个则会发生覆盖,只执行最后一个

DOM2级事件模型

  • DOM2级事件模型是较新的事件模型,IE678不支持的

  • 注册事件:

    function fn2(){
        console.log( 'btn2 2' )
    }
    btn2.addEventListener('click',fn2,false)
    

    addEventListener(type,fn,useCapture) 事件监听器

    • type----事件类型,例:click、mouseover…
    • fn----事件处理函数
    • useCapture----布尔值,默认false
    • ( true表示事件捕获,false表示事件冒泡 )
  • 解除事件:removeEventListener(type, fnName, useCapture)

    remove.onclick = function (){
        console.log( '移除事件' )
        // btn1.onclick = null // 移除btn的点击事件
        // btn2.removeEventListener('click',function (){
        //     console.log( 'btn2 2' )
        // })// 不能移除事件,因为这里要移除的函数和添加事件的函数不是同一个
    
        btn2.removeEventListener('click',fn2)
    }
    
  • 每个DOM对象可以注册多个相同类型的事件,会依次执行,不会发生覆盖

  • IE678不支持addEventListener,但提供自己的实现方式:

  • 注册事件:attachEvent( type , fn )

    • type----事件类型,例:onclick、onmouseover
    • fn----事件处理函数
    • 没有第三个参数
  • 解除事件:detachEvent( type , fnName )

练习:封装事件监听/移除函数(兼容IE678)?
function addEvent(){}
function removeEvent(){}

<button id="btn">点击</button>
    <script>
        btn.onclick = function(){
            if(btn.addEventlistener){
                btn.addEventlistener("click",function(){},false)
            }else {
                btn.attachEvent(onclick,function(){})
            }
        }
// 移除事件监听(兼容IE678)
function removeEvent(dom,type,fnName){
    if (dom.detachEvent) {
        // IE678
        dom.detachEvent('on'+type,fnName);
    } else {
        // 非IE678
 dom.removeEventListener(type,fnName,false);
    }
}

触发事件

  • 事件通常与函数结合使用,函数不会在事件触发前被执行
  • BUT,我们也可以主动触发事件
// DOM 0级事件模型
btn.onclick = function(){ 
    console.log("btn被点击1")
}
btn.onclick()// 触发事件

// DOM 2级事件模型
btn.addEventListener("click", function(){
    console.log("btn被点击2")
})
// 创建一个事件对象
var e = new Event("click")
// 触发元素的一个事件
btn.dispatchEvent(e)

事件流

  • 事件流:事件的流向,事件的执行顺序

  • 子元素和父元素都定义了相同的事件,比如都定义了click事件,当点击子元素时,父元素的click事件也会被触发,JS里称这种事件连续发生的机制为事件冒泡事件捕获

  • IE:事件从里向外发生,事件从最精确对象(target)开始触发,然后到最不精确的对象(document)触发,即事件冒泡

  • 网景:事件从外向里发生,事件从最不精确的对象(document)开始触发,然后到最精确对象(target)触发,即事件捕获

  • W3C将两者进行中和,在标准W3C的事件模型中,事件先进入捕获阶段,再进入冒泡阶段

在这里插入图片描述

不管是事件冒泡,还是事件捕获,都有 '传播' 的特征!!

事件对象

  • 当事件触发时,事件处理函数将被执行
  • 在事件处理函数中,可以获取到一个与事件相关的对象,即事件对象(event对象)
  • event对象中包含了所有与事件相关的信息,如:
    1. 获取键盘按下的按键码
    2. 获取鼠标的位置坐标
    3. 获取事件名称
    4. 获取事件生成的时间
    5. 获取事件的类型
    6. 等等…

获取event对象

  • 所有浏览器都支持event对象,只是支持的方式不一样
  • FireFox、Chrome等浏览器要获取到event对象,需要从函数中传入,参数名随意
  • 而IE在浏览器中event作为window对象的一个属性存在,可以直接使用 event
// 例如:
document.onmousedown=function ( e ){
    var ev = e || window.event  //兼容各个浏览器
    console.log(ev)
}
// 注意 var ev = e || event  顺序!

常用的属性方法

  • clientX/clientY 返回当事件被触发时,鼠标指针的坐标(到浏览器窗口的坐标)

  • offsetX/offsetY 返回当事件被触发时,鼠标指针的坐标(在事件源中的坐标) IE

  • pageX/pageY 返回当事件被触发时,鼠标指针的坐标(整个页面中的坐标) 火狐

  • button 返回触发事件的鼠标按键

  • which 返回触发事件的按键码(针对键盘和鼠标事件) 火狐

  • keyCode 返回键盘按键的按键码(ASCII码) IE

  • 组合键:ctrlKey、altKey、shiftKey、metaKey

  • 触发事件的元素,叫事件目标(事件源)

    属性 event.target 指向事件目标

  • 在IE中使用:event.srcElement 指向事件目标

    兼容写法 target = event.target || event.srcElement

  • event.relatedTarget 获取触发事件的目标源,与target相反

  • event.fromElement IE获取触发事件的目标源,与srcElement相反

  • 在mouseover事件中,它指向鼠标来自哪个元素

  • 兼容写法 from = event.relatedTarget || event.fromElement

  • event.relatedTarget 获取触发事件的目标源,与target相反

  • event.toElement IE获取触发事件的目标源,与srcElement相反

  • 在mouseout事件中,它指向鼠标去往的那个元素

  • 兼容写法 to = event.relatedTarget || event.toElement

  • 阻止默认行为

  • 标准:event.preventDefault()

  • IE:event.returnValue = false

  • 兼容写法 event.preventDefault ? event.preventDefault() : (event.returnValue = false)

  • 也可以在函数中使用 return false 来阻止默认行为

  • 阻止事件传播

  • 标准:event.stopPropagation()

  • IE:event.cancelBubble = true

  • 兼容写法 event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true)

事件委托

  • 什么是事件:通俗讲click,mouseenter,mouseleave等就是事件
  • 什么是委托:一个事件本来是加在某些元素上的,而你却加到其他元素上来完成这个事件
  • 事件委托就是事件目标自身不处理事件,而是把处理事件委托给其父辈元素来完成
  • 子元素把事件委托给父辈元素来完成

原理:利用事件传播的特征

  • 事件委托的优点:

    1. 提高性能和效率

    2. 减少事件注册,节省内存占用

    3. 未来元素无需再次注册事件

    4. document.body.onclick = function (ev){
          // console.log( 'body被点击' )
          var e = ev || window.event
          // 判断哪些是你想要的点击行为
          // console.log( this )// body
          // console.log( e.target )// 点击谁就指向谁
          if (e.target.tagName === 'BUTTON'&&e.target.className === 'add') {
              // var newLi = document.createElement('li')
              // newLi.innerText = '新的li'
              // list.appendChild(newLi)
              list.innerHTML += "<li> li X</>" 
          }
      
          if (e.target.tagName === 'LI'&&e.target.parentNode.className === 'list') {
              e.target.style.backgroundColor = 'blue'
          }
      }
      

鼠标滚轮事件

 需求:在box上滚动鼠标滚轮时,放大(前推)或缩小(后拉)box

// 获取用户浏览器相关的信息并转成小写字母
var userAgent = navigator.userAgent.toLowerCase()
// 把火狐浏览器判断出来
if (userAgent.indexOf('firefox')!==-1) {
    // 是火狐浏览器
    box.addEventListener('DOMMouseScroll',function (e){
        // console.log( e )
        // console.log( e.detail )// 前推 -4  后拉 4
        if (e.detail < 0) {
            // 前推 放大box
            box.style.width = box.clientWidth+20+'px'
            box.style.height = box.clientHeight+20+'px'
        } else {
            // 后拉 缩小box
            box.style.width = box.clientWidth-20+'px'
            box.style.height = box.clientHeight-20+'px'
        }
    })
} else {
    // 非火狐浏览器
    box.onmousewheel = function (ev){
        // console.log( '鼠标滚轮事件' )
        var e = ev || window.event
        // console.log( e )
        // console.log( e.wheelDelta )// 前推 120  后拉-120
        if (e.wheelDelta > 0) {
            // 前推 放大box
            box.style.width = box.clientWidth+20+'px'
            box.style.height = box.clientHeight+20+'px'
        } else {
            // 后拉 缩小box
            box.style.width = box.clientWidth-20+'px'
            box.style.height = box.clientHeight-20+'px'
        }
    }
}

scroll 滚动条

  1. scrollLeft:设置或获取当前左滚的距离,即左卷的距离
  2. scrollTop:设置或获取当前上滚的距离,即上卷的距离
  3. scrollHeight:获取对象可滚动的总高度
  4. scrollWidth:获取对象可滚动的总宽度
  • 获取页面的滚动条:

    var pageScroll = document.body.scrollTop //谷歌(低版本)
    var pageScroll = document.documentElement.scrollTop //火狐 IE
    
  • onscroll 事件,元素滚动条在滚动时触发

Math 对象

  • Math 对象用于执行数学任务
  • Math是一个内置对象,不需要创建,可以直接使用

Math对象常用API:

  1. Math.PI --------------返回圆周率3.1415926…
  2. Math.ceil(x) ----------对数值x进行向上取整
  3. Math.floor(x) --------对数值x进行向下取整
  4. Math.round(x) -------对数值x进行四舍五入取整
  5. Math.abs(x) ----------返回x的绝对值
  6. Math.pow(x,y) --------返回x的y次方
  7. Math.sqrt(x) ----------返回x的平方根
  8. Math.min(a,b,c…) ----返回abc…中的最小值
  9. Math.max(a,b,c…) ----返回abc…中的最大值
  10. Math.random() --------返回介于[0,1)之间的随机数

注意:Math.random() 理论上能得到0,实际使用几乎不可能得到0

  • 如何得到 0 ~ 1 的随机整数[0,1]?

  • 如何得到 0 ~ 5 的随机整数[0,5]?

  • 如何得到 5 ~ 10 的随机整数[5,10]?

  • 如何得到 8 ~ 24 的随机整数[8,24]?

  • 写一个函数 randomInt(min,max) 随机生成[min,max]区间的整数?

三角函数

  • Math.sin(x) ----- 返回x的正弦
  • Math.cos(x) ----- 返回x的余弦
  • … …
    sinα = a/c
    cosα = b/c
    x 是弧度
  • 一个角,可以用度数来表示,也可以用弧度来表示
  • 弧度更加符合计算机的计算模式
  • 【60°=π / 3】,【90°=π / 2】,【180°=π】,【360°=2π】
  • 弧度 = 角度 × π / 180

怎么应用到代码里面?

  • var angle = 60; //60度角
  • var radian = angle * Math.PI / 180; //计算出弧度

案例:图形和动画:在编写动画或者游戏的时候,可能需要用到三角函数来计算旋转、移动路径等。例如,创建一个围绕某点旋转的动画,可以用三角函数计算各个时间点的 x,y 坐标。

let angle = 0;
let centerX = 100; // 圆心x坐标
let centerY = 100; // 圆心y坐标
let radius = 50;   // 半径
setInterval(function () {
    let x = centerX + radius * Math.cos(angle);
    let y = centerY + radius * Math.sin(angle);
    angle += 0.01;
    // 然后在画布的 (x, y) 处绘制图像
}, 100);

物理模拟:在做物理模拟时,常常需要利用到三角函数。例如,做一个投射运动的模拟,当知道初速度和投射角度时,可以使用三角函数计算在不同的时间点物体的位置。

// 初始位置
let x = 0;
let y = 0;

// 初始速度
let v = 10;

// 抛射的角度,假设为45度
let angle = 45;

// 速度的x与y分量
let vx = v * Math.cos(angle * Math.PI / 180);
let vy = v * Math.sin(angle * Math.PI / 180);

// 重力加速度
let g = 9.8;

// 时间间隔
let dt = 0.1;

// 运动过程
for (let t = 0; t <= 2 * vy / g; t += dt) {
    // 时间 t 时的位置
    x = vx * t;
    y = vy * t - 1/2 * g * t * t;

    console.log("时间: " + t.toFixed(2) + " sec, 位置: (" + x.toFixed(2) + ", " + y.toFixed(2) + ")");
}
/**
	这个程序模拟了一个物体以10m/s的速度,45度角抛出,并打印出每个时间t的位置。
	注意这里我们假设了物体是在无阻力的情况下运动的,实际情况下可能需要考虑空气阻力等因素,计算会复杂一些。
	此外,也请注意 JavaScript 中的 Math.sin 和 Math.cos 函数接收的参数是以弧度为单位的,
	所以我们需要将角度转换为弧度,即:角度 * π / 180
*/	

计算两点间距离和角度:这是一个经常遇到的问题,例如在地图应用中。当我们知道两点在地球上的经纬度后,可以使用三角函数来计算这两点之间的距离或者方向角。
在二维平面上,计算两点间的距离和角度的公式如下:
距离公式: d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 距离公式:d=\sqrt{(x_2 - x_1)^2+(y_2 - y_1)^2} 距离公式:d=(x2x1)2+(y2y1)2
角度公式: α = arctan ⁡ ( ( y 2 − y 1 ) / ( x 2 − x 1 ) ) 角度公式:\alpha = \operatorname{arctan}((y_2-y_1)/(x_2-x_1)) 角度公式:α=arctan((y2y1)/(x2x1))
下面是使用这两个公式的JavaScript代码示例:

function calculateDistanceAndAngle(x1, y1, x2, y2) {
    // 计算距离
    let dx = x2 - x1;
    let dy = y2 - y1;
    let distance = Math.sqrt(dx*dx + dy*dy);


    // 计算角度
    // 注意:在javascript中,Math.atan的结果范围是-pi/2到pi/2
    // 这意味着你可能需要根据dx和dy的符号调整角度
    let angle = Math.atan2(dy, dx) * 180 / Math.PI;

    return {
        distance: distance,
        angle: angle
    };
}

let point1 = {x: 0, y: 0};
let point2 = {x: 1, y: 1};

let result = calculateDistanceAndAngle(point1.x, point1.y, point2.x, point2.y);

console.log("Distance: " + result.distance);
console.log("Angle: " + result.angle);
/**
	注意在这个示例中,我们用 Math.atan2(dy, dx) 函数而不是 Math.atan(dy/dx) 函数来计算角度,
	因为 Math.atan2 能够正确处理 dx = 0 的情况,并且给出完整的 -π 到 π 范围的角度。
*/
  • 练习:
    1. 随机生成[min,max]区间的整数
    2. 随机生成十六进制颜色字符串
    3. 随机生成四位验证码(字母数字组合)

Date 对象

  • Date 对象用于处理日期与时间
  • Date 对象自动使用当前系统的日期和时间作为其初始值

创建Date对象:

var d = new Date()
console.log(d)
// Tue Apr 30 2019 00:45:42 GMT+0800 (中国标准时间)
  • UTC国际标准时间又称世界时,以零经度线上的时间作为国际上统一采用的标准时间
  • 因为零经度线通过英国格林尼治天文台,所以国际标准时间也称为格林尼治时间GMT
  • 国际标准时间的起点:1970/01/01 00:00:00
  • 北京时区的时间起点:1970/01/01 08:00:00
  • 所以,北京时间 = 国际标准时间 + 8小时

获取日期时间:

var d = new Date()
  1. getFullYear()------从 Date 对象以四位数字返回年份
console.log( d.getFullYear() )  //2021
  1. getMonth()---------从 Date 对象返回月份 (0 ~ 11)
console.log( d.getMonth() ) //5
  1. getDate()----------从 Date 对象返回一个月中的某一天 (1 ~ 31)
console.log( d.getDate() )//1
  1. getHours()---------返回 Date 对象的小时 (0 ~ 23)
console.log( d.getHours() )//18
  1. getMinutes()-------返回 Date 对象的分钟 (0 ~ 59)
console.log( d.getMinutes() )//21
  1. getSeconds()-------返回 Date 对象的秒数 (0 ~ 59)
console.log( d.getSeconds() ) //34
  1. getMilliseconds()–返回 Date 对象的毫秒(0 ~ 999)
console.log( d.getMilliseconds() )
  1. getDay()-----------从 Date 对象返回一周中的某一天 (0 ~ 6)
console.log( d.getDay() )  //6
  1. getTime()----------返回1970年1月1日至今的毫秒数
console.log( d.getTime() )  //1622510823157
  1. Date.now()--------返回当前时间与起始时间之间的毫秒数
console.log( d.Date.now() )  //1622510823157

11.返回转换后的Date对象与起始时间之间的毫秒数:

Date.parse('2019/05/01 00:00:00'); // 1556640000000

12.返回一个’年月日 时分秒’的本地格式字符串:

d.toLocaleString(); // '2021/4/30 上午12:55:42'

13.返回一个’年月日’的本地格式字符串:

d.toLocale<font color=red>Date</font>String(); // '2021/4/30'

设置日期时间:

var d = new Date()
  1. setFullYear()------设置 Date 对象中的年份(四位数字)

    d.setFullYear(2022)
    
  2. setMonth()---------设置 Date 对象中月份 (0 ~ 11)

    d.setMonth(5)// 设置月份 0-11   12->下一年的1月
    
  3. setDate()----------设置 Date 对象中月的某一天 (1 ~ 31)

     d.setDate(20)// 设置日期
    
  4. setHours()---------设置 Date 对象中的小时 (0 ~ 23)

    d.setHours(12)// 设置小时数
    
  5. setMinutes()-------设置 Date 对象中的分钟 (0 ~ 59)

     d.setMinutes(50)// 设置分钟数
    
  6. setSeconds()-------设置 Date 对象中的秒钟 (0 ~ 59)

    d.setSeconds(50)// 设置秒数
    
  7. setMilliseconds()–设置 Date 对象中的毫秒 (0 ~ 999)

    d.setMilliseconds(999)// 设置毫秒数
    
  8. setTime()----------设置 Date 对象(向1970/1/1添加毫秒数)

    d.setTime(1000*60*60*24)// 向1970.1.1时间累加一天的毫秒数 1970.1.2 08:00:00
    

创建指定时间点的Date对象

var d1 = new Date(毫秒数); //从时间起点开始叠加的毫秒数
var d2 = new Date('yyyy/MM/dd  HH:mm:ss');

// Aug 20 2020 00:00:00 GMT+0800
var d = new Date('8/20/2020');

// Aug 20 2020 00:00:00 GMT+0800
var d = new Date('2020/8/20');

// Aug 20 2020 20:20:20 GMT+0800
var d = new Date('2020/8/20 20:20:20');

// Jan 20 2021 00:00:00 GMT+0800
var d = new Date(2020,12,20); // 年月日  月0-11  12下一年的一月

时区计算

var d = new Date();

// 0时区和当前时区的时间差,单位是分钟
var offset = d.getTimezoneOffset();
console.log( offset ); // -480 = 0时区时间-当前时区时间

var timezone = -offset / 60;

if (timezone > 0) {
    console.log( '东' + timezone + '区' );
} else if (timezone < 0){
    console.log( '西' + -timezone + '区' );
} else {
    console.log( '零时区' );
}

操作世界时,在get或set后面加UTC,如 d.getUTCHours()、d.setUTCHours()

练习拓展

1.显示本地时间并数字为两位数

<h1>北京时间:2021年06月01日 10:05:35</h1>
setInterval(function (){
    var d = new Date() // 创建日期对象
    var year = d.getFullYear()
    var month = d.getMonth()+1 // 0-11
    var day = d.getDate()
    var hour = d.getHours()
    var minute = d.getMinutes()
    var second = d.getSeconds()
    month = month < 10 ? '0'+month : month
    day = day < 10 ? '0'+day : day
    hour = hour < 10 ? '0'+hour : hour
    minute = minute < 10 ? '0'+minute : minute
    second = second < 10 ? '0'+second : second
    document.querySelector('h1').innerText = '北京时间:'+year+'年'+month+'月'+day+'日'+' '+hour+':'+minute+':'+second
},1000)

2.封装一个方法,返回中文的星期几

function getWeek(){
    var d = new Date()
    var num = d.getDay()// 0-6 0->星期日
    var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']
    return arr[num]
}
console.log( getWeek() ) // '星期二'

3. 2021年国庆倒计时

setInterval(function (){
    // 2021年国庆倒计时
    var d1 = new Date()// 现在的日期对象
    var d2 = new Date('2021/10/1 00:00:00')// 未来的日期对象
    var times1 = d1.getTime()// 1970.1.1到现在的总毫秒数
    var times2 = d2.getTime()// 1970.1.1到2021.10.1的总毫秒数
    var allTime = times2 - times1// 现在到2021.10.1的总毫秒数

    // 思路1:用总的时间allTime分别计算出天数小时数分钟数。。。
    // var days = parseInt( allTime / (1000*60*60*24) )
    // var hours = parseInt( (allTime % (1000*60*60*24)) / (1000*60*60) )
    // ...

    // 思路2:计算出天数,利用时间互补性
    var days = parseInt( allTime / (1000*60*60*24) )
    var hours = 23 - d1.getHours()
    var minutes = 59 - d1.getMinutes()
    var seconds = 59 - d1.getSeconds()
    var milliSeconds = 999 - d1.getMilliseconds()

    document.querySelector('h1').innerText = '距离2021国庆节还有:'+days+'天'+hours+'时'+minutes+'分'+seconds+'秒'+milliSeconds
},1)

运动

运动原理:使用计时器,持续改变元素的属性

运动速度:取决于每次所走距离的多少

运动停止:判断什么时候到达目标位置,并清除计时器

匀速运动

运动频率和运动速度保持不变!

运动频率:计时器时间

运动速度:每次改变的量

// 关键步骤:

// 1. 获取当前值
var current = parseInt( getComputedStyle(dom)[attr] )

// 2. 判断运动方向
if (target > current){
    speed = Math.abs(speed); // 向右运动
} else {
    speed = -Math.abs(speed); // 向左运动
}

// 3. 到达目标位置:剩余运动量 <= 每次的运动量
if ( Math.abs(target-current) <= Math.abs(speed) ) {
    ...
} else {
    ...
}

缓冲运动

运动速度发生变化,由快到慢
在这里插入图片描述

// 缓冲运动的关键:

// 1. 获取当前值
var current = parseInt( getComputedStyle(dom)[attr] )

// 2. 频率不变,速度逐渐变慢
var speed = (target - current) / 10

// 3. 对速度取整,避免数据丢失
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed)

// 4. 到达目标位置:剩余运动量 <= 每次的运动量
if ( Math.abs(target-current) <= Math.abs(speed) ) {
    ...
} else {
    ...
}

透明度运动

透明度变量:var opa = 30

其他浏览器:dom.style.opacity = opa/100

IE浏览器:dom.style.filter = 'alpha(opacity:' + opa + ')'

注意:多元素进行相同的运动,属性都不能共用!

ES5 新增特性

严格模式

除了正常运行模式,ECMAscript5添加了第二种运行模式:“严格模式”(strict mode)。
顾名思义,这种模式使得Javascript在更严格的条件下运行。

设立"严格模式"的目的,主要有以下几个:
消除JavaScript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的JavaScript做好铺垫。

进入"严格模式"的标志:“use strict”;

将 “use strict”; 放在脚本文件的第一行,则整个脚本都将以"严格模式"运行。

<script>
   "use strict";
   console.log("全局严格模式。");
</script>

将"use strict"放在函数体的第一行,则整个函数以"严格模式"运行。

function strict(){
   "use strict";
   console.log("局部严格模式。");
}

ES5严格模式的限制规范:

1.变量声明必须使用var,否则报错

2.对不合理的操作显示报错,不再做静默失败处理

NaN = 123;
var abc = 'a12';
delete abc;
abc.length = 5;

3.禁止对象属性重名(IE)

4.禁止函数参数重名

5.禁止使用以0开头的八进制数字
ES6新的语法标准,八进制以0o来表示,与16进制的0x形成统一的语法格式

6.禁止使用with语句

7.强制为eval创建新作用域
eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。
如果参数是一个表达式,eval() 函数将执行表达式。
如果参数是Javascript语句,eval()将执行 Javascript 语句。
严格模式为JavaScript程序创建了第三种作用域:eval作用域

8.arguments不再追踪参数变化

var x = 1
function fn1(x) {
    x = 2;
    arguments[0] = 3;
    alert(x);
}
fn1(4);

9.禁止使用arguments.callee

// 在匿名的递归函数中
var factorialArray = [1, 2, 3, 4, 5].map(function(n) {
return (n < 2) ? 1 : arguments.callee(n - 1) * n;
});
console.log(factorialArray);

10.函数中禁止this指向全局对象window,this变成undefined

11.函数必须声明在整个脚本或函数层面

12.新增一些保留字,不能使用他们作为标识符命名
implements, interface, let, package, private, protected, public, static, yield

下一篇:20.JS高级(一)

🌸友情推荐:全栈大佬笔记     Android领域肥宅

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值