1.DOM(Document Object Model) 文档对象模型
1.DOM是哪种数据结构
树 (DOM树)
2.DOM操作常用API
1.DOM节点操作
- querySelector(第一个节点);
- querySeletorAll(指定选择器组的所有节点集合);
- getElementById(指定id的节点);
- getElementByTagName(指定标签节点集合div、p、span等)
2.DOM结构操作
- innerHTML; 标签内的文本和标签,字符串类型
- parentNode; 指定节点父节点
- children; 指定元素子节点集合
- fistElementChild; 指定元素的第一个子节点
- lastElementChild 指定元素的最后一个子节点
3.attribute和property的区别?
1.property
修改对象属性,不会体现到HTML结构中 (尽量使用property来做)
2.attribute
修改html属性,会改变html结构
这两个都有可能会引起DOM重新渲染
3.一次性插入多个DOM节点,考虑性能
const listNode = document, getElementById('list');
const frag = document.createDocumentFragment()
for (let x = 0; x < 10; x++) {
const li = document.createElement("li");
li.innerHTML = "List item u" + x
frag.appendChild("li");
}
listNode.appendChild(frag)
4.DOM本质
// DOM结构 本质是一棵树,从HTML超文本语言编译出来的一棵树
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body></body>
</html>
5.DOM节点操作
1.获取DOM节点
const div1 = document.getElementById('div1');
const divList = document.getElementsByTagName('div');
console.log(divList.length, divList[0]);
const container = document.getElementsByClassName('.container');
const pAll = document.querySelectorAll('p')
2.attribute(属性)
const p = pAll[0]
p.setAttribute('data-name', 'imooc')
p.setAttribute('style', 'color: blue')
3.property(属性)
const pAll = document.querySelectorAll('p')
const p = pAll[0]
p.style.width
p.style.width = "100px"
p.className = 'p1'
p.className
p.nodeName
p.nodeType
6.DOM结构操作
const newDiv1 = document.getElementById('div1')
const newDiv2 = document.getElementById('div2')
const newP1 = document.createElement('p');
newP1.innerHTML = "this name is P"
newDiv1.appendChild(newP1)
const p1 = document.getElementById('p1')
div2.appendChild(p1)
const a = p1.parentNode
console.log(a);
const b = newDiv1.childNodes
console.log(b);
const c = newDiv1.removeChild(元素[0])
console.log(b);
7.DOM性能
1.DOM 操作非常昂贵,避免频繁的操作DOM操作
2.对DOM查询做缓存
for (let = 0; i < document.getElementsByTagName('p').length; i++) {
}
const pList = document.getElementsByTagName('p')
const length = pList.lengthfor(let i = 0; i < length; i++) {
}
3.将频繁操作改为一次性操作
const listNode = document, getElementById('list');
const frag = document.createDocumentFragment()
for (let x = 0; x < 10; x++) {
const li = document.createElement("li");
li.innerHTML = "List item u" + x
frag.appendChild("li");
}
listNode.appendChild(frag)
2.BOM)Browers Object Model) 浏览器对象模型
1. navigator
const ua = navigator.userAgent
const isChrome = ua.indexOf('Chrome')
console.log(isChrome);
2. screen
console.log(screen.width);
console.log(screen.height);
3. loction
console.log(location.href);
console.log(location.protocol);
console.log(location.pathname);
console.log(location.search);
console.log(location.hash);
4. history
history.back()
history.forward()
history.go()
history.pushState()
history.replaceState()
5. 如何识别浏览器的类型
const ua = navigator.userAgent
const isChrome = ua.indexOf('Chrome')
console.log(isChrome);
6. 分析拆解url各个部分
console.log(location.href);
console.log(location.protocol);
console.log(location.pathname);
console.log(location.search);
console.log(location.hash);
3.事件绑定
1. 事件绑定
const btn = document.getElementById('btn1');
btn.addEventListener('click', event => {
console.log('clicked');
})
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const p1 = document.getElementById('btn1');
bindEvent(p1, 'click', e => {
e.target()
e.preventDefault()
alert('clicked')
})
2. 事件冒泡
<body>
<div id="div1">
<p id="p1">激活</p>
<p id="p2">取消</p>
<p id="p3">取消</p>
<p id="p4">取消</p>
</div>
<h1>----------------------------</h1>
<h1>----------------------------</h1>
<div id="div2">
<p id="p5">取消</p>
<p id="p6">取消</p>
</div>
<script>
function bindEvent (elem, type, fn) {
elem.addEventListener(type, fn)
}
const p1 = document.getElementById('p1');
const body = document.body
bindEvent(p1, 'click', e => {
e.stopPropagation()
alert('激活');
})
bindEvent(body, 'click', e => {
alert('取消');
})
</script>
</body>
3. 事件代理
<body>
<div id="div1">
<a href="#">链接1</a>
<a href="#">链接2</a>
<a href="#">链接3</a>
<a href="#">链接4</a>
</div>
<button>
点击增加a标签
</button>
<script>
function bindEvent (elem, type, fn) {
elem.addEventListener(type, fn)
}
const div1 = document.getElementById('div1');
bindEvent(div1, 'click', e => {
e.preventDefault()
const target = e.target
if (target.nodeName === 'A') {
alert(target.innerHTML)
}
})
</script>
</body>
4. 编写一个通用的事件监听函数
function bindEvent (elem, type, selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, event => {
const target = event.target
if (selector) {
if (target.matches(selector)) {
fn.call(target, event)
}
} else {
fn.call(target, event)
}
})
}
5. 描述事件冒泡的流程
1. 基于DOM树形结构
2. 事件会顺着触发元素向上冒泡
3. 应用场景: 事件代理
6. 无限下拉的图片列表,如何监听每个图片的点击?
1.事件代理
2.使用e.target获取触发元素
3.用matches 来判断是否是触发元素
4.ajax
1.XMLHttpRequest
0. UNSET 尚未调用open方法
1. OPENED open 方法已被调用
2. HEADERS_RECEIVED send 方法已被调用, header 已被接受
3. LOGING 下载中,responseText 已有部分内容
4. DONE 下载完成
1.GET请求
<script>
const xhr = new XMLHttpRequest();
xhr.open('GET', '../test/test.json', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
alert(xhr.responseText)
} else {
alert('其他情况')
}
}
}
xhr.send(null);
</script>
2.POST请求
<script>
const xhr = new XMLHttpRequest();
xhr.open('POST', '/login', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
alert(xhr.responseText)
} else {
alert('其他情况')
}
}
}
const data = {
name: 'zhangsan',
password: '217849'
}
xhr.send(JSON.stringify(data));
</script>
2.状态码
2xx- 表示成功处理请求, 比如常见的200
3xx- 表示需要重定向,浏览器直接跳转
301 永久重定向 从a页面会一直定格到b页面
302 临时重定向 从a页面跳转到b页面 下一次进来还是进入a页面
304 资源未被改变 可以做性能优化
4xx 客户端请求错误
404 找不到页面 访问不存在在的地址
403 未拥有访问权限,像一些内部系统
5xx 服务器端错误 错误一般都会指向后端(服务端)
3.跨域:同源策略,跨域解决方案
1.同源策略
ajax 请求时,浏览器要求当前网页和server必须同源(安全)
同源: 协议,域名,端口,三者必须一致
前端: http:
server: https:
2.加载图片 css,js可以无视同源策略
<img src="跨域的图片地址" /> 但是有些图片资源可能会做一些防盗链设置(后端)
<link href="跨域的css地址" > cdn cdn一般都是外域
<script src="跨域的js地址"> cdn
script 可以实现jsonp
<img /> 可用于统计打点(pv,pu),可使用第三方统计服务(百度统计,站长之家)
3.跨域
所有的跨域,都必须经过server端允许和配置
未经server 端允许就实现跨域,说明浏览器有漏洞,具有较大的安全隐患,容易被攻击
4.手写一个简易的ajax
<script>
function ajax (url, successFn) {
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
successFn(xhr.responseText)
} else {
alert('其他情况')
}
}
}
xhr.send(null);
}
</script>
5.跨域的常用实现方式
1.JSONP
访问一个地址 `http://ashjkh.com/` ,服务端一定会返回一个html文件吗?
服务端可以任意拼接数据返回,只要符合html的格式要求
同理于<script src="http://ashjkh.com/getData.js"> 一定会返回getDatajs吗?
不是的,只要是网址,服务端可以拼接任何的符合格式的数据并且返回
(1) <script> 可以绕过跨域限制
(2) 服务器可以任意动态拼接数据返回
(3) <script> 就可以获得跨域的数据,只要服务端愿意返回
2.CORS-服务器设置 http header
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080/")
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With")
response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")
response.setHeader("Access-Control-Allow-Credentials", "true")
3.框架中
在目前用的vue react框架中的话直接通过配置跨域代理(反向代理),过于简单,不再赘述
5.存储
1. cookie
1.本身用于浏览器和server通讯(本身价值在于 本地和服务器端进行通讯)
2.被借用到本地存储来
3.前端可用document.cookie = '' 来修改() 同一个key会覆盖,不同key会追加
4.(后端也是可以修改的)
缺点:
cookie 最大存储4kb
http请求时需要发送到服务端,增加请求数据量
document.cookie = "..." 不太方便操作
2. sessionStorage和localStorage
1.HTML5 专门为存储而设计的,最大可存储5M
2.API也是比较简单好记,setItem,getItem
3.不会随着http请求被发送出去
4.localStorage数据会永久存储,除非代码或手动删除
5.sessionStorage 数据只存在于当前会话,浏览器关闭则会清空
3. 描述cookie localStorage sessionStorage 的区别
根据上述俩段内容其实回答的时候可以从以下三个方面来回答就OK了
1.容量
2.API的易用性
3.是否会随着http请求发送出去