前端使用的(浏览器执行的)js一般包含两部分:
1.JS基础知识(ECMA262标准)
2.JS-WEB-API(W3C标准):对应DOM
BOM 是 各个浏览器厂商根据 DOM 在各自浏览器上的实现;表现为不同浏览器定义有差别,实现方式不同
- window 是 BOM 对象,而非 js 对象;
DOM(Document Object Model)文档对象模型
几个问题
1.DOM是哪种基本的数据结构? 树型结构
2.DOM节点的attribute和property有何区别?
proterty是指JS对象的属性;
attribute是指html的属性
DOM本质
W3C标准的文档,可用于被浏览器解析并渲染出Web页面的html文档
DOM节点操作
1.获取DOM节点:getElementById/getElementByTagName/getElementByClassName/querySelectorAll
// 获取元素
var div1 = document.getElementById("div1")
// 获取集合
var divList = document.getElementsByTagName("div")
var classList = document.getElementsByClassName(".content")
var pList = document.querySelectorAll("p")
2.property(js对象的属性 )
var pList = document.querySelectorAll("p")
var p = pList[0]
// 获取元素样式
console.log(p.style.width)
// 修改样式
p.style.width = '100px'
// 获取元素class
console.log(p.className)
// 修改class
p.className = 'p1'
// 获取nodeName和nodeType
console.log(p.nodeName)
console.log(p.nodeType)
nodeName: div/a/p/span/h1等等
nodeType: 为数字型,常规的dom节点都是1,text文本是3;这个可以用来区分节点类型
3.Attribute(html属性):getAttribute/setAttribute
var pList = document.querySelectorAll("p")
var p = pList[0]
// 获取html属性
p.getAttribute('data-name')
// 设置html属性
p.setAttribute('data-name', 'imooc')
p.getAttribute('style')
p.setAttribute('style', 'color: red')
DOM树结构操作
1.新增节点
2.获取父节点
3.获取子节点
4.删除节点
var div1 = document.getElementById('div1') // 添加新节点 var p1 = document.createElement('p') p1.innerHTML = 'this.is p1' div1.appendChild(p1)
// 移动已有节点(原来节点就没有了) var p2 = document.getElementById('p2') div1.appendChild(p2)
// 获取父节点 var parent = div1.parentElement // 获取子节点
var child = div1.childNodes // 删除子节点 div1.removeChild(child[0])
BOM(Browser Object Model)浏览器对象模型
几个问题:
1.如何检测浏览器类型 尤其是移动端安卓与IOS/app嵌入浏览器等
2.如何拆解url的各部分内容信息
几个关键对象:navigator、screen、location、history
var ua = navigator.userAgent var isChrome = ua.indexOf('Chrome')
screen.width screen.height
location.href location.protocol // 协议类型 http https location.pathname // 路由地址 /learn/99
location.search // url中的参数 location.hash
history.back() history.forward()
事件绑定
编写一个通用的事件绑定监听函数
// 一个通用的事件绑定监听函数
// 1.未封装的事件绑定
var btn = document.getElementById('btn1')
btn.addEventListener('click', function(){
alert('clicked')
})
// 2.基本封装,参数(绑定元素, 事件类型, 回调函数)
function bindEvent(elem, type, fn){
elem.addEventListener(type, fn))
}
// 使用
var a = document.getElementById('link1')
bindEvent(a, 'click', function(e){
e.preventDefault()
alert('a is clicked')
})
IE低版本浏览器使用的方法是attachEvent ,不深究
描述事件冒泡流程 对于一个无限滚动下拉加载图片的页面,如何给每一个图片绑定事件
事件绑定
一个通用绑定事件的函数完善:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>test</title> </head> <body> <div id="div1"> div1 <p id="p1">p1</p> </div> </body> <script> // 通用的事件绑定监听函数(升级版) // 参数(绑定元素, 事件类型,子元素, 回调函数) function bindEvent(elem, type, selector, fn){ if(fn == null){ fn = selector selector = null }
elem.addEventListener(type, function(e){ var target if(selector){ target = e.target if(target.matches(selector)){ fn.call(target, e) } }else{ fn(e) } }) }
var p1 = document.getElementById('p1') var div1 = document.getElementById('div1') bindEvent(div1, 'click', function(e){ alert('div1') }) bindEvent(p1, 'click', function(e){ // e.stopPropagation() alert('p1') }) </script> </html>
事件冒泡
父元素绑定了点击事件, 子元素点击的时候,其点击事件会不断冒泡,促使父元素的点击事件也会发生
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>opacity</title> <style> .circle { border-radius: 50%; width: 20px; height: 20px; background: red; /* 宽度和高度需要相等 */ } </style>
</head> <body>
<div> <div id="div1"> div1 <p id="p1">p1</p> </div> </div> </body> <script> // 通用的事件绑定监听函数(升级版) // 参数(绑定元素, 事件类型, 回调函数) function bindEvent(elem, type, selector, fn){ if(fn == null){ fn = selector selector = null }elem.addEventListener(type, function(e){ var target if(selector){ target = e.target if(target.matches(selector)){ fn.call(target, e) } }else{ fn(e) } }) }
var p1 = document.getElementById('p1') var div1 = document.getElementById('div1') bindEvent(div1, 'click', function(e){ alert('div1') }) bindEvent(p1, 'click', function(e){ // e.stopPropagation() alert('p1') }) </script> </html>
当点击p1的时候,会先alert出p1,再alert出div1; 如果加了e.stopPropatation(),阻止事件冒泡,就不会弹出div1
*阻止冒泡:e.stopPropatation()
事件代理
通过代理可实现批量对子节点增加点击事件,点击哪个子节点就触发对应的事件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<div id="div1">
<a>a1</a>
<a>a2</a>
<a>a3</a>
<a>a4</a>
</div>
</body>
<script>
var div1 = document.getElementById('div1')
div1.addEventListener('click', function(e){
var target = e.target
if(target.nodeName === 'A'){ // 此处注意:a标签的nodeName为大写的A
alert(target.innerHTML)
}
})
</script>
</html>
点击哪个a标签就会弹出哪个a标签的内容,开发者可在这个基础上增加针对不同a标签不同的处理逻辑
代理的优点:1.代码简洁;2.减少浏览器内存占用
ajax请求与Http协议
js手动写一个ajax的实现 跨域的实现方式 ###XMLHttpRequest http://www.w3school.com.cn/xmldom/dom_http.asp
let xhr = new XMLHttpRequest()
xhr.open("GET", "/api", false)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
alert(xhr.responseText)
}
}
}
xhr.send(null)
Tips:
XMLHttpRequest.open()
作用:初始化 HTTP 请求参数
open(method, url, async, username, password)
参数说明 method 是用于请求的 HTTP 方法。值包括 GET、POST 和 HEAD。
url 是请求的主体。大多数浏览器实施了一个同源安全策略,并且要求这个 URL 与包含脚本的文本具有相同的主机名和端口。 async false 同步的,后续对 send() 的调用将阻塞,直到响应完全接收。如果参数是 true 或省略,请求是异步的,且通常需要一个 onreadystatechange 事件句柄。 username 和 password 参数是可选的,为 url 所需的授权提供认证资格。如果指定了,它们会覆盖 url 自己指定的任何资格。
readyState 请求进行状态
HTTP状态码
status 请求返回结果状态
跨域
可以允许跨域的标签j及其特殊用法
<img src=xxx> // 除非做了防盗链,否则是可以跨域的
用法:可用于打点统计,统计网站可能是其他域
<link href=xxx>
<script src=xxx>
用法:<link><script>可以使用CDN请求资源(CDN也是跨域的)
<script>可以用于JSONP实现跨域请求
JSONP
通过跨域加载api.js文件,而在该文件中执行callback方法,则在此处的window.callback得到的data即为请求结果。 Tips: 另外一种解决跨域的方法,是通过服务端来设置http header
存储
了解cookie,sessionStorage与localStorege的区别与特点? cookie的优势与后面与sessionStorage与localStorege相比的缺点又是什么?
cookie
1.存储太小,只有4KB
2.所有的http请求都会携带cookie信息,会影响获取资源的效率,有的请求其实并不需要cookie
3.API简单,遇到数据较多,需要分割存储的时候必须封装处理,不然就会直接存在document.cookie = "... ..."作为一整个字符串
localStorage
1.HTML5新特性,最大5M,也不会多余的携带在请求中
2.API简介易用
localStorage.setItem(key, value)
localStorage.getItem(key)
sessionStorage
区别之处
1.容量区别 2.是否携带在ajax请求中 3.API易用性
本文使用 mdnice 排版