常说的JS(浏览器执行的JS)包含两部分
- JS基础知识: ECMA262标准
- JS-Web-API: W3C标准
DOM 的本质
DOM可以理解为: 浏览器把拿到的html代码,结构化一个浏览器能识别并且js可操作的一个模型而已。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<p>文本</p>
</div>
</body>
</html>
DOM节点操作
- 获取DOM节点
- 获取节点
- 删除节点
- 获取父元素/子元素
- property
- Attribute
获取DOM节点
// 获取DOM节点
var div1 = document.getElementByID('div1') //元素
var divList = document.getElementsByTagName('div') //集合
console.log(divList.length)
console.log(divList[0])
var containerList = document.getElementsByClassName('.container') //集合
var pList = document.querySelectorAll('p') //集合
//新增节点
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 div1 = document.getElementById('div1')
var parent = div1.parentElement
var child = div1.childNodes
div1.removeChild(child[0])
//删除节点
var div1 = document.getElementById('div1')
var child = div1.childNodes
div1.removeChild(child[0])
property property: JS对象的一个属性
var pList = document.querySelectorAll('p')
var p = pList[0]
console.log(p.style.width) // 获取样式
p.style.width = '100px' // 修改样式
console.log(p.className) // 获取class
p.className = 'p1' // 修改class
// 获取nodeName和nodeType
console.log(p.nodeName)
console.log(p.nodeType)
Attribute HTML标签中的属性
var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data-original')
p.setAttribute('data-original','www.google.com')
p.getAttribute('style')
p.setAttribute('style','font-size:30px;')
attribute 和 property 之间有什么区别?
- property 是对一个JS对象的属性的修改
- Attribute是对HTML标签的修改
Attribute 是在 HTML 中定义的,而 property 是在 DOM 上定义的。为了说明区别,假设我们在 HTML 中有一个文本框:<input type="text" value="Hello">
const input = document.querySelector('input');
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello
但是在文本框中键入“ World!”后:
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello World!
navigator & screen
// navigator 检测浏览器的类型
var ua = navigator.userAgent
var isChrome = ua.indexof('Chrome')
console.log(isChrome)
// screen 检测屏幕大小
console.log(screen.width)
console.log(screen.height)
location & history
// location
console.log(location.href) //https://coding.imooc.com/class/180.html?mc_marking=b587280c0c1c0e76c1092aa21406565a&mc_channel=syb6
console.log(location.protocol) // https
console.log(location.host) // coding.imooc.com
console.log(location.pathname) // /class/180.html
console.log(location.search) // ?mc_marking=b587280c0c1c0e76c1092aa21406565a&mc_channel=syb6
console.log(location.hash) // undefined
// history
history.back() //后退
history.forward() //前进
事件绑定
var btn = document.getElementById('btn')
btn.addEventListener('click', function(e) {
console.log('clicked')
})
// 简单封装事件绑定
function bindEvent(elem, type, fn) {
elem.addEventListener(type,fn)
}
// 使用 bindEvent
var a = document.getElementById('link1')
bindEvent(a,'click',function(e) {
e.preventDefault() //阻止默认行为
alert('clicked')
})
IE低版本兼容
- IE低版本使用attachEvent绑定事件,和W3C标准不一样
- IE低版本使用量非常少,很多网站都早已不支持
- 建议对IE低版本的兼容性: 了解即可,无需深究
冒泡
<body>
<div id="div1">
<p id="p1">激活</p>
<p id="p2">取消</p>
<p id="p3">取消</p>
<p id="p4">取消</p>
</div1>
<div id="div2">
<p id="p1">取消</p>
<p id="p1">取消</p>
</div>
</body>
// ---------- 分割线 -------------
// 简单封装事件绑定
function bindEvent(elem, type, fn) {
elem.addEventListener(type,fn)
}
var p1 = document.getElementById('p1')
var body = document.body
bindEvent(p1,'click',function(e){
e.stopPropatation() //阻止冒泡
alert('激活')
})
bindEvent(body,'click',function(e){
alert('取消')
})
代理
- 代理事件冒泡的具体应用
- 代理的好处
- 代码简洁
- 减少浏览器内存的占用
<div id="div1">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
<!--会随时新增更多a标签-->
</div>
// ------------- 分割线 -------------
var div1 = document.getElementById('div1')
div1.addEventListener('click',function(e){
var target = e.target
if (target.nodeName === 'A') {
alert(target.innerHtml)
}
})
完善通用绑定事件的函数
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 div1 = document.getElementById('div1')
bindEvent(div1, 'click', 'a', function(e) {
console.log(this.innerHTML)
})
// 不使用代理
var a = document.getElementById('a1')
bindEvent(div1, 'click', function (e) {
console.log(a.innerHTML)
})
手动编写一个ajax,不依赖第三方库
XMLHttpRequest
var xhr = new XMLHttpRequest()
xhr.open('GET',"/api",false)
xhr.onreadystatechange = function () {
// 这里的函数一步执行
if(xhr.readyState == 4) {
if (xhr.status == 200) {
console.log(xhr.responseText)
}
}
}
xhr.send(null)
状态码-Status
- 2xx - 表示成功处理请求。如200
- 3xx - 需要重新定向,浏览器直接跳转
- 4xx - 客户端请求错误,如404
- 5xx - 服务器错误
跨域
- 浏览器有同源策略,不允许ajax访问其他域接口
- 跨域条件:协议、域名、端口,有一个不同就是跨域
可以跨域的三个标签
常用于打点统计,统计网站可能是其他域
- 、
跨域常见的两种方法
- JSONP
- 借助第三方JSONP插件
- 服务端设置header
- header('Access-Control-Allow-Origin:*') 允许所有来源访问
- header('Access-Control-Allow-Method:POST,GET') 允许访问的方式
JSONP的实现原理
<script>
//跨域请求成功的回掉函数
window.callback = function (data) {
//这是跨越得到的信息
console.log(data)
}
</script>
<script src="http://coding.m.imooc.com/api.js></script>
<!-- 以上奖返回callback() -->
存储
描述cookie、sessionStorage和localStorage的区别