一、BOM的常用对象
1.1 history对象
保存了当前窗口的历史纪录(过去的url)
- 前进:history.go(1);
- 后退:history.go(-1);
- 刷新:history.go(0);
<script>
// 前进
history.go(1)
// 后退
history.go(-1)
// 刷新
history.go(0)
</script>
1.2 location对象
保存了当前窗口的正在打开的url(现在的url)
- 一个url的组成部分:
- 协议:*https(加密)/*http(未加密)/ftp(传输文件)/ws(直播)... 前两个都属于叫做请求-响应模型
- 主机号|IP地址|域名:域名是需要花钱购买的,主机号|IP地址是免费,127.0.0.1才真的是叫做主机号,只能自己访问自己
- 端口号:https默认端口为443,http默认端口为80,只有默认端口可以省略不写
- 文件的相对路径|路由:百度加密了
- 查询字符串|请求消息:前端传输到后端的东西
- 获取url的5个部分的内容,可以输入location对象查看:
- 协议:location.protocal;
- 域名:location.hostname;
- 端口:location.port;
- 路由:location.pathname;
- 请求消息:location.search;
<script>
console.log(location);//href:"http://127.0.0.1:5500/%E4%BD%9C%E4%B8%9A/%E6%9D%A8%E7%8E%89%E5%8D%8E%20-%20%E7%AC%AC%E4%B8%89%E5%91%A8%E4%BD%9C%E4%B8%9A/day11/02-location%E5%AF%B9%E8%B1%A1.html"
// 协议
console.log(location.protocol);//http:
// 域名
console.log(location.hostname);//127.0.0.1
// 端口号
console.log(location.port);//5500
// 路由 console.log(location.pathname);///%E4%BD%9C%E4%B8%9A/%E6%9D%A8%E7%8E%89%E5%8D%8E%20-%20%E7%AC%AC%E4%B8%89%E5%91%A8%E4%BD%9C%E4%B8%9A/day11/02-location%E5%AF%B9%E8%B1%A1.html
// 请求消息
console.log(location.search);//
</script>
- 跳转:location="新url" - 替换当前窗口,可以后退
- 跳转后,禁止后退:location.replace("新url") - 替换当前窗口,禁止后退
- 刷新:location.reload();
二、DOM
2.1 查找元素
var elem=document.querySelector("任意css选择器的");
- 缺陷:只能找到单个元素,如果匹配到了多个,也只会返回第一个,没找到null
var elems=document.querySelectorAll("任意css选择器的");
- 优点:
- 找到了是一个集合,没找到是一个空集合
- 复杂查找时,非常简单
- 返回的是一个静态集合NodeList
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var li1 = document.querySelector('li')
console.log(li1)//找到的是第一个ul里面的第一个li
// 要想找到第二个ul里面的所有li
var lis = document.querySelectorAll('ul')[1].querySelectorAll('li')
console.log(lis);
</script>
2.2 document.getXXX 和 document.queryXXX的区别
- 后者更适合复杂查找
- 前者返回的是一个动态集合:每一次DOM发生变化,他都会悄悄的再次查找,让页面和数据保持一致,但是效率也就低下了 - 不支持forEach
- 后者返回的是一个静态集合:每一次DOM发生变化,他不会悄悄的再次查找,让页面和数据没有保持一致,但是效率也就高了 - 支持使用forEach
2.3 操作样式表
- 获取你想要操作的样式表
var sheet=document.styleSheets[i];
- 获取此样式表种所有的样式规则
var rules=sheet.cssRules;
- 数出你想要操作的那个规则的
var rule=rules[i];
- 操作
console.log(rule.style.css属性名)
rule.style.css属性名="css属性值";
2.4 DOM分类:
- 核心DOM:即可以操作HTML又可以操作XML,但是语法相对比较繁琐
- HTML DOM:只可以操作HTML
- XML DOM:只可以操作XML
2.5 操作属性
- 获取属性值:
- 核心DOM:elem.getAttribute("属性名");
- HTML DOM:elem.属性名;
- 设置属性值:
- 核心DOM:elem.setAttribute("属性名","属性值");
- HTML DOM:elem.属性名="属性值";
- 删除属性:设置属性值为空字符串,确实某些属性可以算是删除,但是只是删除了属性值,属性名还在,而有的属性哪怕只有一个属性名,也会具有作用(比如:href、disabled、readonly)
- 核心DOM:elem.removeAttribute("属性名");
- HTML DOM:elem.属性名=""; - 属性节点删不干净
- 判断有没有:只能判断有没有,不能判断是什么,推荐用elem.getAttribute("属性名");去获取到值,自己再写比较运算
- 核心DOM:elem.hasAttribute("属性名");
- HTML DOM:elem.属性名!="";
2.6 元素上树的三种方式:
- 父元素.appendChild(elem);//在父元素末尾处追加一个子元素elem
- 父元素.insertBefore(elem,已有子元素);//在父元素追加一个子元素elem,但是放在已有子元素的前面
- 父元素.replaceChild(elem,已有子元素);//在父元素追加一个子元素elem,但是会替换掉已有子元素
2.7 删除元素:
elem.remove();
三、let
let 变量名=值;
作用:
- 解决了声明提前
- 带来了块级作用域,一个{}就是一个块,此变量只能在那个{}里面使用
- 如果用let去当作下标绑定事件,那么他会记录着你当前元素的下标,不再需要自定义下标了 - 其实forEach的那个形参i就是let创建的
四、类数组转为普通数组:接住=Array.from(类数组对象);
五、案例
<div id="menu"></div>
<span>>></span>
<div id="content"></div>
<script>
// 开关门效果
var span = document.querySelector('span')
span.onclick = function(){
span.innerText = span.innerText == '>>'?'<<':'>>'
content.style.display = span.innerText == '>>'?'block':'none'
}
</script>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<section>
<div class="active"></div>
<div></div>
<div></div>
</section>
<script>
// 选项卡
var lis = document.querySelectorAll('li')
var divs = document.querySelectorAll('div')
lis.forEach((li,i)=>{
li.onclick = function(){
divs.forEach(div=>div.className = '')
divs[i].className = 'active'
}
})
</script>
<ul id="ul">
<li>name1</li>
<li>name2</li>
<li>name3</li>
<li>name4</li>
<li>name5</li>
<li>name6</li>
<li>name7</li>
<li>name8</li>
<li>name9</li>
<li>name10</li>
</ul>
<script>
// 摇号功能
// 拿到所有的li
var lis = document.querySelectorAll('li')
// 创建一个新数组用来装排序的数
var num = []
// 死循环 - 当num的长度和lis的长度一致时退出循环
while(num.length < lis.length) {
// 创建随机数
var r = parseInt(Math.random()*(lis.length))
// 如果num中没有这个数则向num中加入这个数
if(num.indexOf(r) == -1) {
num.push(r)
}
}
// 给li设置自定义属性
lis.forEach((li,i)=>li.setAttribute('nn',num[i]))
// 把类数组变为数组
lis = Array.from(lis)
// 对数组进行排序
lis.sort((a,b)=>a.getAttribute('nn') - b.getAttribute('nn'))
// 上树
lis.forEach(li=>ul.appendChild(li))
</script>
<select id="lsel" size="5" multiple>
<option>Argentina</option>
<option>Brazil</option>
<option>Canada</option>
<option>Chile</option>
<option>China</option>
<option>Cuba</option>
<option>Denmark</option>
<option>Egypt</option>
<option>France</option>
<option>Greece</option>
<option>Spain</option>
</select>
<div>
<button id="btn1">>></button>
<button id="btn2">></button>
<button id="btn3"><</button>
<button id="btn4"><<</button>
</div>
<select id="rsel" size="5" multiple>
</select>
<script>
// 国家的移动
// 设置左右空数组
var larr = [];
var rarr = [];
// 拿到每一个国家并且放在左数组中
larr = lsel.innerHTML.trim().slice(8,-9).split('</option>\n\t\t<option>');
// 拿到所有的button
var btns = document.querySelectorAll('button');
// 遍历btns
btns.forEach(btn=>{
// 点击事件
btn.onclick = function(){
// 判断按钮
switch(this.innerText){
case '>>':
// 把左数组的内容全部拼接到右数组
rarr = rarr.concat(larr);
// 左数组设置为空
larr = [];
break;
case '<<':
larr = larr.concat(rarr);
rarr = [];
break;
case '>':
// 拿到sel1里面的option
var op1 = lsel.children;
// 倒着循环
for(var i = op1.length - 1; i >= 0; i--) {
// 判断option是否被选中
if(op1[i].selected) {
// 如果这个被选中就把这个option给删除了并且拼接到右数组
rarr = rarr.concat(larr.splice(i,1));
}
}
break
default :
var op2 = rsel.children;
for(var i = op2.length - 1; i >= 0; i--) {
if(op2[i].selected) {
larr = larr.concat(rarr.splice(i,1));
}
}
}
// 数组按照字符串pk排序
larr.sort();
rarr.sort();
// 判断左数组的长度是否为0
if(larr.length == 0) {
// 为0则设置左边select内容为空
lsel.innerHTML = '';
} else {
lsel.innerHTML = '<option>' + larr.join('</option><option>') + '</option>';
}
// 右
if(rarr.length == 0) {
rsel.innerHTML = '';
} else {
rsel.innerHTML = '<option>' + rarr.join('</option><option>') + '</option>';
}
}
})
</script>