DOM及其基础操作
- dom:docoument object model 文档对象模型,提供一些属性和方法供我们操作页面上的元素
document和document.documentElement
- document对象是整个html文档,可以通过document.head,document.body等访问具体dom节点。
- document.documentElement是整个dom节点数的根节点,就是html标签
- document包括document.documentElement
获取dom元素的方法
document.getElementById()
指定在文档中基于元素的id或者这个元素对象 ,只取第一个document.getElementsByName()
在整个文档中通过标签的name属性值获取一组节点集合(一般用于表单的获取)document.head document.body document.documentElement
获取页面中的head/body/html 三个元素[content].getElementsByTagName()
在指定上下文中,通过标签名获取一组元素集合[content].getElementsByClassName()
在指定上下文中,通过样式类名获取一组元素集合(不兼容ie678
)[content].querySelector([selector])
在指定上下文中,通过选择器获取到指定的元素对象(不兼容ie678
),参数是选择器,只取第一个[content].querySelectorAll([selector])
在指定上下文中,通过选择器获取到指定的元素集合(不兼容ie678
)
js中的节点和描述节点之间关系的属性
- 节点:Node
- 节点集合:NodeList (使用querySelectorAll/getElementsByName等方法获取的是节点集合)
- 元素集合 (使用getElementsByClassName/getElementsByTagName/getElementsByClassName等方法获取的是元素集合)
- 元素节点
- nodeType:1
- nodeName:大写的标签名
- nodeValue:null
- 文本节点(标准浏览器(非ie 6 7 8 )会把空格和换行符当作一个文本节点)
- nodeType:3
- nodeName:#text
- nodeValue:文本内容
- 注释节点
- nodeType:8
- nodeName:#commen
- nodeValue:注释内容
- 文档节点document
- nodeType:9
- nodeName:#document
- nodeValue:null
描述这些节点之间关系的属性
childNodes
:获取所有的子节点children
: 获取所有的元素子节点firstChild
:获得第一个子节点lasrChild
:获取最后一个子节点firstElementChild
:获取第一个元素子节点lastElementChild
:获取最后一个元素子节点previousSibiling
:获取上一个哥哥节点nextSibling
:获取下一个弟弟节点previousElementSibling/nextElementSibling
获取哥哥或弟弟元素节点不兼容ie678
js中动态增删改元素
createElement
创建元素对象document.createElement('div')
createTextNode
创建文本对象document.createTextNode('这里是文本内容')
appendchild
把元素添加到容器的末尾insertBefore
把元素添加到指定容器中指定元素的前面replaceChild(newNode,oldNode)
用newNode元素替换oldNode这个元素// 容器.insertBefore([新增页面],[指定元素]) var box = document.createElement('div') // 创建一个div box.style.width = '100px' box.style.height = '100px' box.style.backgroundColor = 'red' document.body.appendChild(box); // 把div放进body的末尾 var text = document.createTextNode('div') // 创建一个text document.body.insertBefore(text,box) // 把text放在box这个div中
cloneNode
克隆元素var box1 = document.getElementById('id'); let box2 = box.cloneNode(true) // 深克隆,不仅克隆当前元素,当前元素下的子元素也一并克隆。 let box3 = box.cloneNode(false) // 浅克隆,只克隆当前元素,不克隆子元素 document.body.appendChild(box2) document.body.appendChild(box3) box2.querySelector('span').innerText = '内容2'
removeChild
移除容器中的某个元素// 容器.removeChild(元素) document.body.removeChild(box3)
setAttrbute
设置设置属性(相当于自定义属性,这种属性是直接放在元素标签的结构上,不是添加到堆栈上的)box2.setAttribute('data-index',1)
getAttrbute
获取元素属性box2.getAttrbute('data-index',1)
js盒子模型属性
- 基于一些属性和方法,让我们能够获取当前元素的样式信息
- client 获取的结果没有单位,且是整数
clientwidth
元素可视化内容的宽 clientWidth = width+左右paddingclientHeight
元素可视化内容的宽 clientHeigh = height + 上下paddingclientTop
clientTop = boder.top(上边框的宽度)clientLeft
clientLeft = boder.left(左边框的宽度)
- offset 获取的结果没有单位,且是整数
offsetWidth
元素本身的宽高 offsetWidth = width+左右padding+ 左右borderoffsetHeight
元素本身的高 offsetHeight= height + 上下padding + 上下borderoffsetTop
当前元素 上边框 外边缘 到 最近的已定位父级(offsetParent) 上边框 内边缘的 距离。如果父级都没有定位,则分别是到body 顶部 和左边的距离offsetLeft
当前元素 左边框 外边缘 到 最近的已定位父级(offsetParent) 左边框 内边缘的距离。如果父级都没有定位,则分别是到body 顶部 和左边的距离offsetParent
拥有相对定位的第一个父元素
- scroll 获取的结果没有单位,且是整数 这个属性在不同浏览器情况下不同的数值。而且在使用overflow的话也会影响它的数值
width / height
获取指定标签内容层的真实宽高(可视区域宽高+被隐藏区域宽高)。,在没有滚动的时候,它的值就是clientWidth
和clientHeight
top / left
获取垂直和水平滚动条卷去的高度和宽度
- client 获取的结果没有单位,且是整数
window.getComputedStyle(不兼容ie678【currentStyle】)
- 这个方法能获得页面上展示的元素的所有样式(包括没有设置的,没有设置的获取默认值)
- 获取当前元素所有经过浏览器计算过的样式(只要元素在页面中呈现了,那么所有的样式都是经过浏览器计算的)
- 用法:
window.getComputedStyle[[element],null]
第一个参数是操作的元素,第二个参数是元素的伪类let styleObj = window.getComputedStyle([element],null) styleObj.backgroundColor // 元素的背景颜色
js正则表达式(regular expression :RegExp
)
正则的作用和使用方法
- 用来处理字符串的规则
- 只能处理字符串
- 它是一个规则:可以验证(text方法)字符串是否符合某个规则,也可以把字符串中符合规则的内容捕获(exec方法)
- 使用方法
var reg = new RegExp() reg = /\d+/ // 这就是一个正则表达式
- 创建正则的两种方式以及区别
- 通过字面量方式(两个斜杠包裹的用来描述正则规则的元字符就是正则)
let reg = /\d+/
- 通过构造函数创建正则,它有两个参数:元字符字符串,修饰符字符串,
let reg2 = new RegExp("\\d+")
- 他们之间的区别
- 用构造函数创建的正则中 元字符中的\需要转义
- 用构造函数创建的正则中,可以存在变量
var type = 'aaaa' reg = /^@+type+@$/ // 这里面的type不是一个变量 new RegExp('^@'+type+'@$') // 这里面的type就是变量type的值’aaaa‘
正则中的方法
- RegExp 对象是带有预定义属性和方法的正则表达式对象
test()
它通过模式来搜索字符串,然后根据结果返回 true 或 false。var str = 'hello word' var reg = new RegExp() reg = /\d+/ console.log(reg.test(str));
exec()
它通过指定的模式(pattern)搜索字符串,并返回已找到的文本。如果未找到匹配,则返回 null。var reg = new RegExp() reg = /\d+/ reg.exec('dffsd1') // ["1", index: 5, input: "dffsd1", groups: undefined] // 返回值是一个数组,数组中包括找打内容的索引,以及原始字符串
正则表达式的两部分
元字符
如果字符串中有\的话 需要转义一下,因为字符串中的\默认就是转义字符
let reg = /2.3/
- 量词元字符
+
一到多次*
零到多次?
零次和一次{n}
出现n次{n,}
出现n到多次{n,m}
出现n到m次
- 特殊元字符
\
转义字符(普通-特殊-普通).
除\n以外的任意字符^
以哪一个元字符作为开始
- 组合元字符
\n
除换行符以外的任意字符\d
0~9之间的任意一个数字\D
非0~9之间的数字\w
数字字母下划线中的任意一个字符\W
非数字字母下划线中的任意一个字符\s
一个空白字符(包括空格,制表符【一个tab键】,换页符)\t
一个制表符\d
匹配一个单词的边界x|y
x或者y中的字符[xyz]
xyz三个中的任一个字符[^xy]
非x或者y中的字符[a-z0-9A-Z_]
代表数字字母下划线中的任一个字符 等于/w
()
正则中的分组符号(?:)
只匹配不捕获(?=)
正向预查(?!)
反向预查
修饰符
i
忽略单词大小写匹配m
进行多行匹配g
全局匹配
使用正则元字符时会出现的一下问题
- 使用y|x出现的问题
// x|y会存在一个优先级问题 reg = /^18|19/ reg.test('18') // true reg.text('19') // true reg.text('181') // true reg.text('1219') // true reg1 = /^(18|19)/ reg1.test('18') // true reg1.text('19') // true reg1.text('181') // false reg1.text('1219') // fase
- 使用[],中括号中出现的字符一般都代表本身的含义,但又有些意外
reg = /^[@+]$/ // 这里的[@+]代码字符@和字符+的任意一个 reg = /^[\d]$/ // 这里的[\d] 代表的就是0-9之间的任意一个数字 reg = /^[10-29]/ // 代表的是1或0-2或9 并不是10-29之间的一个数字
常用的正则表达式
- 验证是否是有效数字
// 可能会出现+ - 号 [+-]? // 一位数字首位可能为0 ,多位数字首位不能为0 (\d|([1-9]\d+)) // 小数部分 (\.\d+)? let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/
- 验证密码
// 数字字母下划线 6~16位 let reg = /^\w{6,16}$/
- 验证真实姓名
// 汉字的正则表达式 /^[u4e00-u9FA5]$/ // 汉字长度2-10 // 可能存在有 名字·名字的类型(音译名) let reg = /^[u4e00-u9FA5]{2,10}(.[u4e00-u9FA5]{2,10}){0,2}$/
- 验证邮箱的正则表达式
let reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/
- 身份证号码的正则表达式
- ()分组捕获,并且可以单独获得每个分组的内容
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/ reg.exec('412723199412351241') // 得到的就是一个数组["412723199412351241", "412723", "1994", "12", "35", "4", "1", index: 0, input: "412723199412351241", groups: undefined]
正则的捕获(以及分组捕获)
- 实现正则捕获的前提是:当前正则要和字符串匹配,如果不匹配捕获的话那就返回null
- 基于exec()这个方法实现正则的捕获,返回的结果是一个null或者是一个数组
- 数组中的第一个内容就是捕获到的内容
- 如果有分组
()
的话,后几项就是分组捕获的内容 - 然后数索项,返回捕获的整体整容的索引
- 然后是我们操作的字符串
reg = /(\d)(\d)(\d)/ //分组捕获’ reg.exec('123') // 上面分组捕获得到的数组 ["123", "1", "2", "3", index: 0, input: "123", groups: undefined]
- 每执行一次exec()只能捕获到一个符合正则规则的,就是执行100遍也只捕获第一个,这就是正则捕获的
懒惰性
(解决办法用全局修饰符g)//懒惰性解释 var str = 'a12a21a' reg = /a/ reg.exec(str) // 如果我们需要捕获str中的所有a,那么我们使用exec进行捕获的时候,只能拿到第一次捕获的 // 正则有一个索引为lastIndex:当前正则下一次匹配的起始索引位置,而产生懒惰性的原 //因就是lastIndex永远不会自动改变,它默认一直都是0就是说他无论执行多少次,他都是 //从索引0开始捕获 // 但是如果我们给正则使用修饰符g的时候。可以改变lastIndex的值
- 使用exec进行分组捕获的时候,如果想要只匹配不捕获的时候,我们可以使用
(?:)
不捕获let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(?:\d|X)$/ // 这样的话最后一个分组的就只匹配不捕获了 reg.exec('412723199412351241') // 返回值的数组中没有最后一个分组的值
- 分组引用
let str = 'book' // look good food 类似于这种带有重复字母的字符串,我们使用分组引用进行匹配 let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/ // 在分组后面使用 \1可以让分组后面出现一个同分组一样的字符 类似于([a-zA-Z])/1
- 正则捕获的贪婪性
var str = '123@1233' reg = /\d+/g str.match(reg) // 获得的结果应该["123", "1233"] ,但是\d+应该拿到的是1到多个连续数字,但是他拿到的是正则匹配的最长结果 // 我们可以在量词后面设置?取消贪婪性, reg = /\d+?/g(按照正则匹配的最短结果来获取)
其他正则捕获的方法
- test也能捕获(本意是匹配)
let str = "{0}年{1}月{2}日" let reg = /\{\d+}\/g; console.log(reg.test(str)) // true console.log(RegExp.$1) // "0" 获取当前匹配的第一个分组
- replace 字符串中实现替换的方法(一般都是伴随正则一起使用的)
- 这个方法的解析:replace这个方法有两个参数,第一个参数是正则,第二个参数是回调函数,回调函数中返回什么那就把正则匹配的内容替换成什么,这个回调还有实参,就是大正则匹配的内容和小分组匹配的信息
let str = 'zhufeng@2019|zhufeng@2020' =>把字符串珠峰全部替换成汉字珠峰 str = str.replace("zhufeng","珠峰") // 这样执行一次只替换一次,如果使用两个repalce方式可以替换两次 //但是如果我们把zhufeng替换成zhufengpeixun这样就是不能使用上面那种方式替换,因为会出现zhufengpeixunpeixun这种情况,每一种替换都是从字符串的首字符开始,这就类似于正则的懒惰性 // 使用正则一次性替换所有zhunfeng str = str.replace(/zhufeng/g,"珠峰")
//案例 把字符串进行处理 let time = '2019-08-13' // 把上面字符串变为2019年08月13日 let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/ time = time.replace(reg,"$1年$2月$3日") // 得到"2019年08月13日" // 原理就是replace这个方法,传入一个正则,这个正则匹配一次有三个分组,然后我们可以使用$1,$2,$3拿到匹配到的第一二三个分组 // 上面的代码还可以写成下面这种方式 time = time.replace(reg,(big,$1,$2,$3)=>{ console.log(big,$1,$2,$3)// 打印匹配的大分组和三个小分组 return "@"// return什么就把匹配的内容替换成什么 })
- 案例:单词的首字母大写
let str = 'good googd study, day day up!' let reg = /\b([a-zA-Z])[a-zA-Z]*\b/g; str = str.replace(reg,(...arg)=>{ let [content,$1] = arg; $1=$1.toUpperCase() content= content.substring() return $1+content; })
- 案例:时间字符串的格式化