BOM DOM
BOM DOM介绍
BOM Browser Object Model(浏览器模型)
DOM Document Object Model(文档模型)
ECMA 标准 所有浏览器必须按照这个标准设计
Model 模型 是一种参考物,浏览器适配
Object 对象 可以添加属性,可以使用.语法
DOM 从属于 BOM
BOM 有一个根节点 --- window
window包括以下根节点
document 文档 --- >DOM的根节点
location 本地
history 历史
navigator 导航
screen 屏幕
BOM
window
window是可以省略的
open("http://www.daidu.com","_blank",width=300,height=300) 打开 用于弹窗
close()关闭
1. console.log(innerWidth,innerHeight)//可视窗口宽高
2. console.log(outerWidth,outerHeight)//窗口宽高
location
1.location.host//127.0.0.1:5500 ip+端口号
2.location.hostnmae//127.0.0.1 ip
3.location.port//5500 端口号
4.location.protocol///http: 协议
5.location.pathname//%E6%B5%8B%E8%AF%95.html 路径和页面地址
6.location.origin//http://127.0.0.1:5500 协议+ip+端口号
7.location.search//?a&b ?后面的部分传参用
8.location.hash//#abc 锚点或路由(点击跳转对应位置 #abc 跳转到abc位置) 用于SPA中页面跳转
9.location.reload()//重载(基本不用)
10.location.assign()//只能跳转页面,有历史
11.location.href=""//是一个属性 可以获取当前地址,也可以跳转到指定地址,有浏览历史
12.location.replace//替换页面,没有历史记录
`hash 和 search`
hash 开头多一个#
search使用?开头
hash必须在写search后面 否则会直接带走search的信息
/*
ip 地址 0.0.0.0-255.255.255.255
域名 www.域名.域.地址域 www万维网 域名购买时可以随便取名 域(应用的域 com net edu cc) 地址域 cn hk tw jp
DNS 域名解析系统,是一个大型数据库,用来存储ip和域名的对应表 在浏览器中输入域名后,会去DNS中查找对应的ip地址,然后访问IP地址
端口号 http 80 https 443 如果同一个电脑中有相同的端口号就会造成端口冲突
文件夹和文件不能有中文、全角、空格
*/
http 超文本传输协议
https 加密超文本传输协议(用于数据加密,保证数据安全性) s是SSL加密
http 短链接
socket 长链接 socket伪长链接
RTMP协议 视频推流协议
/*
URI编码格式(浏览器的地址栏) :把中文和符号转为URL编码格式
URI编码格式 地址中不能出现任何全角符号和中文,这是都会被更改为URI编码
decodeURIComponent();//将URI编码格式转换为全角
encodeURIComponent();//将全角转换为URI编码格式
console.log(decodeURIComponent("%E4%BD%A0%E5%A5%BD"))//你好
console.log(encodeURIComponent("你好"))//%E4%BD%A0%E5%A5%BD
*/
CSR Client Side Render 客户端渲染 SPA 单页面应用
SSR Sever Side Render 服务端渲染 SEO 搜索引擎优化
跳转案例
//主页面
<style>
#div1 {
width: 100px;
height: 2000px;
background-color: red;
}
#div2 {
width: 100px;
height: 1200px;
background-color: blue;
}
#div3 {
width: 100px;
height: 400px;
background-color: green;
}
</style>
<a href="./b.html#div2">超链接1</a><!-- 跳转到b的div2 -->
<a href="#div2">超链接2</a><!-- 跳转到自己的div2 -->
<a href="./b.html?小波">超链接3</a><!-- 跳转到b 并传参 在b中使用location.search 可以看到传来的参数 若传的是任何全角符号和中文,都会被更改为URI编码-->
<button id="bn0">按钮1</button>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<script>
var bn0 = document.getElementById("bn0")
bn0.onclick = function () {
// console.log(location.href)
location.href = "./b.html"
// location.assign("./b.html")
// location.replace("./b.html")
}
</script>
//副页面
<style>
#div1 {
width: 100px;
height: 2000px;
background-color: red;
}
#div2 {
width: 100px;
height: 1200px;
background-color: blue;
}
#div3 {
width: 100px;
height: 400px;
background-color: green;
}
</style>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<script>
console.log(location.search)//可以看到location传来的参数 ?%E5%B0%8F%E6%B3%A2
console.log(location.hash)//#div2
</script>
</body>
screen
1.console.log(screen.width,screen.heigh)//屏幕宽高
2.console.log(screen.availWidth,screen.availHeigh)//去除任务栏宽高
navigator
//获取当前浏览器内核和其操作系统的版本,以前根据这个值判断浏览器兼容问题
1.navigator.userAgenvt
2.navigator.clipboard//剪切板
3.navigator.cookieEnabled//是否允许使用cookie
4.navigator.language//语言
5.navigator.appName// 浏览器内核
6.navigator.appVersion// 浏览器当前版本信息
7.navigator.mimeTypes//文档类型
8.navigator.platform// 电脑的品牌
//获取当前的位置 经纬度
9.navigator.geolocation.getCurrentPosition(function(pos){
console.log(pos);
},function(err){
console.log(err)
})
//手机web端 根据当前手机所在的公网ip,推出当前的位置
//手机端 内置获取手机的定位
10.console.log(naigator.onLine)//是否在线
history
1.history.back();//回退
2.history.forward();//前进
3.history.go(0);//刷新页面
4.history.go(1);//前进一个历史记录
5.history.go(-1);//回退一个历史记录
6.history.length //长度 当前历史记录数量
7.history.state //当前历史记录的数据
//向当前历史记录中添加一个新的历史记录,并且存储数据
8.history.pushState(向当前历史记录添加的数据, 无效的标识, 在url地址中添加部分内容,例如search和hash)
//替换当前历史记录的数据
9.history.replaceState(向当前历史记录添加的数据, 无效的标识, 在url地址中添加部分内容,例如search和hash)
//当点击历史回退或者前进时触发
10.window.onpopstate = function () {
}
案例1 hash路由
<style>
html,
body {
height: 100%;
}
ul {
list-style: none;
width: 15%;
border: 1px solid #000;
margin: 0;
height: 100%;
padding: 0;
float: left;
}
ul>li {
height: 50px;
line-height: 50px;
text-align: center;
}
ul>li>a {
text-decoration: none;
color: #000;
display: block;
width: 100%;
height: 100%;
}
#content {
width: 84%;
float: left;
height: 100%;
border: 1px solid #000;
}
</style>
<body>
<ul>
<li id="all"><a href="#all">选择</a></li>
<li id="fruit"><a href="#fruit">水果</a></li>
<li id="vegetable"><a href="#vegetable">蔬菜</a></li>
<li id="oil"><a href="#oil">粮油</a></li>
<li id="meat"><a href="#meat">肉禽</a></li>
</ul>
<div id="content"></div>
<script>
var obj = {
all: `<p>水果、蔬菜、粮油、肉禽</p>`,
fruit: `<p>菠萝、香蕉、西瓜</p>`,
vegetable: `<p>小白菜、油麦菜、西红柿</p>`,
oil: `<p>大米、面粉、黄豆</p>`,
meat: `<p>羊肉、猪肉、牛肉</p>`
}
/*
window.onhashchange是一个JavaScript事件,当浏览器的URL的哈希值(#后面的部分)发生变化时触发。可以通过监听这个事件来实现单页应用的路由功能,从而在不刷新页面的情况下切换不同的页面内容
*/
var content, prevLi;
init();
function init() {
// 当hash改变时
window.onhashchange = hashHandler;
content = document.getElementById("content");
// 如果当前地址中有hash,则直接执行hashHandler,就会获取hash,填充内容改变li背景色
if (location.hash) {
hashHandler()
} else {
// 如果没有hash给当前地址后面添加一个hash默认是login
location.href += "#all"
}
}
function hashHandler() {
var name = location.hash.slice(1);
//此时是#all 所有name是all
// console.log(location.hash)
content.innerHTML = obj[name];
changeLi(name)
}
function changeLi(name) {
// 如果上一次存储的li是真值,有值,就把上一次存储的li背景色换为白色
if (prevLi) {
prevLi.style.backgroundColor = "#FFF"
}
// 根据传入name获取当前点击的li
var li = document.getElementById(name);
// 将这个li存储给prevli,就是本次点击的li,下次点击时就可以用来判断上次点击是谁
//让prevLi 不为undefined
prevLi = li;
// 将本次点击li设置背景色为灰色
li.style.backgroundColor = "#ccc"
}
</script>
案例2 history路由
<style>
html,
body {
height: 100%;
}
ul {
list-style: none;
width: 15%;
border: 1px solid #000;
margin: 0;
height: 100%;
padding: 0;
float: left;
}
ul>li {
height: 50px;
line-height: 50px;
text-align: center;
}
#content {
width: 84%;
float: left;
height: 100%;
border: 1px solid #000;
}
.active {
background-color: #ccc;
}
</style>
<body>
<ul>
<li id="all">选择</li>
<li id="fruit">水果</li>
<li id="vegetable">蔬菜</li>
<li id="oil">粮油</li>
<li id="meat">肉禽</li>
</ul>
<div id="content"></div>
<script>
var obj = {
all: `<p>水果、蔬菜、粮油、肉禽</p>`,
fruit: `<p>菠萝、香蕉、西瓜</p>`,
vegetable: `<p>小白菜、油麦菜、西红柿</p>`,
oil: `<p>大米、面粉、黄豆</p>`,
meat: `<p>羊肉、猪肉、牛肉</p>`
}
var lis, content;
init();
function init() {
lis = document.getElementsByTagName("li")
content = document.getElementById("content")
/*
window.onpopstate是popstate事件在window对象上的事件句柄.
每当处于激活状态的历史记录条目发生变化时,popstate事件就会在对应window对象上触发
*/
window.onpopstate = popstateHandler;
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = clickHandler
}
当第一次进入时没有历史记录,这时候,可以将当前的历史记录替换为login
if (!history.state) {
history.replaceState("all", "all")
}
// 并且执行popstateHandler用来根据当前的History.state改变效果
popstateHandler();
}
function clickHandler() {
//this是指被点击的那个li
// console.log(this.id)
var item = this.id;
content.innerHTML = obj[item]
history.pushState(item, item)
changeLi(item)
}
function popstateHandler() {
// console.log(history.state)
//获取存储历史中的name
content.innerHTML = obj[history.state];
changeLi(history.state)
}
//className是类选择器的名字
function changeLi(item) {
// 根据名字获取到对应的li
var li = document.getElementById(item)
// 根据类名获取元素的列表,多个 同一个类名的li
var prevLi = document.getElementsByClassName("active")[0]
// 如果上一次添加active的li存在,将它的class设置为""
if (prevLi) prevLi.className = "";
// 设置当前li的class为active
li.className = "active";
}
</script>
DOM
DOM创建
通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素
JavaScript 能够改变页面中的所有 HTML 元素、所有 HTML 属性、所有 CSS 样式、对页面中的所有事件做出反应
通过innerHTML写入标签名
使用innerHTML会造成重新渲染div中的所有内容,会覆盖之前的内容
document.body.innerHTML="<div>1</div>"
document.body.innerHTML="<button>开始</button>"
document.body.innerHTML="<button>清零</button>"
<style>
div {
width: 100px;
height: 100px;
background-color: blueviolet;
}
</style>
<body>
<button id="bn1">创建</button>
<script>
var bn = document.getElementById("bn1")
bn.onclick = function () {
//点击按钮创建一个div
document.body.innerHTML="<div>1</div>"//这样会把button覆盖
document.body.innerHTML+="<div>1</div>"//这样不会把button覆盖
//下面方式 同上面+=的方式一样(对上面+=的解释)
var str = document.body.innerHTML + "<div>1</div>"
// console.log(str)
document.body.innerHTML = str;
}
</script>
</body>
node节点
`节点包含标签`
包含内容
标签 html
文本
注释
document
// nodeType节点类型 nodeName节点名 nodeValue节点值
/*
所有的标签nodeName都是这个标签名大写 div 的节点名 DIV
任何html标签的节点值都是null
console.log(div1.nodeType)//1 1是指对应的节点类型是html类型
*/
1.//获取当前body元素的所有子元素(html标签) HTMLCollection
document.body.children
document.body.children.div1
document.body.children.ul0
2.//获取当前body元素的所有子节点 NodeList
document.body.childNodes
3.//获取当前body的父元素
document.body.parentElement
4.//获取当前body的父节点
document.body.parentNode
5.//上一个兄弟元素
document.body.previousElementSibling
6.//上一个兄弟节点
document.body.previousSibling
7.//下一个兄弟元素
document.body.nextElementSibling
8.//下一个兄弟节点
document.body.nextSibling
9.//获取第一个子元素
document.body.firstElementChild
10.//获取第一个子节点
document.body.firstChild
11.//获取最后一个子元素
document.body.lastElementChild
12.//获取最后一个字节点
document.body.lastChild
DOM的操作
获取标签方法
1.//getElementsByTagName 根据标签获取标签列表 HTMLCollection
var lis=document.getElementsByTagName("li")
console.log(lis)//HTMLCollection(6) [li.li0, li.li1.li0, li.li0.li2, li.li0, li.li1.li0, li.li0.li2] 只要是li标签都能获取
2.//getElementsByClassName 根据类名获取标签列表 HTMLCollection
var lis=document.getElementsByClassName("li0")
console.log(lis)//HTMLCollection(6) [li.li0, li.li1.li0, li.li0.li2, li.li0, li.li1.li0, li.li0.li2] 只要类名有li0标签都能获取
3.//getElementById 根据id名获取标签
var uls=document.getElementById("ul0")
console.log(uls)
4.//getElementsByName 根据name名称获取节点列表 NodeList
var cks=document.getElementsByName("hobby")
console.log(cks)
5.//querySelector 根据选择器获取对应的第一个元素
var li=document.querySelector("li")
console.log(li)
6.//querySelectorAll 根据选择器获取到所有的节点列表 NodeList
var lis=document.querySelectorAll("li")
console.log(lis)//NodeList(6) [li.li0, li.li1.li0, li.li0.li2, li.li0, li.li1.li0, li.li0.li2] 只要是li标签都能获取
`nodeList和HTMLCollection的不同`
NodeList直接可以调用forEach, 包含html,字符,注释,document
HTMLCollection 不可以foreach---只能出现标签
'下列元素可以通过父元素调用'
父元素.querySelector
父元素.getElementsByClassName
父元素.getElementsByTagName
父元素.querySelectorAll
方法使用
1. document.createElement(标签名) //根据标签名创建一个标签节点
//这种方式打开DOM树,将新的节点插入到DOM 树中,没有修改里面的其他元素效率不高,会重新回流,重绘
2.父元素.appendChild(子元素) //追加子元素
appendChild可以移动dom节点
//此时是兄弟结构
var div1=document.querySelector("#div1");
var div=document.querySelector("div");
// 移动
div.appendChild(div1);// 把div1添加到div里面
3.document.createTextNode("文本内容") //创建文本节点
4.document.createDocumentFragment(); //创建碎片容器
5.元素.cloneNode(是否深复制); //复制元素 true深赋值 false浅复制
6.元素.insertBefore(要插入的元素,要插入在谁的前面);
7.元素.remove(); //元素直接删除 删除自身
//remove 不是把这个DOM销毁,只是从DOM树中移除
8.父元素.removeChild(子元素) //删除 父删子
9.父元素.replaceChild(新的子元素,要被替换掉子元素);
10.被替换的元素.replaceWith(新元素);
//新元素可以是node节点,可以是标签,也可以是字符串
11.instanceof //判断是否是HTMLElement或者继承于他的类型
12.textContent //放入文本 可以获取换行符 不能设置换行符
// innerHTML与textContent区别
//放入html文本,就会自动转换为文本
document.body.innerHTML="<div>1</div>"
//放入文本就会变成纯文本 显示在浏览器窗口中
document.body.textContent="<div>1</div>"
13.innerText //可以设置换行符 不能获取换行符
打印标签
console.log(document)
// html标签在打印时,有时候会显示为对象效果的,有时候会显示标签效果的
//console.dir() 固定打印为对象样式
console.log(document.documentElement)//html标签
console.dir(document.documentElement)
console.log(document.body)//body标签
console.log(document.title)//title标签内容
console.log(document.styleSheets)//样式对象列表
console.log(document.head)//head标签
//document 由docType和html组成
console.log(document.doctype)
HTML渲染
网页打开时,先把所有的HTML标签变为DOM对象-->把网页中所有标签变成一个DOM树-->把CSS转换成一个CSS树-->再将CSS树和DOM树合并形成渲染DOM树-->加载图片等异步内容完成后-->触发load事件
window.load(function(){
})
/*
当改变已经完成渲染完成的网页时
回流 如果改变的内容是影响其他元素结构和位置
重绘 如果改变的内容不影响其他元素结构和位置
回流比重绘的效率更低,速度更慢,并且执行一次就会造成一次回流,执行多次就会造成多次回流
回流和重绘都会将已经渲染好的D0M渲染树,先拆分为DOM树和CSS树,然后修改对应的内容,并且再次重新染到D0M渲染树
回流在拆分D0M树后,还会调整其他相连或者父级子级的元素DOM树,重绘仅仅操作当前设置的D0M对象的内容
*/
//同步:当默认状态时,js加载先加载完成一个文件后,执行js后才会继续向后执行
//异步:如果不希望在这里等待加载,希望这里加载的同时,继续向后执行后面的html
async 执行异步 在加载完成之后及时执行js
defer 执行异步 在HTML标签DOM树渲染完成后执行
方法案例
//点击添加
//方式1
var bn = document.querySelector("button")
bn.onclick = function () {
var div = document.createElement("div")
document.body.appendChild(div)
}
//方式2
function ce(type, parent) {
var elem = document.createElement(type)
parent.appendChild(elem)
}
var bn = document.querySelector("button")
bn.onclick = function () {
ce("div", document.body)
// var text=document.createTextNode("小波小波")
// document.body.appendChild(text)
}
//添加导航列表
var arr = [
{ href: "http://www.baidu.com", site: "百度" },
{ href: "http://www.163.com", site: "网易" },
{ href: "http://www.jd.com", site: "京东" },
{ href: "http://www.taobao.com", site: "淘宝" },
]
var ul = document.createElement("ul")
arr.forEach(item => {
var li = document.createElement("li")
var a = document.createElement("a")
a.href = item.href;
a.textContent = item.site;
li.appendChild(a)
ul.appendChild(li)
})
document.body.appendChild(ul)
//添加100个div 让其中的值为i
for(var i=0;i<100;i++){
var div=document.createElement("div")
div.textContent=i;
document.body.appendChild(div)
}
//复制
var bn=document.querySelector("button")
//浅复制
// var bn1=bn.cloneNode(false)
//深复制
var bn1=bn.cloneNode(true)
bn1.id="bns"//给bn1设置id
document.body.insertBefore(bn1,bn)//把bn1放到bn前面
// document.body.appendChild(bn1)
//删除bn自己
var bn = document.querySelector("button")
bn.onclick = function () {
document.body.removeChild(bn)
}
//替换
var p=document.createElement("p")
p.textContent="撒旦萨达萨达打撒大的"
var bn=document.querySelector("button")
//以下两句效果一样
document.body.replaceChild(p,bn)
bn.replaceWith(p)
DOM的样式
1.设置行内样式 两种方式
<div></div>
//方式1
var div=document.querySelector("div")
div.style="width:100px;height:100px;background-color:red"
//方式2
div.style.width="100px"
div.style.height="100px"
div.style.backgroundColor="blue"
// getComputedStyle 获取计算后样式 兼容
console.log(getComputedStyle(div).width)
2.css样式
//设置class
var div = document.querySelector("div")
div.className = "div1 div2"
div.classList属性的方法
1)div.classList.add() 添加
2)div.classList.remove() 移除
3)div.classList.replace() 替换
4)div.classList.contains() 判断是否有class
5)iv.classList.forEach(item=>{ 遍历
console.log(item)
})
6) div.classList.toggle() 切换class
注意点
/*
行内样式和css样式不互通
div.style这个对象属性的值(本身是字符串)在生成domd树之后变成了dom的一个对象 由字符串自动变换为 CSSStyleDeclaration 类型 的对象
可以通过console.log(div.style.width)拿到行内样式,但是不能拿到内联样式,需要通过getComputedStyle()
*/
/*
Object.assign(目标对象,...源对象)
复制对象合并对象 属性名相同会覆盖 浅复制 返回目标对象
*/
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { a: 3, c: 4 };
//还是同一个对象
var o4 = Object.assign(o1, o2, o3)
console.log(o4)//{a: 3, b: 2, c: 4}
console.log(o1===o4)//true
与...复制的区别
// 使用...复制对象不再是同一个对象
var o4={...o1,...o2,...o3}
console.log(o4)
console.log(o1===o4)//false
//使用Object.assign() 设置样式
var div = document.querySelector("div")
Object.assign(div.style, {
width: "50px",
height: "50px",
bakgroundColor: "red",
borderRadius: "50px"
})
DOM的属性
css内容补充
<style>
/* 标签有data-main的变 */
div[data-main] {
color: red;
}
div[data-main="ab-1"] {
font-size: 20px;
color: blue;
}
div[data-main="ab-2"] {
font-size: 30px;
color: green;
}
/* 开头为a的变 */
/* div[data-main^=a] {
font-size: 30px;
color: blueviolet;
} */
/* 结尾是b的变 */
div[data-main$=b] {
font-size: 30px;
color: orangered;
}
/* 以ab起头并且后面紧跟一个-, 或者就是ab的*/
div[data-main|=ab] {
font-size: 30px;
color: darkorange;
}
/* 属性值中包含ab */
div[data-main*=ab] {
font-size: 30px;
color: brown;
}
/* 不等于ab的变 */
div:not([data-main*=ab]) {
font-size: 30px;
color: deeppink;
}
/* class属性中是li1 或者class属性时li1前面后面是空格的 */
li[class~=li1] {
color: aquamarine;
}
</style>
<!-- css补充内容 -->
<div title="abc" id="ab-cd" data-main="ab-1">1</div>
<div title="abc" id="ab-cd" data-main="ab-2">1</div>
<div title="abc" id="ab-cd" data-main="ab">1</div>
<div title="abc" id="ab-cd" data-main="ac">1</div>
<ul>
<li class="li1 li2">2</li>
<li class="li2 li3">2</li>
<li class="li3 li1">2</li>
<li class="li1">2</li>
</ul>
1.标签属性
/*
就是直接将属性和值描述在标签中,可以通过选择器获取到的,因为标签的特征,因此标签属性和标签属性值
要求在设置时必须以短横线连接的形式命名 sumValue sum-value
标签属性值必须是字符串而且不能有大写字母
标签属性可以直接在标签上设置,也可以通过js设置标签属性
*/
设置标签属性 dom元素.setAttribute("属性名","属性值")
获取标签属性 dom元素.getAttribute("属性名")
删除属性 dom元素.removeAttribute("属性名")
2.对象属性
DOM有自带的对象属性
对象属性中有部分和标签属性完全相同,有部分和标签属性完全不同,有部分和标签属性名字相同值不同
<div id="div1" title="abc" name="div-user" class="div2"></div>
<input type="text" name="user">
<input type="checkbox" checked="checked">
var div = document.querySelector("div")
div.a = 1
console.log(div.id)
console.log(div.title)
console.log(div.name)
console.log(div.className)
var input = document.querySelector("input")
console.log(input.name)
var ck = document.querySelector("[type=checkbox]")
console.log(ck.checked)
ck.checked = false;
console.log(ck.checked)
init();
function init() {
var num = 10;
var div = document.querySelector("div")
div.num = num
//dom对象可以携带数据传参
div.onclick = clickHandler;
}
function clickHandler() {
console.log(this.num)
}
注意点
/*
1.标签的系统属性一般标签属性名和对象属性名相同 特殊:标签属性的class与DOM对象属性className相同
2.标签如果是表单元素 checked disabled等这些值与属性名相同的属性,对象属性中值就是布尔值(冲突时以对象属性设置为准)
3.表单元素中部分属性例如name value这些系统属性在对象中可以获取,在其他元素中是没有的
4.标签属性的自定义属性,对象属性是无法获取,对象属性中设置的自定义属性,标签属性上也不会显示
*/
DOM常见属性
//要获取这三个元素,要求这个DOM对象必须已经放在body中
//要获取这三个宽高,会自动造成重绘
1. clientWidth,clientHeight 客户宽高 元素边线以内宽高值,不含边线 (元素不带边框的自身宽高)
2. offsetWidth,offsetHeight 偏移宽高 元素占位的宽高 包含边线的宽高 (元素带自身边框的自身宽高)
3. scrollWidth,scrollHeight 滚动条宽高 元素内部实际内容所占的宽度和高度 (元素内部 内容的宽高 当内容小于元素时为元素宽高 当内容大于元素时为内容宽高)
//scrollWidth:返回自身的width + padding,返回数值不带单位
//scrollHeight:返回自身的height + padding,返回数值不带单位
4. document.documentElement HTML 可以使用以上三个属性
/*
// html 可视窗口宽高
console.log(document.documentElement.clientWidth, document.documentElement.clientHeight)
// html (html自身的宽高) offsetHeight是内容的高度
console.log(document.documentElement.offsetWidth, document.documentElement.offsetHeight)
// html内容宽高,没有内容时是可以窗口宽高
console.log(document.documentElement.scrollWidth, document.documentElement.scrollHeight)
*/
5. document.body body
body会有一个8px的margin上下
原因:空元素合并,例如<p><p> 无内容,上下的margin会重合合并为16px,本身一个上边距就是16px 重叠了;
7. clientLeft,clientTop 边线粗细 距离自己的盒子边框的距离
8. offsetLeft,offsetTop 当前元素相对父元素所在的坐标(有定位)
(相对于父元素左上角) 没有定位相对于浏览器的位置
9. scrollLeft,scrollTop 滚动容器的位置
(//只能用于设置了overflow的css样式中,否则这2个属性没有任何意义,并且overflow的值不能为visible,但是可以为hidden、quto、scroll,但是hidden属性最常见)
通过设置div.scrollTop=200,将屏幕停到指定的位置 可以置顶按钮
(只有这一个可以设置,,其余都是只读)
10. onscroll 滚动条滚动事件 当滚动条发生改变时,触发函数
div.onscroll=function(){
console.log(div.scrollLeft,div.scrollTop)
}
11. 浏览器滚动条那个滚动内容位置 console.log(document.documentElement.scrollLeft,document.documentElement.scrollTop)
document.documentElement.scrollTop=300;// 只有当第一次回流完成后可以设置(第一次回流完成之前设置无效)
document.onclick=function(){
document.documentElement.scrollTop=500;//有效
}
//因为此时浏览器第一次渲染已经完成 在点击时才会执行其中代码
菜单案例
<style>
ul {
max-height: 200px;
transition: all 0.5s;
overflow: hidden;
}
ul[hide] {
max-height: 0px;
}
</style>
<body>
<ul>
<li class="city">北京
<ul>
<li>昌平</li>
<li>海淀</li>
<li>朝阳</li>
<li>东城</li>
</ul>
</li>
<li class="city">河北</li>
<li class="city">山西</li>
<li class="city">陕西</li>
</ul>
<script>
var lis;
init();
function init() {
lis = document.getElementsByClassName("city");
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = clickHandler;
}
}
function clickHandler(e) {
//事件触发的目标对象
// console.log(e.target)
if (e.target.className !== "city") return;
var ul = e.target.firstElementChild;
if (!ul) return;
//没有hide 表示现在是展开状态,加上hide属性就会隐藏
if (ul.getAttribute("hide") === null) {
ul.setAttribute("hide", "")
} else {
//如果有hide,表示现在是隐藏,将hide属性删除就会展开
ul.removeAttribute("hide")
}
}
</script>
</body>