获取元素的方法
1. getElementById -> Dom对象
2. getElementsByTagName -> 类数组
3. getElementsByName -> 类数组
4. getElementsByClassName -> 类数组
offsetWidth = width(元素宽) + padding + border
offsetHeight = height + padding + border
clientWidth = width + padding
clientHeight = height + padding
offsetTop 距最近的已定位的祖先元素顶部的距离
offsetLeft 距最近已经定位的祖先元素的左边的距离
类数组如果没有获取到元素的话 返回[]
使用JS写CSS样式 都是字符串的形式
节点
节点类型
Node.ELEMENT_NODE 元素节点(1)
Node.ATTRIBUTE_NODE 属性节点(2)
Node.TEXT_NODE 文本节点(3)
Node.COMMENT.NODE 注释节点(8)
document.getElementsByTagName()函数获取到的为类数组
| 特征/方法 | 类型返回值 | 说明 |
|---|---|---|
| nodeName | String | 节点名字(大写标签名) 元素节点返回TagName 文本节点返回#text 属性节点返回属性名 |
| nodeValue | String | 节点的值:元素节点属性为null,文本节点属性为节点中的字符串,属性节点返回属性值 |
| firstChild | Node | 指向在childNodes列表中的第一个子节点 |
| lastChild | Node | 最后一个子节点 |
| nodeTyoe | Number | 节点的类型常量值之一 |
| nextSibling | Node | 指向后一个兄弟节点;如果这个节点就是最后一个兄弟节点,那么该值为null |
| previousSibling | Node | 指向前一个兄弟节点;如果这一节点就是第一个兄弟节点,那么该值为null |
| appendChild(node) | Node | 将node添加到childNodes的末尾 |
| removeChild(node) | Node | 从childNodes中删除node |
| replaceChild(newnode,oldnode) | Node | 将childNodes中的oldnode替换成newnode |
| insertBefore(newnode,refnode) | Node | 在childNodes中的refnode之前插入newnode |
nodeName:文本节点名称#text
空格回车算为文本节点
查找结点
nextSibling与nextElementSibling
//nextSibling 找到下一个节点 标准浏览器 会找到(回车 空格) IE浏览器下可以直接找到元素节点
//nextElementSibling 标准浏览器找到元素节点 IE不支持
//拿到元素的下一个节点,并判断节点类型是否为元素节点 如果不是继续查找下一个节点并返回
function next(elem) {
do{
elem = elem.nextSibling;
}while(elem && elem.nodeType != 1)
return elem;
}
firshChild
//查找第一个子节点
function first (elem) {
elem = elem.firstChild ;
if(elem.nodeType != 1){
elem = next(elem);//next()上 next()函数
}
}
nextElementSibling 标准浏览器找到元素节点 ie不支持
previousSibling 前一个节点 previousElementSibling
nodeValue 节点的值 元素节点的值为null
nodeType 返回节点类型值
children
<body>
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<script>
//节点
var oUl = document.getElementsByTagName('ul')[0];
console.log(oUl);
//children 查找所有子节点 返回的是类数组
console.log(oUl.children);
console.log(oUl.innerHTML);
var oH1 = document.createElement('h1');
oH1.innerHTML = 'hello world';
oUl.appendChild(oH1);
</script>
</body>
创建节点
creatElement 创建节点
//创建一个<p>节点
var oP = document.createElement('p');
document.creaetElement(); appendChild 插入到末尾
<body>
<div>
<h1></h1>
<h2></h2>
<a href="#"></a>
</div>
<script>
var oDiv = document.getElementsByTagName('div')[0];
//创建节点
var oP = document.createElement('p');
//将<p>插入到<div>中所有节点的 尾部
oDiv.appendChild(oP);
var oA = document.getElementsByTagName('a')[0];
//将<a>移除
oDiv.removeChild(oA);
var oH1 = document.getElementsByTagName('h1')[0];
var oSpan =document.createElement('span');
//在<div>中<h1>之前添加一个<span>标签
oDiv.insertBefore(oSpan,oH1);
//将<h2>替换为<span>
var oH2 = document.getElementsByTagName('h2')[0];
oDiv.replaceChild(oSpan,oH2);
</script>
</body>
removeChild 删除节点
insertBefore (new,old) 插入到old元素之前
replaceChild (new,old) 替换
创建文本节点,传参数即是文本内容
<body>
<script>
//创建一个元素节点,传入标签名
var p = document.createElement("p");
var txt = document.createTextNode("创建文本节点,传参数即是文本内容");
//将txt所引用的文本节点插入p到p的最后面(在这里p是空的)
p.appendChild(txt);
//直到现在,页面不会出现任何内容,必须将创建的节点插入到文档中
document.body.appendChild(p);//p将出现在最后
</script>
</body>
节点属性
1. setAttribute 设置属性
2. getAttribute 获取属性
3. removeAttribute 删除属性
<body>
<p>1111</p>
<script>
var oP = document.getElementsByTagName('p')[0];
//为<p>添加了一个 index属性 值为 1
oP.setAttribute('index',1);
//getAttribute()取出属性值
console.log(oP.getAttribute('index'));
//setAttribute()添加的属性可以在标签中展示
//对象.属性 赋值后 在标签中无法显示
oP.tag = 1;
console.log("tag = ",oP.tag);//tag = 1
//删除index属性
oP.removeAttribute('index');
</script>
</body>
函数下有一个原型 prototype
通过原型添加的属性和方法可以被实例化对象所共有
判断是数组还是对象
var arr = [];
var obj = {};
console.log(typeof arr);//object
console.log(typeof obj);//object
显然,typeof() 无法判断是否是数组与对象
1.obj.constructor =>Objct Array
var arr = new Array();
var obj = new Object();
console.log(arr.constructor);//Array
console.log(obj.constructor);//Object
2.arr instanceof Array 判断 arr 是否为Array 的 一个实例化对象
var arr = new Array();
var obj = new Object();
console.log(arr instanceof Array);//ture
console.log(obj instanceof Array);//false
事件委托->事件冒泡
动态添加的元素 无法在已进入页面绑定事件 需要把事件绑定在已存在的父元素上
this
-
函数中this是window
-
定时器this是window
-
对象this是当前对象
-
构造函数this是实例化对象
-
事件绑定this是绑定事件的Dom对象
var a = 1;
function f1(){
console.log(this);
}
f1();//window
setTimeout(function() {
console.log(this);
},1000)//window
var obj = {
name:'Bob',
code:function(){
console.log(this);
}
}
obj.code();//obj
function Person(_name) {
this.name = _name;
this.code = function(){
console.log(this);
}
}
var person = new Person();
person.code();//Person
<body>
<div>123</div>
<script>
oDiv = document.getElementsByTagName('div')[0];
oDiv.onclick = function(){
setTimeout(function(){
console.log(this)//Window
},1000)
console.log(this);//<div>
}
</script>
</body>
call()方法 改变指针 第一个参数 要改变指针的对象 后面的参数 是方法需要的参数
apply()方法 改变指针 第一个参数 要改变指针的对象 call与apply 传入参数方式不一样 , []
apply 两个参数 对象,数组
call()和apply 会自动调用方法 bind需要手动调用
call与apply的区别: 改变this指针并且自动调用方法 bind只改变了this指针
call 与bind的区别:call自动调用 bind手动调用 其他相同
<body>
<div>123</div>
<script>
oDiv = document.getElementsByTagName('div')[0];
function f1(x,y){
console.log(this,x,y);
}
var obj = {
name :'Bob',
age :'18'
}
f1.call(oDiv,2,3);//<div> 2 3
f1.apply(obj,[2,3]);//Object 2 3
f1.bind(oDiv,3,4)();//<div> 3 4
</script>
</body>
闭包
闭包
- 外部函数里面有一个内部函数(函数套函数)
- 内部函数会使用外部函数里的局部变量
function fun1() {
var a = 1;
return function() {
console.log(a)
}
}
var aa = fun1();
console.log(aa);
aa();
优点:
- 闭包里的变量 不会被垃圾回收机制清理 一直在内存里
- 可以拿到索引值
缺点: 造成内存泄漏
函数的立即调用
例一
var name = "The window";
var object = {
name :"My Object",
getNameFunc :function(){
return function(){ //->window
return this.name;
}
}
}
alert(object.getNameFunc()());//The window
var name = "The window";//window.name
var object = {
name :"My Object",
getNameFunc :function(){
//this->object
var that = this;
return function(){
return that.name;
}
}
}
alert(object.getNameFunc()());// My Object
例二
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
var oLi = document.querySelectorAll('li');
for(var i = 0;i< oLi.length;i++){
(function(index){
oLi[index].onclick = function(){
console.log(index)
}
})(i)
}
类
类(构造方法or构造函数):表示具有相同的属性方法的集合 类名的首字母要大写
声明类的时候 属性写在构造函数中 方法写在原型(prototype)中
原型中的方法被实例化对象所共用
function Person(_name,_age,_weight) {
this.name = _name,
this.age = _age,
this.weight = _weight,
this.code = function(){
console.log('hello')
}
}
//实例化一个对象
var people1 = new Person('John',19,'60kg');
console.log(people1.name);//John
console.log(people1.age);//19
console.log(people1.weight);//60kg
people.code();//hello
//没有传入参数为undefined
var people2 = new Person('Bob',20)
console.log(people2);//weight: undefined
原型:函数下有一个原型 prototype
通过原型添加的属性和方法可以被实例化对象所共享
prototype 下有一个constructor 代表的是构造函数
通过原型添加的属性
function Person(_name,_age,_weight) {
this.name = _name,
this.age = _age,
this.weight = _weight,
this.code = function(){
console.log('hello')
}
}
Person.prototype.height = '175';
事件
事件冒泡与事件捕获
**点击事件
oDiv.onclick = function(event) {
//this
evetn = window.event ||event//兼容IE浏览器的方式
//event.clientX
//event.clientY
event.preventDefault();//阻止默认事件
e.targe//事件源 触发当前事件的源头
return false //组织默认事件
}
事件冒泡:从里向外(触发了子元素的事件后 就会冒泡到父元素的事件)
事件捕获:从外向里
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#div1{
width:200px;
height:200px;
background:red;
}
#div2{
width:100px;
height:100px;
background:blue;
}
</style>
</head>
<body>
<div id="div1">
<div id="div2"></div>
</div>
<script>
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
oDiv1.onclick = function() {
console.log('div1')
}
//事件冒泡 从里向外传播
oDiv2.onclick = function() {
console.log('div2');
}
</script>
</body>
给予同一元素相同事件时,执行后一个事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#div1{
width:200px;
height:200px;
background:red;
}
</style>
</head>
<body>
<div id="div1" > </div>
<script>
var oDiv1 = document.getElementById('div1');
oDiv1.onclick = function() {
console.log('hello')
}
oDiv1.onclick = function() {
console.log('world');
}
//显示world
</script>
</body>
</html>
addEventListener(事件,方法,布尔值):添加事件监听 可以给元素绑定多个相同事件
false 事件冒泡
<style>
#div1{
width:200px;
height:200px;
background:red;
}
#div2{
width:100px;
height:100px;
background:blue;
}
</style>
</head>
<body>
<div id="div1">
<div id="div2"></div>
</div>
<script>
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
oDiv1.addEventListener('click',function(){
console.log('div1')
},false)
oDiv2.addEventListener('click',function(){
console.log('div2')
},false)
</script>
</body>
</html>
ture 事件捕获
oDiv1.addEventListener('click',function(){
console.log('div1')
},true)
oDiv2.addEventListener('click',function(){
console.log('div2')
},true)
即有冒泡又有捕获, 先捕获后冒泡
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
oDiv1.addEventListener('click',function(){
console.log('捕获:','div1')
},true)
oDiv2.addEventListener('click',function(){
console.log('捕获:','div2')
},true)
oDiv1.addEventListener('click',function(){
console.log('冒泡:',''div1')
},false)
oDiv2.addEventListener('click',function(){
console.log('冒泡:',''div2')
},false)//捕获: div1 捕获: div2 冒泡: div2 冒泡: div1
阻止事件冒泡
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
oDiv1.onclick = function(e) {
console.log('div1');
}
oDiv2.onclick = function(e) {
//阻止事件冒泡
e.stopPropagation();
console.log('div2')
}
事件委托
动态添加的元素,无法在一进入页面时绑定事件,需要把事件绑定在已存在的父元素上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
li{
background:red;
}
ul{
background:#000;
}
</style>
</head>
<body>
<button>添加</button>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var aLi = document.getElementsByTagName('li');
var oUl = document.getElementsByTagName('ul')[0];
var oBtn = document.getElementsByTagName('button')[0];
oBtn.onclick = function() {
var oLi = document.createElement('li')
oLi.innerHTML = Math.random();
//给ul下的li追加元素li
oUl.appendChild(oLi);
}
oUl.onclick = function(e){
//判断点击的事件源是否为li
if(e.target.tagName == 'LI'){
//输出li内容
console.log(e.target.innerHTML)
}
}
</script>
</body>
</html>