Web API
DOM 操作 (Documwnt Object Model)
题目六
-
DOM
是那种基本的数据结构- 树
-
DOM
操作常用的API
有哪些 -
DOM
节点的attr
和property
有何区别
知识点
-
DOM
本质
- 文档对象模型 (DOM) 是HTML和XML文档的编程接口。它给文档(结构树)提供了一个结构化的表述并且定义了一种方式—程序可以对结构树进行访问,以改变文档的结构,样式和内容。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Document</title>
</head>
<body>
<div>
<p>this is p</p>
</div>
</body>
</html>
- DOM 节点操作
- 获取 DOM 节点
1. getElementById
var elem = document.getElementById("test") // 元素
2. getElementsByTagName
var paras = document.getElementsByTagName("p"); // 集合
3. getElementsByClassName
var elements = document.getElementsByClassName('tab'); // 类似数组的对象
4. getElementsByName // getElementsByName方法用于选择拥有name属性的HTML元素
// 假定有一个表单是<form name="x"></form>
var forms = document.getElementsByName("x");
forms[0].tagName // "FORM"
5. querySelector // querySelector方法返回匹配指定的CSS选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null。
var el1 = document.querySelector(".myclass");
var el2 = document.querySelector('#myParent > [ng-click]'); // querySelector方法无法选中CSS伪元素。
6. querySelectorAll // querySelectorAll方法返回匹配指定的CSS选择器的所有节点,返回的是NodeList类型的对象。
var matches = document.querySelectorAll("div.note, div.alert"); //querySelectorAll方法的参数,可以是逗号分隔的多个CSS选择器返回所有匹配其中一个选择器的元素。
-
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
// 获取nodeName 和 nodeType
console.log(p.nodeName)
console.log(p.nodeType)
attribute :
var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data-name')
p.setAttribute('data-name', 'imooc')
p.getAttribute('style')
p.getAttribute('style', 'font-size: 30px')
// 文档上的属性标签
<li class="li">
<a href="#" data-name="a"></a>
</li>
- DOM 结构操作
- 新增节点
createElement
var div1 = document.getElementById('div1')
// 添加新节点
var p1 = document.createElement('p')
div1.appendChild(p1) // 添加新创建的元素
- 获取父元素和子元素
parentElement childNodes
var div1 = document.getElementById('div1')
var parent = div1.parentElement
var child = div1.childNodes
div1.removeChild(child[0])
- 删除节点
var child = div1.childNodes
div1.removeChild(child[0])
题目七
- 如何检测浏览器的类型
function isAndroid(){ return /Android/.test(navigator.userAgent); } funcnction isIphone(){ return /iPhone/.test(navigator.userAgent); } function isIpad(){ return /iPad/.test(navigator.userAgent); } function isIOS(){ return /(iPad)|(iPhone)/i.test(navigator.userAgent); }
- 解析
url
各部分
BOM操作
知识点
-
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属性返回一个只读对象,提供了当前文档的URL信息
// 假定当前网址为http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
document.location.href //"http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
document.location.protocol // "http:"
document.location.host // "www.example.com:4097"
document.location.hostname // "www.example.com"
document.location.port // "4097"
document.location.pathname // "/path/a.html"
document.location.search // "?x=111"
document.location.hash // "#part1"
document.location.user // "user"
document.location.password // "passed"
// 跳转到另一个网址
document.location.assign('http://www.google.com')
// 优先从服务器重新加载
document.location.reload(true)
// 优先从本地缓存重新加载(默认值)
document.location.reload(false)
// 跳转到另一个网址,但当前文档不保留在history对象中,
// 即无法用后退按钮,回到当前文档
document.location.assign('http://www.google.com')
// 将location对象转为字符串,等价于document.location.href
document.location.toString()
// history
history.back()
history.forward()
题目八
- 编写一个通用的事件监听函数
- 描述事件冒泡流程
- 对于一个无限下拉加载图片的页面, 如何给每个图片绑定事件
- 使用代理
事件
知识点
- 通用事件绑定
// 普通事件绑定
var btn = document.getElementById('btn')
btn.addEventListener('click',function(event) {
console.log('clicked')
})
// 通用事件绑定
function bindEvent(el, type, fn) {
el.addEventListener(type, fn)
}
var a = document.getElementById('link')
bindEvent(a, 'click', function(e) {
e.preventDefault() // 阻止默认行为
console.log('clicked')
})
- 关于IE低版本的兼容性
- IE低版本使用
attachEvent
绑定事件 - IE低版本使用量非常少, 很多网站早已不支持
- 要求低 IE ,放弃面试
- 事件冒泡
// html
<div id="div1">
<p id="p1">激活</p>
<p id="p2">取消</p>
<p id="p3">取消</p>
<p id="p4">取消</p>
</div>
<div id="div2">
<p id="p5">取消</p>
<p id="p6">取消</p>
</div>
// js
function bindEvent(el, type, fn) {
el.addEventListener(type, fn)
}
var p1 = document.getElementById('p1')
var body = document.body
bindEvent(p1, 'click', function(e) { // 会发生冒泡事件, stopPropagation阻止冒泡
e.stopPropagation()
console.log('激活')
})
bindEvent(body, 'click', function(e) { // 冒泡
console.log('取消')
})
- 代理
<div id="div1">
<a href="#" id="a1">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
<!- 会随时新增更多 a 标签 -->
</div>
var div = document.getElementById('div1')
div.addEventListener('click', function(e) {
var target = e.target
if (target.nodeName === 'A') {
console.log(target.innerText)
}
})
- 完善通用绑定事件的函数
function bindEvent(el, type, selector, fn) {
// 如果没有第三个参数, selector = fn
if (fn == null) {
fn = selector
selector = null
}
el.addEventListener(type, function (e) {
var target
if(selector) {
target = e.target
// dom 节点是否和选择器匹配
if (target.matches(selector)) {
fn.call(target, e)
}
} else {
fn(e)
}
})
}
// 使用代理
var div = document.getElementById('div1')
bindEvent(div, 'click', 'a', function (e) {
e.preventDefault() // 阻止默认行为
console.log(this.innerHTML)
})
// 不使用代理
var a = document.getElementById('a1')
bindEvent(a, 'click', function (e) {
e.preventDefault()
console.log(a.innerHTML)
})
题目九
- 手动编写一个ajax, 不依赖第三方库
- 跨域的几种实现方式
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)
- IE 兼容性问题
- IE 低版本使用
ActiveXObject
, 和W3C
标准不一样
readyState
- 0 - (未初始化) 还没有调用
send()
方法 - 1 - (载入) 已调用
send()
方法, 正在发送请求 - 2 - (载入完成)
send()
方法执行完成, 已经接收到全部响应内容 - 3 - (交互) 正在解析响应内容
- 4 - (完成) 响应解析完成, 可以在客户端调用
status
-
2xx
- 表示成功处理请求, 如 200 -
3xx
- 需要重定向, 浏览器直接跳转 -
4xx
- 客户端请求错误, 如 404 -
5xx
- 服务端错误
- 跨域
- 什么是跨域
- 浏览器有同源策略, 不允许
ajax
访问其他域接口 - 跨域条件 : 协议 域名 端口 有一个不同就算跨域
- 浏览器有同源策略, 不允许
- 可以跨域的三个标签
<img src="xxx">
<link href="xxx">
<script src="xxx">
- 三个标签的场景
-
<img>
用于打点统计, 统计网站可能是其他域 -
<link><script>
可以使用CDN
,CDN
的也是其他域 -
<script>
可以用于JSONP
-
- 跨域注意事项
- 所有的跨域都必须经过信息提供方允许
- 如果未经允许, 那是浏览器同源策略出现漏洞
-
JSONP 实现原理
-
jsonp
全称是JSON with Padding
,是为了解决跨域请求资源而产生的解决方案。 - 加载
http://xxx/a.html
, 不一定服务端真正有一个a.html
文件, 服务端可以根据请求,动态生成一个文件,返回 - 同理于
<script src="http://xxx.com/api.js">
<script> window.callback = function (data) { // 这里是我们跨域得到信息 console.log(data) } </scrpt> // 下面返回callback({x:100, y: 200}) <script src="http://xxx.com/api.js"> function getBooks(){ var script=document.createElement('script'); script.setAttribute('type','text/javascript'); script.setAttribute('src','http://test.com/bookservice.php?callback=displayBooks'); // 重点 callback= xxx document.body.appendChild(script); } getBooks();
-
服务器端设置
http header
// 第二个参数写跨域名称, 不建议直接写 "*"
response.setHeader("Access-Control-Allow-Origin", "http://a.com, http://b.com")
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With")
response.setHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS")
// 接受跨域的cookie
response.setHeader("Access-Control-Allow-Credentials", "true")
题目十
- 请描述一下
cookie sessionStorage 和 localStorage
的区别 ?- 容量
- 是否在
ajax
中 -
API
易用性
知识点
-
cookie
- 本身用于客户端和服务端通信
- 但是它有本地存储的功能, 于是被 "借用"
- 使用
document.cookie = ...
获取和修改即可
-
cookie
用于存储的缺点- 存储量太小,只有 4kb
- 所有
http
请求都带着, 会影响获取资源的效率 -
API简单
, 需要封装才能用document.cookie = ...
-
sessionStorage 和 localStorage
-
HTML5
专门为存储设计, 最大容量5M
- API 简单易用
localStorage.setItem(key,value)
localStorage.getItem(key)
-
IOS safari
隐藏模式下,localStorage.getItem
会报错 - 建议统一使用
try-catch
封装
-