JavaScript(04)BOM & DOM

浏览器对象

一、window对象

  • window对象的属性和方法
window.open(url,'_self'):打开一个窗口;
window.close():关闭一个窗口,最好是脚本打开,脚本关闭,不然会有一些问题;
  • window相关事件:·onload、onscroll、onresize

  • 窗口尺寸:innerWidth是指页面的宽度,对应有一个outerWidth指整个浏览器的宽度

var w = window.innerWidth|| document.documentElement.clientWidth|| document.body.clientWidth;
var h = window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight; 
  • 滚动距离
document.body.scrollTop || document.documentElement.scrollTop

二、screen & location & history & navigator

1、screen

2、location

  • location对象表示当前页面的URL信息
  • 一个完整的URL可以用location.href获取
  • location.href='https://www.baidu.com'直接赋值可以实现页面的跳转
  • 要获得URL各个部分的值,可以这么写
location.protocol; // 'http'
location.host; // 'www.example.com'
location.port; // '8080'
location.pathname; // '/path/index.html'
location.search; // '?a=1&b=2'
location.hash; // 'TOP'
  • 刷新当前页面reload和加载新页面assign
if (confirm('重新加载当前页' + location.href + '?')) {
    location.reload();
} else {
    location.assign('https://www.baidu.com'); // 设置一个新的URL地址
}

3、history

  • history.back() - 等同于在浏览器点击后退按钮
  • history.forward() - 等同于在浏览器中点击前进按钮
  • 这个对象已经过时了,最好不要使用了吧

4、navigator

  • navigator对象表示浏览器的信息,最常用的属性包括:
navigator.appName:浏览器名称;
navigator.appVersion:浏览器版本;
navigator.language:浏览器设置的语言;
navigator.platform:操作系统类型;
navigator.userAgent:浏览器设定的User-Agent字符串。
  • 来自 navigator 对象的信息通常是误导性的,不应该用于检测浏览器版本用于书写兼容代码
  • 充分利用JavaScript对不存在属性返回undefined的特性,直接用短路运算符||计算才是书写兼容代码的正解

三、弹出框 & 定时器 & cookie

1、弹出框

  • 对话框:alert(提示框)、confirm(确认框)、prompt(输入框)

2、定时器

  • setTimeout() :只执行一次;停止方法clearTimeout
  • setInterval():循环往复执行;停止方法clearInterval

3、cookie

  • 参考JS 知识点拾遗的cookie部分
  • cookie的安全问题:网页可以引用外部脚本的特性导致cookie容易被恶意的脚本窃取,就是遭到XSS攻击,防止的办法就是服务端设置 cookie 设置为 httpOnly 即可

操作DOM

一、节点获取

  • 最重要的概念:html中万物都是节点(文本节点、元素节点、属性节点、文档节点、注释节点)
  • DOM的操作无外乎就是一个节点的增删改查,无论进行什么操作第一步必须获取到相应的节点

1、通过 id、标签名、类名和选择器获取

  • getElementById 和 getElementsByTagname
  • getElementsByClassName 通过类名获取元素列表
  • querySelector通过 css 选择器获取一个元素
  • querySelectorAll通过 css 选择器获取元素列表
  • 这些方法支持链式操作,可以先获取较近的父节点,再进一步获取目标节点
关于 element 和 node
  • 严格地讲,上面所说的DOM节点是指Element,但是DOM节点实际上是Node,
  • 在HTML中,Node包括Element、Comment、CDATA_SECTION、根节点Document类型等
  • 绝大多数时候我们只关心Element,也就是实际控制页面结构的Node,其他类型的Node忽略即可

2、父子兄弟节点获取

  • 父节点获取
parentNode
offsetParent(获取有定位的父节点)
  • 子节点获取
childNodes 属性返回所有的节点,包括文本节点、注释节点
children   属性只返回元素节点
  • 首尾子节点
firstChild(firstElementChild 不会获取到文本节点,IE9以下不可用)
lastChild(lastElementChild)
  • 兄弟节点获取
nextSibling(nextElementSibling)
previousSibling(previousElementSibling)

二、更新DOM

  • 用innerHTML时要注意,是否需要写入HTML
  • 使用innerText或textContent属性只能设置文本,无法解析html
  • DOM节点的style属性对应所有的CSS,可以直接获取或设置,类似font-sizeCSS属性在JavaScript中改写为驼峰式命名fontSize
innerText 和 textContent
  • innerText基本的浏览器都支持,textContent 低版本的 IE 不支持;
  • textContent 相对于 innerText 保留了一定的格式信息;
示例代码
<!-- HTML结构 -->
<div id="test-div">
  <p id="test-js">javascript</p>
  <p>Java</p>
</div>
// 获取<p>javascript</p>节点:
var js = document.getElementById('test-js');
// 修改文本为JavaScript:
js.innerText = 'JavaScript'
// 修改CSS为: color: #ff0000, font-weight: bold
js.style.color= '#ff0000';
js.style.fontWeight='bold'

三、插入DOM

1、直接使用innerHTML

  • 这个方法很直接暴力,但是会直接替换掉父节点里面的html,有的时候这个是我们不希望发生的

2、获取已有节点插入

  • 这里的操作是原先位置的节点会被删除,然后插入到新的位置
<!-- HTML结构 -->
<p id="js">JavaScript</p>
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>
var
    js = document.getElementById('js'),
    list = document.getElementById('list');
list.appendChild(js);

3、创建新的节点插入

var
    list = document.getElementById('list'),
    haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);
  • 创建 style 节点动态改变样式
var d = document.createElement('style');
d.innerHTML = 'p { color: red }';
document.getElementsByTagName('head')[0].appendChild(d);

4、指定位置插入:insertBefore

var
    list = document.getElementById('list'),
    ref = document.getElementById('python'),
    haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.insertBefore(haskell, ref);

四、删除DOM

  • removeChild 会返回被删除的节点
// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true
  • children属性是一个只读属性,并且它在子节点变化时会实时更新
<div id="parent">
    <p>First</p>
    <p>Second</p>
</div>
var parent = document.getElementById('parent');
parent.removeChild(parent.children[0]);
parent.removeChild(parent.children[1]); // <-- 浏览器报错

五、补充说明

1、关于Node

  • nodeName:nodeName 是只读的
元素节点的 nodeName 等同于标签名
属性节点的 nodeName 是属性名称
文本节点的 nodeName 总是 #text
文档节点的 nodeName 总是 #document
  • nodeValue
元素节点的 nodeValue 是 undefined
文本节点的 nodeValue 是文本文本
属性节点的 nodeValue 是属性值
  • nodeType:具体的值是数字,每个数字代表不同的节点类型
关于nodeList和HTMLCollection
  • HTMLCollection是 HTML 元素的集合
  • NodeList 是文档节点的集合
  • 都是类数组,都有 length 属性和索引

2、属性操作

基本方法
obj.value(不可以传参) 
obj["value"](可以传参)
setAttribute | getAttribute | removeAttribute
相关细节
  • 元素属性基本 html 怎么写 js 就怎么写,除了 class 外:div.className
  • style 属性无论是增加还是获取都是取行间,style 的优先级高于 className
  • 下面封装的方法行间和非行间的样式都可以获取
function getStyle(obj, attr) {
    if(obj.currentStyle){
        return obj.currentStyle[attr];
    }else{
        return getComputedStyle(obj,null)[attr];
    }
}

1.表格的便捷操作:tHead、tFoot、tBodies、rows、cells
2.document对象的一些属性:cookie、domain、body(对象)、forms(页面所有表单集合)


操作表单

  • 常用的表单控件
<input type="text" />文本输入框<br />
<input type="password" />密码输入框<br />
<input type="submit" value="提交按钮" /><br />
<input type="reset" value="重置按钮" /><br />
<input type="radio" />单选按钮<br />
<input type="checkbox" />复选框<br />
<input type="image" />图像<br />
<input type="file" />文件提交<br />
<input type="hidden" />隐藏域<br />
<input type="button" />普通按钮<br />
<select>
	<option>选择列表</option>
	<optgroup>
		<option>下拉子菜单</option>
	</optgroup>
</select>
<textarea>文本区域</textarea>

一、获取值

  • 对于text、password、hidden、select直接使用 value 属性进行获取值
  • 对于radio、checkboxvalue属性返回的永远是HTML预设的值,实际需要获取的是用户是否勾选的信息,所以应该用checked判断
// <label><input type="radio" name="weekday" id="monday" value="1"> Monday</label>
// <label><input type="radio" name="weekday" id="tuesday" value="2"> Tuesday</label>
var mon = document.getElementById('monday');
var tue = document.getElementById('tuesday');
mon.value; // '1'
tue.value; // '2'
mon.checked; // true或者false
tue.checked; // true或者false

二、设置值

  • 值的设置也是直接使用 value 和 checked 属性进行设置即可

一、提交表单

1、普通按钮提交

  • 这种方式的缺点是扰乱了浏览器对form的正常提交,默认是使用submit按钮提交或者enter提交
<!-- HTML -->
<form id="test-form">
    <input type="text" name="test">
    <button type="button" onclick="doSubmitForm()">Submit</button>
</form>

<script>
function doSubmitForm() {
    var form = document.getElementById('test-form');
    // 可以在此修改form的input...
    // 提交form:
    form.submit();
}
</script>

2、提交按钮提交

  • js代码里面 return false 的话表单不会被提交
<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
    <input type="text" name="test">
    <button type="submit">Submit</button>
</form>

<script>
function checkForm() {
    var form = document.getElementById('test-form');
    // 可以在此修改form的input...
    // 继续下一步:
    return true;
}
</script>

3、密码加密提交

  • 使用 MD5 进行加密
  • 最后提交的是有 name 属性的 hidden,没有 name 属性的 password 不会被提交
<!-- HTML -->
<form id="login-form" method="post" onsubmit="return checkForm()">
    <input type="text" id="username" name="username">
    <input type="password" id="input-password">
    <input type="hidden" id="md5-password" name="password">
    <button type="submit">Submit</button>
</form>

<script>
function checkForm() {
    var input_pwd = document.getElementById('input-password');
    var md5_pwd = document.getElementById('md5-password');
    // 把用户输入的明文变为MD5:
    md5_pwd.value = toMD5(input_pwd.value);
    // 继续下一步:
    return true;
}
</script>

4、表单数据验证

  • 利用JavaScript检查用户注册信息是否正确,在以下情况不满足时报错并阻止提交表单
用户名必须是3-10位英文字母或数字;
口令必须是6-20位;
两次输入口令必须一致;
<!-- HTML结构 -->
<form id="test-register" action="#" target="_blank" onsubmit="return checkRegisterForm()">
    <p id="test-error" style="color:red"></p>
    <p>
        用户名: <input type="text" id="username" name="username">
    </p>
    <p>
        口令: <input type="password" id="password" name="password">
    </p>
    <p>
        重复口令: <input type="password" id="password-2">
    </p>
    <p>
        <button type="submit">提交</button> <button type="reset">重置</button>
    </p>
</form>

<script>
'use strict';
var checkRegisterForm = function () {
	var username = document.getElementById('username').value;
	var pass = document.getElementById('password').value;
	var pass_2 = document.getElementById('password-2').value;
	var username_regexp = /^[0-9A-Za-z]{3,10}$/;
	var pass_regexp = /^.{6,20}$/;

	if(!username_regexp.test(username)){
		console.log('用户名错误');
		return false;
	}else if(!pass_regexp.test(pass)){
		console.log('密码错误');
		return false;
	}else if(pass != pass_2){
		console.log('两次密码输入不一致');
		return false;
	}else{
		return true;
	}
}
</script>
H5支持的表单验证
  • <input >添加属性进行输入约束:disabled、required、pattern、max、min
  • css 伪选择器选择相应约束的元素:disabled、invalid、valid、optional、required
  • input 约束验证相关方法
checkValidity() :input 的数据有效则返回 true
setCustomValidity() :设置input元素的 validationMessage(校验提示信息)
  • input 约束验证相关属性
validity   包含一系列和input元素的合法性相关的布尔属性
validationMessage   错误提示信息
willValidate   是否会进行校验
  • validity包含的属性:
customError
patternMismatch
rangeOverflow
rangeUnderflow
stepMismatch
tooLong
typeMismatch
valueMissing
valid
  • 示例代码
<form action="https://www.baidu.com/">
    <input type="text" name="username" required id="f1"><br>
    <input type="number" max="100" min="90" id="f2"><br>
    <input type="submit" value="提交"><br>
</form>

<script>

    window.onload = function () {
        var f1 = document.getElementById('f1');
        var f2 = document.getElementById('f2');
        f1.setCustomValidity('test-validity');
    }

</script>

以上基于html的约束及其验证在IE浏览器不太好使!!!


操作文件

一、文件上传

  • 注意:当一个表单包含<input type="file">时,表单的enctype必须指定为multipart/form-datamethod必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据
  • 以前前端对上传文件能做的操作十分有限,使用 value 进行取值也只能获取到一个假的文件路径
<form action="" enctype="multipart/form-data" method="post">
    <input type="file" id="fff">
</form>
<div id="info"></div>
<script>
    window.onload = function () {
        var info = document.getElementById('info');
        var fff = document.getElementById('fff');
        fff.addEventListener('change', function () {
            info.innerHTML = this.value;
        })
    }
</script>

在这里插入图片描述

二、File API

  • HTML5的File API提供了FileFileReader两个主要对象,可以获得文件信息并读取文件
File API 使用示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #preview {
            width: 200px;
            height: 200px;
            border: 1px solid #000;
            margin-top: 20px;
        }
    </style>
</head>
<body>


<form action="" enctype="multipart/form-data" method="post">
    <input type="file" id="fff">
</form>
<div id="preview"></div>
<div id="info"></div>


<script>
    window.onload = function () {
        var info = document.getElementById('info');
        var fff = document.getElementById('fff');
        var preview = document.getElementById('preview');
        fff.addEventListener('change', function () {
            var file = fff.files[0];
            console.log(file);
            //update info
            info.innerHTML = `
            <p>文件:${file.name}</p>
            <p>大小:${file.size}</p>
            <p>最后修改时间:${file.lastModifiedDate}</p>
            `;
            //update the preview
            preview.style.background = '';
            var reader = new FileReader();
            reader.onload = function (e) {
                var data = e.target.result;
                preview.style.background = 'url(' + data + ')';
            };
            reader.readAsDataURL(file);
        })
    }
</script>

</body>
</html>
关于回调
  • JS是单线程执行,异步执行一般的实现方法就是 事件监听加方法回调
  • 更多关于JS的异步和事件循环的说明参考:JS 单线程&异步&事件循环
发布了153 篇原创文章 · 获赞 51 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/stanwuc/article/details/103958027