浏览器对象
一、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-size
CSS属性在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、checkbox
的value
属性返回的永远是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-data
,method
必须指定为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提供了
File
和FileReader
两个主要对象,可以获得文件信息并读取文件
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 单线程&异步&事件循环