DOM和BOM

BOM

//window瀏覽器窗口,js可以控制一部分Browser Object Model
//document頁面的主體部分Document Object Model
//window
      location 本地
      history  历史
      screen   屏幕
      navigator  信息
//window下的屬性
document.onmousemove=function(){
   close();//关闭
   open("http://www.163.com","网易","width=400,height=400");//打开
}
console.log(innerWidth,innerHeight);//浏览器内部宽度,高度
console.log(outerWidth,outerHeight);//浏览器外部宽度,高度
​
// 窗口距离屏幕左上角的位置
console.log(screenLeft,screenTop)
console.log(screenX,screenY)
​
location.reload();//重载,刷新当前页面;reload(true)方法:刷新页面,如果参数为true,通过缓存刷新。[注意: 不要写在全局,不然浏览器就会一直处在刷新状态]
//reload()方法用于刷新当前文档。reload() 方法类似于浏览器上的刷新页面按钮。
//如果把该方法的参数设置为 true,那么无论文档的最后修改日期是什么,它都会绕过缓存,从服务器上重新下载该文档。这与用户在单击浏览器的刷新按钮时按住 Shift 健的效果是完全一样。
location.href="http://www.163.com";
location.assign("http://www.163.com");
location.replace("http://www.163.com")
​
// encodeURIComponent函数可把字符串作为 URI 组件进行编码
//http%3A%2F%2Fw3cschool.cc%2Fmy%20test.php%3Fname%3Dst%C3%A5le%26car%3Dsaab
// decodeURIComponent
​
document.onclick=function(){
    console.log(location.href)//可以获取当前页面的地址
    location.href="http://www.163.com";//可以设置跳转当前页面地址,獲取當前頁面的地址encodeURIComponent
    location.assign("http://www.163.com");//可以设置跳转当前页面地址
    location.replace("http://www.163.com");//不产生历史记录
} 
​
console.log(location.hash);//获取#号后面的锚点
console.log(location.search);//获取?号后面的参数
console.log(location.hostname);
console.log(location.pathname);
console.log(location.port);
console.log(location.protocol);//websocket聊天游戲協議,http/https協議,視頻二進制流的協議rtmp協議,qq無連接協議UDP,上傳提交内容ftp
​
history.back();
history.forward();
history.go(-1);//回退1
history.go(0);//刷新
history.go(1);//前进1
​
history.pushState({a:1},"aaa");
history.replaceState({a:1},"aa");
console.log(history);
console.log("aaa");
//仅改变网址,网页不会真的跳转,也不会获取到新的内容,本质上网页还停留在原页面
//做到改变网址却不需要刷新页面,这个特性后来用到了单页面应用中
//window.history.pushState(data, title, targetURL);
//状态对象:传给目标路由的信息,可为空(一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null)
//页面标题:目前所有浏览器都不支持,填空字符串即可
//可选url:目标url,不会检查url是否存在,且不能跨域。如不传该项,即给当前url添加data
//特点:pushState()可以创建历史,可以配合popstate事件,可以使用history.go(-1)返回到上一个页面。
​
//window.history.replaceState(data, title, targetURL);
//类似于pushState,但是会直接替换掉当前url,而不会在history中留下记录
//特点:replaceState不会加入到历史记录里面,用history.go(-1)会跳过当前页面相当于是history.go(-2)。
​
console.log(screen.availWidth,screen.availHeight);//不包含任务宽高
console.log(screen.width,screen.height);//整个屏幕宽高
​
console.log(navigator.userAgent);
console.log(navigator.appName)
console.log(navigator.appVersion)
console.log(navigator.platform)
console.log(getBrowserInfo());
function getBrowserInfo(){
    if(navigator.userAgent.indexOf("Chrome")>-1) return "Chrome:"+navigator.userAgent.split("Chrome")[1].split(" ")[0].slice(1);
    if(navigator.userAgent.indexOf("Firefox")>-1) return "Firefox:"+navigator.userAgent.split("Firefox")[1].slice(1); 
} 
//Window 尺寸
//有三种方法能够确定浏览器窗口的尺寸。
//对于Internet Explorer、Chrome、Firefox、Opera 以及 Safari:
window.innerHeight - 浏览器窗口的内部高度(包括滚动条)
window.innerWidth - 浏览器窗口的内部宽度(包括滚动条)
//对于 Internet Explorer 8、7、6、5:
document.documentElement.clientHeight
document.documentElement.clientWidth
//或者
document.body.clientHeight
document.body.clientWidth
//实用的 JavaScript 方案(涵盖所有浏览器):
var w=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
var h=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;
//来自 navigator 对象的信息具有误导性,不应该被用于检测浏览器版本,这是因为:
//navigator 数据可被浏览器使用者更改,一些浏览器对测试站点会识别错误,浏览器无法报告晚于浏览器发布的新操作系统,浏览器检测:由于 navigator 可误导浏览器检测,使用对象检测可用来嗅探不同的浏览器。
//由于不同的浏览器支持不同的对象,您可以使用对象来检测浏览器。例如,由于只有 Opera 支持属性 "window.opera",您可以据此识别出 Opera。例子:if (window.opera) {...some action...}
window.name属性是一个字符串,表示当前浏览器窗口的名字。窗口不一定需要名字,这个属性主要配合超链接和表单的target属性使用。

//该属性只能保存字符串,如果写入的值不是字符串,会自动转成字符串。各个浏览器对这个值的储存容量有所不同,但是一般来说,可以高达几MB。
//只要浏览器窗口不关闭,这个属性是不会消失的。举例来说,访问a.com时,该页面的脚本设置了window.name,接下来在同一个窗口里面载入了b.com,新页面的脚本可以读到上一个网页设置的window.name。页面刷新也是这种情况。一旦浏览器窗口关闭后,该属性保存的值就会消失,因为这时窗口已经不存在了。
//如果两个窗口之间不需要通信,建议将子窗口的opener属性显式设为null,这样可以减少一些安全隐患。

var newWin = window.open('example.html', 'newWindow', 'height=400,width=400');
newWin.opener = null;
//上面代码中,子窗口的opener属性设为null,两个窗口之间就没办法再联系了。
//通过opener属性,可以获得父窗口的全局属性和方法,但只限于两个窗口同源的情况(参见《同源限制》一章),且其中一个窗口由另一个打开。<a>元素添加rel="noopener"属性,可以防止新打开的窗口获取父窗口,减轻被恶意网站修改父窗口 URL 的风险。
//window.devicePixelRatio属性返回一个数值,表示一个 CSS 像素的大小与一个物理像素的大小之间的比率。也就是说,它表示一个 CSS 像素由多少个物理像素组成。它可以用于判断用户的显示环境,如果这个比率较大,就表示用户正在使用高清屏幕,因此可以显示较大像素的图片。
//window.innerHeight和window.innerWidth属性,返回网页在当前窗口中可见部分的高度和宽度,即“视口”(viewport)的大小(单位像素)。这两个属性只读。
//用户放大网页的时候(比如将网页从100%的大小放大为200%),这两个属性会变小。因为这时网页的像素大小不变(比如宽度还是960像素),只是每个像素占据的屏幕空间变大了,因为可见部分(视口)就变小了。
//注意,这两个属性值包括滚动条的高度和宽度。

//window.requestAnimationFrame()方法跟setTimeout类似,都是推迟某个函数的执行。不同之处在于,setTimeout必须指定推迟的时间,window.requestAnimationFrame()则是推迟到浏览器下一次重流时执行,执行完才会进行下一次重绘。重绘通常是 16ms 执行一次,不过浏览器会自动调节这个速率,比如网页切换到后台 Tab 页时,requestAnimationFrame()会暂停执行。
//如果某个函数会改变网页的布局,一般就放在window.requestAnimationFrame()里面执行,这样可以节省系统资源,使得网页效果更加平滑。因为慢速设备会用较慢的速率重流和重绘,而速度更快的设备会有更快的速率。
//该方法接受一个回调函数作为参数。

//window.requestAnimationFrame(callback)上面代码中,callback是一个回调函数。callback执行时,它的参数就是系统传入的一个高精度时间戳(performance.now()的返回值),单位是毫秒,表示距离网页加载的时间。
//window.requestAnimationFrame()的返回值是一个整数,这个整数可以传入window.cancelAnimationFrame(),用来取消回调函数的执行。
//下面是一个window.requestAnimationFrame()执行网页动画的例子。

var element = document.getElementById('animate');
element.style.position = 'absolute';
​
var start = null;
​
function step(timestamp) {
  if (!start) start = timestamp;
  var progress = timestamp - start;
  // 元素不断向左移,最大不超过200像素
  element.style.left = Math.min(progress / 10, 200) + 'px';
  // 如果距离第一次执行不超过 2000 毫秒,
  // 就继续执行动画
  if (progress < 2000) {
    window.requestAnimationFrame(step);
  }
}
​
//window.requestAnimationFrame(step);
//上面代码定义了一个网页动画,持续时间是2秒,会让元素向右移动。
//它跟window.requestAnimationFrame()的区别在于,后者指定回调函数在下一次浏览器重排时执行,问题在于下一次重排时,系统资源未必空闲,不一定能保证在16毫秒之内完成;window.requestIdleCallback()可以保证回调函数在系统资源空闲时执行。
//需要注意的是,如果脚本网址与网页网址不在同一个域(比如使用了 CDN),浏览器根本不会提供详细的出错信息,只会提示出错,错误类型是“Script error.”,行号为0,其他信息都没有。这是浏览器防止向外部脚本泄漏信息。一个解决方法是在脚本所在的服务器,设置Access-Control-Allow-Origin的 HTTP 头信息。

//Access-Control-Allow-Origin: *
///然后,在网页的<script>标签中设置crossorigin属性。

<script crossorigin="anonymous" src="//example.com/file.js"></script>
//上面代码的crossorigin="anonymous"表示,读取文件不需要身份信息,即不需要 cookie 和 HTTP 认证信息。如果设为crossorigin="use-credentials",就表示浏览器会上传 cookie 和 HTTP 认证信息,同时还需要服务器端打开 HTTP 头信息Access-Control-Allow-Credentials。
//window.resizeTo()方法用于缩放窗口到指定大小。
//它接受两个参数,第一个是缩放后的窗口宽度(outerWidth属性,包含滚动条、标题栏等等),第二个是缩放后的窗口高度(outerHeight属性)。

window.resizeTo(
  window.screen.availWidth / 2,
  window.screen.availHeight / 2
)
//上面代码将当前窗口缩放到,屏幕可用区域的一半宽度和高度。
//window.resizeBy()方法用于缩放窗口。它与window.resizeTo()的区别是,它按照相对的量缩放,window.resizeTo()需要给出缩放后的绝对大小。
//它接受两个参数,第一个是水平缩放的量,第二个是垂直缩放的量,单位都是像素。

window.resizeBy(-200, -200)
//上面的代码将当前窗口的宽度和高度,都缩小200像素。

参考资料:

https://wangdoc.com/javascript/bom/index.html

DOM節點

// node  标签  注释  文本  文档
// 任何标签的nodeName都是该标签的大写字母
console.log(document.body.firstChild.nodeName==="DIV");
console.log(document.body.firstChild.constructor===HTMLDivElement);
console.log(document.body.firstChild.nodeType);
console.log(document.body.firstChild.nodeValue);
​
document.getElementById("id");//通过id获取元素
var list=document.getElementsByTagName("div");
//通过标签名获取标签列表,只能通过document获取,HTMLCollection
​
var list=document.getElementsByClassName("div1") 
//通过Class名获取标签列表,任何标签都可以获取其子项中Class列表,HTMLCollection
console.log(list)
​
var list=document.getElementsByName("sex");
//通过name属性获取节点列表,只能通过document获取,NodeList
// NodeList
​
// 选择选择器列表中的第一个元素
var div=document.querySelector(所有选择器)
var div=document.querySelector("#div0");
var div=document.querySelector(".div1");
var div=document.querySelector("[type=text]");
var div=父容器.querySelector()
​
// 选择选择器可以获取的所有元素
var div=document.querySelectorAll(所有选择器)
​
var div0=document.getElementById("div0");
var list=div0.getElementsByClassName("div1");
console.log(list);
div0.innerHTML="aaa";
​
var  forms=document.getElementById("form0");
console.log(forms)
var list=forms.getElementsByName("sex");
console.log(list); 
​
//nodeList是有forEach方法遍历  
var list=document.getElementsByName("sex");
    list.forEach(function(item){
    console.log(item);
})
// 节点遍历
console.log(document.body.children);//所有子元素的列表HTMLCollection
console.log(document.body.childNodes);//所有子节点列表
console.log(document.body.firstChild);//第一个子节点
console.log(document.body.firstElementChild);//第一个子元素
console.log(document.body.lastChild);//最后一个子节点
console.log(document.body.lastElementChild);//最后一个子元素
console.log(document.body.lastElementChild.previousSibling);//上一个兄弟节点
console.log(document.body.lastElementChild.previousElementSibling);//上一个兄弟元素
console.log(document.body.firstElementChild.nextSibling);//下一个兄弟节点
console.log(document.body.firstElementChild.nextElementSibling);//下一个兄弟元素
console.log(document.body.firstChild.parentNode);//父节点
console.log(document.body.firstChild.parentElement);//父元素

DOM的創建和使用

//创建元素document.createElement(标签名)
var div=document.createElement("div");
div.style.width="100px";
div.style.height="100px";
div.style.backgroundColor="red";
//appendChild追加到子元素中    父元素.appendChild(子元素)
document.body.appendChild(div);
​
var script=document.createElement("script");
var img=document.createElement("img");
var table=document.createElement("table");
​
var bn=document.querySelector("button");
var div0=document.querySelector("#div0");
bn.onclick=function(){
    console.log('aaaa');
    div0.innerHTML+="<div></div>";//会把button覆盖只能点击一次
} 
​
var str="aaa";
str+="aaa";
str=str+"aaa";
​
var bn=document.querySelector("button");
bn.onclick=function(){
    var div=document.createElement("div");
    document.body.appendChild(div);
} 
​
function ce(type,style,parent){
    var elem=document.createElement(type);
    for(var prop in style){
        elem.style[prop]=style[prop];
    }
    if(typeof parent==="string") parent=document.querySelector(parent);
    if(parent){
        parent.appendChild(elem);
    }
    return elem;
}
​
var div=ce("div",{
    width:"50px",
    height:"50px",
    backgroundColor:"red"
});
document.body.appendChild(div); 
​
var div=ce("div",{
    width:"50px",
    height:"50px",
    backgroundColor:"red"
},"#div0"); 
​
document.addEventListener("click",clickHandler);
​
function clickHandler(e){//事件函数里参数只能为e,包含点击的一部分数据
    Utils.ce("div",{
    width:"50px",
    height:"50px",
    backgroundColor:Utils.randomColor(),
    position:"absolute",
    left:e.x-25+"px",
    top:e.y-25+"px"
    },"body");
} 
​
// 碎片容器
var con=document.createDocumentFragment();
​
var ul=document.createElement("ul");
for(var i=0;i<10;i++){
    var li=document.createElement("li");
    li.innerHTML=i;
    ul.appendChild(li);//创建多个子元素放到页面,效率低下
}
document.body.appendChild(ul);
​
var con=document.createDocumentFragment();
for(var i=0;i<10;i++){
    var div=document.createElement("div");
    con.appendChild(div);
}
document.body.appendChild(con); 

DOM插入複製和刪除替換

var span=document.createElement("span");
span.textContent="你好";//给div设置文本内容,不能设置html
//textContent与innerHTML的区别:innerHTML主要的作用是在标签中设置新的html标签内容,是有标签效果的
//为了在元素中检索或写入文本,人们使用innerHTML。但是,textContent通常具有更好的性能,因为文本不会被解析为HTML。此外,使用textContent可以防止 XSS 攻击。
​
document.body.appendChild(div);
// 父容器.insertBefore(要插入的元素,插入在谁的前面);
document.body.insertBefore(div,document.body.firstChild)
​
var div0=document.querySelector("#div0");
// 插入在子元素的最尾部
div0.appendChild(span);
// 插入在子元素的最前面
div0.insertBefore(span,div0.firstChild);
​
// 插入在元素的兄弟项前面
div0.parentElement.insertBefore(span,div0);
​
// 插入在元素的兄弟项后面
div0.parentElement.insertBefore(span,div0.nextSibling);
​
// 给指定元素列表中的内容增加外容器
function wrap(elemType,newType){
    var elems=document.querySelectorAll(elemType);
    elems.forEach(function(item){
        var parent=document.createElement(newType);
        item.parentElement.insertBefore(parent,item);
        parent.appendChild(item);
    })
}
wrap("span","div"); 
​
function wrapAll(elemType,newType){
    var elems=document.querySelectorAll(elemType);
    if(elems.length===0) return;
    var parent=document.createElement(newType);
    elems[0].parentElement.insertBefore(parent,elems[0]);
    elems.forEach(function(item){
        parent.appendChild(item);
    })
}
wrapAll("span","div"); 
​
// 创建文本节点
var txt=document.createTextNode("你好");
div0.insertBefore(txt,div0.firstElementChild);
​
var p=document.createElement("p");
// 父容器.replaceChild(新的子元素,要替换掉旧元素);
div0.replaceChild(p,div0.firstElementChild);
​
// 删除节点
// 父容器.removeChild(子元素);
​
// 子元素.remove()
// 在删除时,元素仅仅是从页面中删除,不是从内存删除
div0.addEventListener("click",clickhandler);
function clickhandler(){
    console.log("aaa");
} 
div0.remove();
div0=null;//需要在设值null之前将事件也需要删除
document.body.appendChild(div0);
// 如果在没有清楚内存的情况下还可以加入回去
​
div0.textContent="";
div0.innerHTML="";
​
// 复制  复制元素=复制目标.cloneNode(深浅复制) 
// true  深复制  复制元素和元素的所有子元素和节点
// false  浅复制 仅复制当前元素
var span1=document.querySelector("#span1");
var span2=span1.cloneNode(true);
// 复制标签时,会标签的属性一起复制
span2.id="span2";
div0.appendChild(span2);

DOM屬性

var div=document.querySelector("div");
var input=document.querySelector("input");
div.aa=3;
​
// DOM 对象属性
// DOM的对象属性,分为自定义型和原DOM对象属性
console.dir(div);
// DOM的对象原属性与DOM对象的标签属性部分对应,部分有差别
div.className="div1";//就是设值class标签属性
div.id="div2";
div.style="width:100px;height:100px;"
div.stlye.width="100px";
​
input.name="user";
input.checked=true;
input.placeholder="用户名"
​
div.aa=10;
console.log(div.aa);
// DOM 标签属性
// 设置标签的属性和值,值和属性都必须是字符类型
// DOM的标签属性命名,不能使用大小写区分不适用下划线区分
// 属性名必须全小写字母,并且使用-区分每个单词
div.setAttribute("shop-data","10");
// 获取标签属性
console.log(div.getAttribute("shop-data"));
console.log(div.getAttribute("class"));
// 删除标签属性
div.removeAttribute("shop-data");
​
document.body
document.title
document.head
document.URL   当前页面地址
document.domain  域名
​
var str="欢迎同学们来千锋好程序员学习H5的课程。";
var i=0;
setInterval(animation,400);
​
function animation(){
    i++;
    if(i>str.length-1) i=0;
    document.title=str.slice(i);
} 

DOM样式

var div0=document.querySelector("#div0");
div0.style.width="100px";
div0.style.height="100px";
div0.style.backgroundColor="red"; 
div0.style.width="100px";
div0.style.height="100px";
div0.style.border="1px solid #000000";
div0.style.backgroundColor="#FF0000"; 
// 上面的对象写法,需要将所有的css中-字母 替换为大写字母
// 例如  font-size    fontSize
// 而style字符串方式写法,按照原css行内样式填写
​
div0.style="width:100px;height:100px; padding-right: 0.1px;">Object.assign()  复制对象  浅复制
var o={a:1,b:2};
var o1={};
Object.assign(o1,o);
o.a=10;
console.log(o,o1); 
​
Object.assign(div0.style,{
    width:"50px",
    height:"50px",
    backgroundColor:"red"
}) 
​
// 增添class样式
div0.className="div1";
div0.className+=" div2";
​
div0.className=div0.className.replace("div1","");
// 如果DOM的行内样式有内容,可以通过这个方式获取对于的行内样式
// 如果DOM的样式在CSS中,这时候还没有渲染所以无法计算CSS的样式,这种style获取是不能获得CSS样式的
console.log(div0.style.width);
​
// 想要获取计算后样式,就需要使用getComputedStyle获取元素的样式
console.log(getComputedStyle(div0).width);//不支持IE8及以下
console.log(div0.currentStyle.width);
var style;
try{
    style=getComputedStyle(div0);
}catch(error){
    style=div0.currentStyle;
} 
​
for(var i=0;i<document.styleSheets[0].cssRules.length;i++){
    console.log(document.styleSheets[0].cssRules[i].selectorText)
    for(var j=0;j<document.styleSheets[0].cssRules[i].style.length;j++){
        var key=document.styleSheets[0].cssRules[i].style[j];
        // console.log(key, document.styleSheets[0].cssRules[i].style[key]);
        if(document.styleSheets[0].cssRules[i].selectorText===".div2"){
            document.styleSheets[0].cssRules[i].style.color="green";
        }
    }
} 
console.log(document.styleSheets[0]);
​
var styles={
    ".div1":{
        width:"50px",
        height:"50px",
        backgroundColor:"red"
    },
    ".div2":{
        fontSize:"20px",
        color:"#FFFFFF"
    }
}
Utils.setStyle(styles);
init();
function init(){
    var style=document.createElement("style");
    document.head.appendChild(style);
    var styleSheet=document.styleSheets[document.styleSheets.length-1];
    for(var prop in styles){
        addCss(styleSheet,prop,styles[prop]);
    }
}
​
function addCss(styleSheet,selector,style){
    // console.log(styleSheet,selector,style)
    // console.log(styleSheet.insertRule)
    var str=selector+" {";
    for(var prop in style){
        var value=style[prop]
        prop=prop.replace(/([A-Z])/g,function($1){
        return "-"+$1.toLowerCase();
    })
    str+=prop+":"+value+";"
    }
    str+=" }";
    styleSheet.insertRule(str,styleSheet.cssRules.length);
} 

DOM对象的常见属性

<!-- asdkjasldjaslkjdlaskjdlaksjdlaskjdlkasjdlksajdlkasjdlkasjdlkasjdlsakjdlaksjdlaskjdlakjsdlaskjdlkasjdlaksjdlaksjdlkasjdlaskjdlaksjdlkajsdlkajsdlkasjdlakjsdlkasjdlkasjdlaksjdlkasjdlaksjdlk<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> -->
<!-- <div class="div0">lkajsdlkajsdlkjasdlkjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br>kjsadlkjadlksjd<br></div> -->
<div class="div1">
    <div class="div2">
        asdlkasdlaksdlaskasdasdasdasdasdasdasdasdsadsadasddlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
        asdlkasdlaksdlaskdlas<br>
    </div>
</div>
var div=document.querySelector("div");
// 宽高
// clientWidth  clientHeight   客户宽高
// offsetWidth  offsetHeight   偏移宽高
// scrollWidth  scrollHeight   滚动内容宽高
​
// DOM的宽高问题
console.log(div.clientWidth,div.clientHeight);//计算后宽高=宽高+padding-(如果有滚动条,减去滚动条宽高)
console.log(div.offsetWidth,div.offsetHeight);//计算后宽高=宽高+padding+border
console.log(div.scrollWidth,div.scrollHeight);//如果没有超出 等同于clientWidth和clientHeight
// 如果超出就是实际内容所占的宽高,但是padding没有右侧和下侧
// 如果超出就是实际内容所占的宽高,但是padding没有右侧和下侧-(如果有滚动条,减去滚动条宽高)
// html和body宽高问题
document.documentElement   html标签
document.body    body标签
​
console.log(document.body.clientWidth,document.body.clientHeight);//实际body的宽度和高度-滚动条宽高
console.log(document.body.offsetWidth,document.body.offsetHeight);//实际body的宽度和高度-滚动条宽高
console.log(document.body.scrollWidth,document.body.scrollHeight);//实际body中内容的宽高
​
console.log(document.documentElement.clientWidth,document.documentElement.clientHeight);//当前文档的可视宽高-(如果有滚动条,减去滚动条宽高)
console.log(document.documentElement.offsetWidth,document.documentElement.offsetHeight);//当前文档的内容宽高-(如果有滚动条,减去滚动条宽高)
console.log(document.documentElement.scrollWidth,document.documentElement.scrollHeight);//当前文档的可视宽高
//如果有滚动条,就是实际body撑开的宽高     
​
// 位置
// clientLeft  clientTop   客户位置
// offsetLeft  offsetTop    偏移位置
// scrollLeft  scrollTop    滚动条位置
​
// DOM的位置问题
var div2=document.querySelector(".div2");
div2.addEventListener("scroll",scrollHandler);
console.log(div2.clientLeft,div2.clientTop);//边线的宽高
console.log(div2.offsetLeft,div2.offsetTop);//当前div到父容器左上角的距离(父容器是定位),
// 它和position的left和top是相同的
​
console.log(div2.scrollLeft,div2.scrollTop);//当前元素的滚动条位置
//  前面的这些属性都是只读,但是这个是可以修改的
div2.scrollLeft=100;//滚动条位置设置
var rect=div2.getBoundingClientRect();
console.log(rect);
rect.x===rect.left;
rect.y===rect.top;   当前元素到可视窗口左上角的位置
​
function scrollHandler(e){
    console.log(div2.scrollLeft,div2.scrollTop);
} 
// html和body位置问题
​
// html和body的clientLeft ,offsetLeft 不考虑
// document.body.scrollTop=100;
// 页面中的滚动是html的scrollTop和scrollLeft控制
// 早期的浏览器是body控制
// document.documentElement.scrollTop=200;

历史列表

<style>
    div{
        width: 100px;
        height: 40px;
        font-size: 30px;
        line-height: 40px;
        text-align: center;
        border:1px solid #000000;
        float: left;
        margin-left: 50px;
        user-select: none;
    }
    p{
        clear: both;
        display: none;
    }
</style>
<div>水果</div>
<div>蔬菜</div>
<div>零食</div>
<div>饮料</div>
<br>
<br>
<p>猕猴桃
    苹果
    梨</p>
<p>白菜
    土豆
    地瓜</p>
<p>辣条
    牛肉干
    薯片</p>
<p>可乐
    雪碧
    果汁</p>
var arr,divs;
init()
function init(){
    // 当历史前进或者后退时就会收到这个事件
    window.onpopstate=popStateHandler;
    arr=Array.from(document.getElementsByTagName("p"));
    divs=Array.from(document.getElementsByTagName("div"));
    arr[0].style.display="block";
    for(var i=0;i<divs.length;i++){
        divs[i].onclick=clickHandler;
    }
    
}
​
function clickHandler(){
    var index=divs.indexOf(this);
//    history.pushState({state:1},"","#"+this.innerHTML);
    // 在历史记录列表中增加数据,后面的#内容标示当前跳转部分
        history.pushState({index:index}, "", "#" +this.innerHTML);
        changeMenu(index);
}
​
function popStateHandler(){
    console.log(history.state);
    changeMenu(history.state.index)
}
​
function changeMenu(index){
for(var i=0;i<arr.length;i++){
        if(i===index){
            arr[i].style.display="block";
        }else{
            arr[i].style.display="none";
        }
    }
}

普通列表

<style>
    div{
        width: 100px;
        height: 40px;
        font-size: 30px;
        line-height: 40px;
        text-align: center;
        border:1px solid #000000;
        float: left;
        margin-left: 50px;
        user-select: none;
    }
    p{
        clear: both;
        display: none;
    } 
</style>
<div>水果</div>
<div>蔬菜</div>
<div>零食</div>
<div>饮料</div>
<br>
<br>
<p>猕猴桃
    苹果
    梨</p>
<p>白菜
    土豆
    地瓜</p>
<p>辣条
    牛肉干
    薯片</p>
<p>可乐
    雪碧
    果汁</p>
var arr,divs;
init()
function init(){
    arr=Array.from(document.getElementsByTagName("p"));
    divs=Array.from(document.getElementsByTagName("div"));
    arr[0].style.display="block";
    for(var i=0;i<divs.length;i++){
        divs[i].onclick=clickHandler;
    }
}
​
function clickHandler(){
    var index=divs.indexOf(this);
    for(var i=0;i<arr.length;i++){
        if(i===index){
            arr[i].style.display="block";
        }else{
            arr[i].style.display="none";
        }
    }
}

找徐峥

<style>
    div {
      width: 500px;
      height: 500px;
      border: 1px solid #000000;
      font-size: 0;
    }
</style>
<script src="./js/Utils.js"></script>
<div></div>
var n = 2,
  arr = [];
init();
function init() {
  createImageCon(n);
}
​
function createImageCon(n) {
  /*  document.querySelector("div").innerHTML="";
  arr.length=0; */
  for(var i=0;i<arr.length;i++){
      arr[i].remove();
      arr[i]=null;
  }
  arr.length=0;
  for (var i = 0; i < n * n; i++) {
    var img = Utils.ce("img", {
      width: 500 / n + "px",
      height: 500 / n + "px",
    });
    if (i === 0) img.src = "img/1.png";
    else img.src = "img/2.png";
    arr.push(img);
    img.addEventListener("click", clickHandler);
    /*  var url=""
          if(!bool)url=Math.random()>0.5 ? "img/1.png" : "img/2.png";
          else url="img/2.png";
          if(url==="img/1.png") bool=true;
          if(!bool && i===n*n-1) url="img/1.png";
          console.log(url);
          img.src=url; */
  }
  arr
    .sort(function () {
      return Math.random() - 0.5;
    })
    .forEach(function (item) {
      document.querySelector("div").appendChild(item);
    });
}
​
function clickHandler(e) {
  if (this.src.indexOf("1.png") > -1) {
    n++;
  }
  createImageCon(n);
}

Utils.js

var Utils=(function(){
    var time=0;
    var ids=0;
    var timeManage={};
    return {
        timeStart:function(){
            if(time) return;
            time=new Date().getTime();
        },
        timeEnd:function(){
            var t=new Date().getTime()-time;
            time=0;
            return t;
        },
        ts:function(){
            ids++;
            timeManage[ids]=new Date().getTime();
            return ids;
        },
        te:function(id){
            if(!timeManage[id]) return 0;
            var t=new Date().getTime()-timeManage[id];
            delete timeManage[id];
            return t;
        },
        randomColor:function(){
            var col="#";
            for(var i=0;i<6;i++){
                col+=Math.floor(Math.random()*16).toString(16);
            }
            return col;
        },
        ce:function(type,style,parent){
            var elem=document.createElement(type);
            if(style){
                for(var prop in style){
                    elem.style[prop]=style[prop];
                }
            }
            if(typeof parent==="string") parent=document.querySelector(parent);
            if(parent) parent.appendChild(elem);
            return elem;
        }
    }
})();
posted @ 2020-07-15 22:45  菠蘿的旅行  阅读(205)  评论(0编辑  收藏  举报