JS原生知识点个人笔记

API与webAPI简单介绍--------------------------------

  • API 就是封装好的一些东西,可以直接去调用,可以不需要掌握里边的原理.能用就好.
  • webAPI : 指的是javascript对浏览器使用封装好的API, 道理个API一样,方便简洁,不用知道底层是如何实现.

javascript 的组成-----------------------------------------

ECMAjavascript

  • 定义javascript的语言规范
  • 描述了语言的基础语法和数据类型,是一套标准

DOM —文档对象模型

  • 一套操作页面元素的API
  • DOM可以把HTML页面看做文档树,通过DOM提供的API对树上的节点进行操作

BOM —浏览器对象模型

  • 一套对浏览器操作的API
  • 通过BOM可以操作浏览器窗口,弹出框,浏览器跳转,获取分辨率等

获取元素的方式-----------------------------------------

  • 整个页面都是document 所以不管是哪种方法来获取元素, 都可以使用document
  • 除了 id和querySelector 能够直接获取元素之外, 其它获取到的都是伪数组(伪数组不能使用数组API)
  • querySelectorAll 获取的也是伪数组,但是可以调用forEach()方法

通过id方式获取

  • document.getElementById
  • getElementById只能由document来调用,否则会报错(唯一性)
  • 当找不到时,返回null 不是报错
  • id具有唯一性

通过class类名获取

  • document.getElementByClassName
  • 获取到的是伪数组
  • 伪数组的特点 : 和数组的区别就是 ,不能使用数组的API,所以就不能用forEach啥的
  • 遍历循环时,不能使用forEach来遍历,会报错.forEach只能作用于 querySelectorAll
  • 找不到时,返回空对象
// 获取的都是伪元素,所以不能直接使用,需要通过下标[]来dom操作

var li = document.getElementByTagName('box');
for(var i = 0; i < li.length; i++){
    li[i].style.color = 'red';
}

通过标签名获取

  • document.getElementByTagName
  • 遍历循环时,不能使用forEach来遍历,会报错.forEach只能作用于 querySelectorAll
  • 用法和class是一样的 找不到时,返回空数组

根据选择器获取

  • document.querySelector // 获取单个元素,当有多个时,只获取第一个
  • document.querySelectAll
  • query英语单词 : 查询
// 作用id, 需要加下标
var father = document.querySelectorAll('#father')[0];

// 可以用forEach循环来遍历,  ByTagName   ByClassName都会报错

fs.forEach(function (ele,index) {
      ele.style.color = 'blue';
 })
或者
fs.forEach(function (ele,index) {
      fs[index].style.color = 'blue';
 })

[外链图片转存失败(img-lQQErgPk-1568959753571)(C:\Users\shen\Desktop\markdown\5.webAPI\my_img\forEach能用否.png)]

  • 上边为通过 ByTagName来获取的,在原型链上只有三个方法
  • 下边的为通过querySelectAll 来获取的,在原型链上有多个方法来使用

通过name获取

  • ElementsByName
  • 用于获取表单的name,也是一个伪数组.

获取css属性的三种方式总结 ------------------------

------- css特点 --------

font-size或background-color等在js中获取需要使用驼峰布局才能够使用 fontSize backgroundColor

------- css特点 --------

点语法

  1. 推荐获取和设置常用属性,不建议设置自定义属性(但是其实这样简单!! 哈哈哈哈哈)
  2. 元素.className || 元素.style.color
  3. 只能获取和设置行内样式
  4. 获取和设置,值一定是字符串
  5. 与attrbute方式互相不能获取和设置自定义属性
  6. 设置的自定义属性通过浏览器F12看不到(attrbute可以看到)
  7. 不能获取到自己在html标签中定义的自定义属性(Attrbute可以)

Attrbute

  1. 推荐获取和设置自定义属性
  2. 只能获取和设置行内样式
  3. 获取和设置,值一定是字符串
  4. 与点语法方式互相不能获取和设置自定义属性
  5. 设置的自定义属性可以通过浏览器F12看到(点语法看不到)
  6. 能够获取到自己在html标签中定义的自定义属性(点语法不行)

getAttribute 获取

<body>
<div class="box" id="box" style="height: 500px">
    <p>你好,woshi ni爸爸</p>
    <p>你好, i am your father</p>
</div>
<script>
    var box = document.getElementById('box');
    console.log(box);
    console.log(box.getAttribute('class'));     // 获取class的名字
    box.setAttribute('box','aaaa');             // 
    console.log(box.getAttribute('box'));
</script>
</body>

setAttribute 设置

  • 不能和jQuery一样,通过对象来设置
  • box.setAttribute(‘box’,‘aaaa’);

removeAttribute

  • 删除元素行内属性

getComputedStyle

  • 用法 : getComputedStyle(obj,null)[‘width’]
    第一个参数 : 获取的标签
    第二个参数 : 获取伪元素 不需要的话为null
    第三个参数 : 获取啥css属性
  • 特点 :
  1. 能够获取一切css样式 包括行内,外链式,内嵌式
  2. 不能设置属性

事件----------------------------------------------------------

事件冒泡

  • 事件冒泡:如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发
  • 元素->父元素->body->html->document->window
  • 事件冒泡一直存在,只不过以前我们没有给父级元素加同名事件
  • 事件冒泡取消 : e.stopPropagation()

事件委托

  • 属于事件冒泡带来的优点
  • 作用 :
  • 动态创建的元素添加事件不建议直接在创建元素的函数地方添加新的事件,通过事件委托可以在外部直接赋值事件
  • 不需要for循环挨个子元素添加事件,提升代码的性能
  • 使用方法 :
  • 对祖先元素绑定事件,利用事件对象 e.target来获取当前的元素
  • 代码执行顺序问题
  1. 在页面渲染完成之后,js文件是已经从上到下完成了执行, 此时新元素还没创建,获取不到该元素,此时对空的元素事件绑定,那么因为会找不到该元素而报错
  2. 为啥还没添加元素之前用for循环遍历父元素.children不报错呢?
    因为用for循环来遍历的时候,遍历的元素是一个伪数组,伪数组的length为0是不会报错的.那么此时js从上到下正常加载,发现伪数组的长度为0会直接跳过这个for循环,更不会去执行里边的事件函数. 因为根本就没有进入到循环当中. 因此不会报错.
<style>
        div{
            width: 400px;
            height: 400px;
            background: red;
            margin: 0 auto;
        }
        p{
            width: 200px;
            height: 200px;
            background: blue;
        }
    </style>
</head>
<body>
<div style="" >
    <p></p>
</div>
<script>
    document.addEventListener('click',function (e) {
        if(e.target.nodeName === 'P'){
            e.target.parentNode.style.background = '#cccc';
        }
        console.log(e.target);
    })
</script>

事件捕获

  • addEventListenner(obj,function(){},true)
  1. 第三个参数为true时,为事件捕获,事件从window到最里边元素挨个执行(false为事件冒泡)
  2. 清除事件委托 : e.stopPropagation()

事件对象

  • 当有事件触发时,只要在函数小括号里放个 e 自动就会启用事件对象,可以获取当前触发事件的一些信息.好比: 当前的事件名称 click || mouseover用e.type来获取 ,当前的元素 e.target获取
  • 兼容性 : e = e || window.event (该死的IE8)
e.type
  • 获取当前的事件名称
e.target
  • 获取当前触发的最里边的元素
e.target.nodeName
  • 判断当前元素是什么标签 ( 判断的值为大写 )
document.addEventListener('click',function (e) {
    
   //  此处 P  是大写
        if(e.target.nodeName === 'P'){
            e.target.parentNode.style.background = '#cccc';
            e.target.style.background = '#cccc';
        }
        else if(e.target.nodeName === 'DIV'){
            e.target.style.background = '#cccc';
        }
        else {
            e.target.style.background = 'black';
        }
    })
e.clientX e.clientY
  • 获取鼠标在当前可视区域的坐标
e.pageX e.pageY
  • 获取当前距离顶部的距离(包括滚动条)
  • pageY = clientY + scrollTop(距离顶部的距离 = 当前滚条的距离 + 可是区域的距离)

阻止默认事件

  • 第一种:给a标签添加点击事件,在点击事件中return false或者 e.preventDefault()
  • 第二种:给a标签的href属性设置一个伪链接
  1. javascript:void(0)
  2. javascript:;

注册事件

on语法

  • onclick等

addEventListener(‘click’,function(){},false)

  • 第一个参数 : 事件类型
  • 第二个参数 : 事件执行函数
  • 第三个参数 : 确认是事件冒泡(false)还是事件捕获(true) 默认为false(可以不传默认为false)

两者的区别 :

  1. on语法只能给一个元素的一种事件类型绑定一个函数来执行, addEventListener可以绑定多喝函数为同个事件,执行顺序为代码的编写顺序

移除事件

元素.onclick = null

  • 点语法直接赋值为空

removeEventListener

  • 元素.removeEventListener(参数1,参数2,参数3)
  • 第一个参数 : 事件类型
  • 第二个参数 : 删除的函数
  • 第三个参数 : 布尔值,确定是事件冒泡还是事件捕获

onfocus 获得焦点

  • focus() : 直接获得焦点
  • onfocus = function(){} : 当获得焦点时.执行函数
  • this : 谁触发这个函数就代表谁
<script>
        window.onload=function () {
           var input = document.getElementsByTagName("input");
            input[0].focus();                 //  让它默认就获得焦点
            input[1].onfocus=function () {    //  当获得焦点时,执行里边的函数
                this.style.border = '5px solid red';   
                this.style.outline = '1px solid blue';
            }
        }
    </script>
</head>
<body>
<input type="text" placeholder="请输入姓名">
<input type="password" placeholder="请输入密码">
</body>

onblur 失去焦点

onclick 鼠标单击

ondblclick 鼠标双击

onmouseover鼠标移入

onmouseout 鼠标移出

onmousedown 鼠标点下

onmouseup 鼠标抬起

onkeydown 键盘按下

onkeyup键盘抬起

onkeypress 键盘按下并抬起

  • onkeypress 和 onkeydown的区别 :
  1. onkeypress可以过滤掉特殊的功能键例如删除、F1-F12,shift,alt键等等,onkeydown不会过滤
2. onkeypress可以区分大小写,但是onkeydown永远都是大写(不管大小写状态)
  • e.keyCode 获取当前键盘在ASCII中的数字

三大家族---------------------------------------------------

offset家族

offsetLeft offsetTop
  • 获取当前元素与offsetParent的距离
// 1.  脱离标准流(以定位为参照)
1. offsetTop 和 offsetTop都是绝对定位中的left和top为准   并且transiform中的transilate改变值以后,offsetTop和offsetLeft的值还是left和top的值

// 2. 没脱离标准流的时候
没脱离标准流的话,个人理解: 以浏览器最顶端最左边为参照点(以body为参照物)
offsetWidth offsetHeight
  • 作用 : 获取当前盒子的宽高, 包括盒子设定的大小和边框
  • 使用 : 元素.offsetWidth
offsetParent
  • 作用 : 获取最近的定位父元素

scroll家族

scrollWidth scrollHeight
  • 作用 : 如果没有内容为当前盒子的宽高,不包括边框。 如果有内容,且超出了父盒子的大小,那么也能获取到大于父盒子的大小的宽高
scrollTop scrollLeft
  • 作用 : 获取当前屏幕滚动的距离
  • 获取当前屏幕滚动距离 :
  • 通常用 : document.documentElement.scrollTop
  • document.body.scrollTop || document.documentElement.scrollTop (存在兼容性,Chrome用的是后者)
  • 获取盒子的滚动宽度的前提是盒子必须有滚动条
  • 元素.scrollTop
  • 可以直接设置
元素.scrollTop = 999999999999999999999999999999      // 默认会滚动到最下边
  • 封装scroll的使用
function getScroll(){
    return {
  top : window.pageYoffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
left :  window.pageXoffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0
    }
}
window.onscroll
  • 作用 : 监听滚动事件
  • 监听当前window的滚动事件 window.onscroll = function(){}
  • 监听div盒子的滚动事件 div.onscroll = function(){}

client家族

clientWidth clientHeight
  • 获取当前屏幕宽高
  • document.documentElement.clientWidth
window.onresize
  • 是啥 : 监听浏览器重置窗口大小时候的事件
  • 做啥 : 用于响应式布局( PC端用的比较多,因为窗口固定,并不会和网页一样随着屏幕滚动而变化 )

缓动动画----------------------------------------------------

function glm_animation ( obj, attrs, callback ) {
    //1每次设置计时器之前,都要把原来的计时器给清空掉
    clearInterval ( obj.timerID )
    //2 设置计时器
    obj.timerID = setInterval ( function () {
        //开关思想确保所有的属性都到达目标位置之后再停止定时器
        var isAllOK = true
        //3 循环参数对象,让每一个属性执行一次定时器的代码
        for ( var key in attrs ) {
            //透明度的范围是0-1的小数,需要单独处理逻辑
            if ( key == "opacity" ) {
                var target = attrs[ key ]
                //透明度是0-1的小数所以需要使用parseFloat,乘以一百方便计算
                var current = parseFloat ( getStyle ( obj, key ) ) * 100
                var step = ( target * 100 - current ) / 50
                step = step > 0 ? Math.ceil ( step ) : Math.floor ( step )
                current += step
                //由于之前我们乘了一百,把透明度的值放大一百倍转成0-100的整数,所以所以又要除以一百转成0-1的小数
                obj.style[ key ] = current / 100
                if ( current / 100 != target ) {
                    isAllOK = false
                }
            } else if ( key == "zIndex" ) {
                //层级的改变无需动画(这是一个瞬间的过程)
                obj.style.zIndex = attrs[ key ]
            } else {
                //3.1 获取本次动画要修改的属性的值  key就是属性  atts[key]就是属性对应的值
                var target = attrs[ key ]
                //3.2 获取box的当前的的属性的值,此时key就是元素的属性
                var current = parseInt ( getStyle ( obj, key ) )
                //3.3 计算本次要运动的距离
                var step = ( target - current ) / 10
                //如果是正数,就向上取整,如果是负数,就向下取整。
                step = step > 0 ? Math.ceil ( step ) : Math.floor ( step )
                //3.4 开始移动
                current += step
                obj.style[ key ] = current + "px"
                //3.5 开关思想检测所有属性是否都到达目标位置
                if ( current != target ) {//只要有一个没达到,开关就为false
                    isAllOK = false
                }
            }
        }
        //4.检测是否所有属性都到达目标位置,如果是就清楚定时器
        if ( isAllOK == true ) {
            clearInterval ( obj.timerID )
            //判断函数调用者是否需要告诉他函数执行完毕,如果传递了回调函数这个参数我们就执行这个函调函数,否则不执行
            if ( typeof  callback == "function" ) {
                console.log(this);
                
                callback ();
            }
        }
    }, 30 )
}

//获取元素样式的值
function getStyle ( obj, attr ) {
    //能力检测
    if ( obj.currentStyle ) {
        //IE8及之前
        return obj.currentStyle[ attr ]
    } else {
        return window.getComputedStyle ( obj, null )[ attr ]
    }
}

拖拽----------------------------------------------------------

html5 + css3

draggable = ‘true’

  1. 支持IE10及以上,近四五年的谷歌浏览器
  2. draggable = 'true’作用是为了可以进行拖拽事件 img标签默认加上了draggable = ‘true’
主动
  1. ondragstart 一个盒子开始拖拽启动事件
  2. ondrag 一个盒子拖拽中启动事件
  3. ondragend 一个盒子拖拽结束启动事件
  • 注意事项 : 如果要进行两个容器之间的盒子appendChild 就不能使用ondrag 因为到处都是bug!!!
例子 ( 简单拖拽 )
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body{
            background: #000;
            margin: 0;padding: 0;
        }
        img{
            position: absolute;left: 0;top: 0;
        }
    </style>
</head>
<body>
    <img src="./images/1.jpg" alt="" width="200px">
    <script>
        var img111 = document.getElementsByTagName('img')[0];
        var x = 0, y = 0;
        // 拖拽开始,计算鼠标点击的位置到两边的距离
        img111.ondragstart = function(e){
            x = e.pageX - this.offsetLeft;
            y = e.pageY - this.offsetTop;
        } 
       // 拖拽中, 让盒子的位置和拖拽的位置保持一致
        img111.ondrag = function(e){
            this.style.left = e.pageX - x +'px';
            this.style.top = e.pageY - y + 'px';
        }
        // 拖拽结束,还是让盒子位置和拖拽的位置保持一致
        img111.ondragend = function(e){
            this.style.left = e.pageX - x +'px';
            this.style.top = e.pageY - y + 'px';
        }
    </script>
</body>
</html>
被动(容器盒子)
  • ondragenter : 当有拖拽的盒子进入到这个容器盒子触发事件
  • ondragleave : 当有拖拽的盒子出去这个容器盒子触发事件
  • ondragover : 当有拖拽的盒子在容器中移动的时候触发事件
  • ondrop : 当有拖拽的盒子在容器中放下触发事件
  • 这个东西必须要让ondrapover事件阻止默认事件 e.preventDefault()
  • 注意事项 如果要使用容器盒子,则主动中的ondrag一定不要使用,到处都是bug…

DOM操作---------------------------------------------------

innerHTML 获取设置元素内容

innerText 获取设置元素文字

  • 只能获取或者设置双标签, 单标签啥的都是用value

children 获取子元素伪数组

  • 通过children也不能使用forEach来遍历伪数组. 和tagName className使用方法一样

nextElementSibling 获取下一个兄弟元素

previousElementSibling 获取上一个兄弟元素

firstElementChild 获取第一子元素

lastElementChild 获取最后一个子元素

parentNode 获取父节点

  • 节点和元素原本是不一样的. 但是此处用法是一样的
  • 获取父元素用parentElement

cloneNode() 克隆元素

  • p.cloneNode(true) // true时, 克隆所有的东西
  • p.cloneNode(false) // false时, 克隆除了内容所有的东西
  • id一个元素只能有一个, 那么克隆之后必须对id名字的修改
  • 克隆后的元素必须插入到盒子当中才能生效
  • 父元素.insertBefore(p,添加到什么之前)
  • 父元素.appendChild§ ==> 末尾添加

removeChild 删除元素

  • 父元素.removeChild(子元素)

动态创建元素 结合事件委托---------------------------

什么是元素? (重点)

  • 元素不仅仅是一个html标签. 具体的说应该是一个元素对象. 元素对象中有n中属性,和对应的值. 属性不仅仅是css样式的属性, 也不仅仅是行内上 value type name 及自定义的属性. 最最最最最主要的还包括了各种事件的属性. 每一个事件都是一个属性,当激活了这个属性,会找到对应值中的方法来运行.

createElement 创建元素

var new_li = document.creatElement(‘li’)

appendChild() 末尾添加

  • 父元素.appendChild( 添加元素)
  • 特点 :
    如果是将已经存在的元素作为子元素添加到新的父元素上,那么该元素对象上所有的属性及所对应的值都能够传递过去. 并不仅仅是一个全新的元素,对该元素赋值过的属性都能够传递过去.
  • 举例子 : 存在两个容器, 子盒子onclick能够在容器中自由互换位置(使用appendChild),那么这个click事件的值也会一起append过去,点击的时候也能够实现效果.

insertBefore() 自定位置添加

  • 父元素.insertBefore(p,添加到什么之前)

图片延迟加载问题

  • 特点 : 在js动态添加新的图片的时候,不能够直接获取到图片的css样式.解决方法有三个:
    1. 使用定时器延时获取创建的img图片的样式
    2. 不在window.onload下创建元素,在window.onload下获取属性
    3. 通过定时器来不定时获取元素,用if去判断,当获取的undefine/ null / ‘’/等时,直接return,等待定时器下一次访问

动态创建总结:

  1. 熟记appendChild和insertBefore的特点,把旧元素作为传递的子元素,能够携带所有的属性到新的父元素下
  2. 如果时新的元素,需要通过自身点击的情况下,最好使用事件委托, 不要在创建元素的时候把事件绑定在上边

BOM---------------------------------------------------------

window

  • open()和 close() == 》 打开和关闭窗口
window.open(URL, '_self', 'width=100;height=300;top:100')\

//  window.close()

location URL 的使用

  • 获取url上的各种信息 :
  • window.location.hash #后面的路径
  • window.location.host 主机名和端口号
  • window.location.hostname 主机名
  • window.location.pathname 相对路径
  • window.location.port 端口号
  • window.location.protocol http还是https协议
  • window.location.href 完整的路径
  • window.location.search 传输内容的字符串
  • location.href = “https://www.baidu.com” 和 location.assign(“https://www.baidu.com”) 是一样的,设置跳转的路径
  • location.reload() : 重新加载
  • location.replace(“https://www.baidu.com”)
  • replace和href的区别 : replace不能后退,也就是浏览器没有缓存之前的记录

history 浏览历史记录的前进与后退

  • back()后退
  • forward() 前进
  • go() : 括号是正数就前进 是负数就后退
window.history.forward()

navigator 查看当前型号(浏览器,电脑系统等)

  • window.navigator.userAgent 查看当前使用的是什么浏览器,型号是多少
  • window.navigator.platform 查看当前的电脑操作系统
  • 获取经纬度
// 注意点  :  谷歌浏览器默认获取经纬度的功能被和谐了,所以只能通过火狐等功能来获取,获取经纬度的实际是向浏览器服务器发送请求功能,让浏览器的服务器获取我的ip地址的地理位置。然后返回给我们 
navigator.geolocation.getCurrentPosition(function(location){
	// 获取纬度  location.coords.latitude 
    console.log(location.coords.latitude )
    
    // 获取经度 location.coords.longitude
    console.log(location.coords.longitude)
})

localStorage

  • 增 localStorage.setItem(‘name’,‘glm’);
  • 删除 localStorage.removeItem(‘name’) 或者删除全部 localStorage.clear
  • 查 getItem
  • 特点 :
  • 存储到硬盘当中,不手动删除是不会删除掉的
  • 存储的都是字符串,如果时json文件,需要转成字符串 localStorage.setItem(‘shop_list’,JSON.stringify(list));获取的时候也需要把字符串转成json : JSON.parse(localStorage.getItem(‘shop_list’))

sessionStorage

  • 特点 : 一次性存储,浏览器关闭后信息就消失了。 用法和localStorage一模一样