浏览器执行
浏览器分成两个部分:渲染引擎和JS引擎。
渲染引擎:用来解析html、css,俗称内核,比如chorme的blink,老版本的webkit
JS引擎:称为JS解析器,读取网页中的JS代码,对它处理后运行
JS是高级编程语言,浏览器读到scrip时,JS引擎将JS代码转为二进制机器语言。机器语言能识别就能执行这个代码。JS引擎执行代码时会逐行解释每一句源码,转为机器语言,然后交给计算机执行,所以JS归为脚本语言,会逐行解释执行。
编译型语言和解释型语言:
编程语言 -> 解释器翻译(编译器在代码执行前进行编译) -> 机器语言(二进制)
编程语言 -> 解释器翻译(解释器在运行时进行及时解释,立即执行) -> 机器语言(二进制)
JS组成
ECMAScript(JS语法) 、DOM(页面文档对象模型)、BOM(浏览器对象模型)【api】
ECMAScript规定了JS的编程语法和基础核心知识,是所有浏览器厂商共用遵守的一套JS语法工业标准。
JS书写
分为三种:行内、内嵌和外部。
行内:
<body>
<input type="button" value="唐伯虎" onlick="alert('唐伯虎')">
</body>
内嵌式:
<scrip>
alert('唐伯虎');
</scrip>
外部:
js文件:alert('唐伯虎');
引入:
<script src="my.js"></script>
注意:js推荐用单引号,html推荐用双引号
行内式写法:可读性差、引号容易出错,在引号多层嵌套匹配时,容易弄混、特殊情况下使用。
内嵌式:常用
外部:适用于js代码量比较大的情况,引用JS的scrip标签中间不可以写代码。
JS输入输出语句
方法一:alert():浏览器弹出警示框,归属浏览器
方法二:console.log():浏览器控制台打印输出信息,归属浏览器
这是程序员能看到的,按F12在console看到。
方法三:prompt():浏览器弹出输入框,用户可以输入,归属浏览器
prompt()取出来的是字符型。
JS变量
1.声明变量并赋值()
var 变量名1=变量值1,变量名2=变量值2;
比如:
<script>
var username=prompt('请输入用户名');
alert(username);
</script>
2.声明变量的特殊情况
(1)只声明变量,不赋值=> undefined未定义的
(2)不声明,不赋值,直接用=> 报错
(3)不声明,只赋值 => age=10;console.log(age) 输出10;
underfined和数字相加,显示NaN
JS数据类型
js变量数据类型只有程序在运行过程中,根据=右边的值来确定。JS是一种弱类型或动态语言。
数据类型分类:
简单数据类型:Number(数字型,包含整型和浮点型,默认0)、String(字符串类型,要带引号)、Boolean(布尔值类型,默认false)、Undefined(默认underfined)、Null(默认null)
复杂数据类型:object
8进制需要在数字前加个0
16进制需要在数字前加0x
Number.MAX_VALUE
Number.MIN_VALUE
Infinity:无穷大,大于任何值
-Inifinity:无穷小
NaN:代表一个非数字
isNaN():判断是否是数字,是:false;不是:true
string.length:获取字符串长度
stringa+stringb=拼接后的新串;拼接前将类型转为字符串再拼接。
引引加加:console.log('hello' '++age' 'world');
typeof 变量:得到变量是什么类型的。
数据类型转换
1.其他类型转为字符串:
toString()
String(变量) 【强转】
+拼接字符串
2.其他类型转为数字型
parseInt(string) : 将string转为整型
parseFloat(string): 将string转为浮点型
Number(): 将string类型转为数值型
js隐式转换(-*/) :比如console.log('12'-0);
3.其他类型转为布尔类型
Boolean():代表空、否定的值会被转为false,比如''、0、NaN、null、undefined
其余转为true
运算符
==:在判断时候会自动转类型,比如console.log('12'==12); => true
=== !== :全等,要求值和数据类型都一致 ;不全等
逻辑与:表达式1&&表达式2
如果表达式1为真,返回表达式2【逻辑或相同,也有短路】
表达式1为假,返回表达式1
流程控制有三种结构:顺序、分支、循环。
数组
数组就是一组数据的集合
1.通过new 的方式创建数组
var arr=new Array();
2.利用数字字面量创建数组(使用最多)
var arr=[];
可以通过修改arr.length来实现扩容。没有声明的变量默认值undefined
函数
声明方式一:
function getSum(num1,num2){
return num1+num2;
}
getSum(1,2);
声明方式二:(匿名函数)
var sum=function(num1,num2){
console.log(num1+num2);
};
sum(1,2);
注意:
如果实参的个数=形参的个数,正常输出结果
实参个数>形参个数,取形参个数
实参个数<形参个数,那剩下的形参就是undefined;1+undefined=NaN
如果函数没有return,返回undefined
如果无法确定多少个参数传递时,用arguments来获取,它实际上是当前函数的内置对象。arguments对象中存储了传递的所有实参。
作用域
全局作用域:整个script标签或一个单独的js文件。如果在函数内部没有声明直接赋值的变量也属于全局变量。
局部作用域:在函数内部;函数的形参也可以看成局部变量。
全局变量只有浏览器关闭的时候才会销毁,比较占用内存资源
局部变量,当我们程序执行完就会销毁。
ES6的时候新增了块级作用域{},if{} for{}
预解析
JS代码通过JS解析器执行,解释器运行JS代码时候,分为两步:预解析和代码执行。
1.JS解释器会把JS里面所有的var 、function提升到当前作用域的最前面。
2.代码执行,按照代码的书写顺序从上往下执行
预解析分为变量预解析(变量提升)和函数预解析(函数提升)
(1)变量提升,就是把所有变量声明提升到当前作用域的最前面,不提升赋值操作
(2)函数提升,就是把所有的函数声明提升到当前作用域最前面,不调用函数
对象
创建对象的三种方式:
1.用字面量创建对象
对象的字面量是{}
var obj={
username:'lkq',
age:18,
sex:'男',
sayHi:function(){
console.log('hi~');
}
};
调用属性:
obj.username;
obj['username'];
2.用new Object创建对象
var obj=new Object();
obj.username='lkq’;
obj.sayHi=function(){
console.log('Hi');
}
3.用构造函数创建对象
构造函数就是把对象一些公共的属性和方法抽取出来,封装到函数中去。
1.new构造函数在内存中创建一个空的对象
2.this指向刚才创建的空对象
3.执行构造函数里面代码,为这个空对象添加属性和方法
4.返回这个对象
function 构造函数名(属性){
this.属性=值;
this.方法=function(){}
}
new 构造函数名(属性);
function star(username,age,sex){
this.name=username;
this.age=age;
this.sex=sex;
}
var lkq=new star('lkq',18,'男');
遍历对象
for(var k in obj){
console.log(k);//属性名
console.log(obj[k]);//属性值
}
内置对象
js中对象分为三种,自定义对象、内置对象、浏览器对象。
内置对象就是js语言自带的一些对象,这些对象供开发者使用,提供一些常用基本必要的功能。
查阅文档:https://developer.mozilla.org/zh-CN/
Math
console.log(Math.PI);
console.log(Math.max(1,3,99));//如果里面有其他类型,无法转换,返回NaN
Math.abs():绝对值
Math.floor():向下取整(去掉小数)
Math.ceil():向上取整(取最接近最大的整数)
Math.round():四舍五入
Math.random():返回一个浮点数,范围在【0,1)
得到两数之间的随机整数
function getRandom(min,max){
min=Math.ceil(min);
max=Math.floor(max);
return Math.floor(Math.random()*(max-min))+min;
}
得到两数之间的随机整数,包括两个数
function getRandom(min,max){
min=Math.ceil(min);
max=Math.floor(max);
return Math.floor(Math.random()*(max-min+1))+min;
}
Date
var date=new Date();//没有参数,返回系统的当前时间
var date=new Date('2020-10-1 12:12:12');//常用
var date=new Date(2020,10,1);//会返回11月,比写的大一月
方法名 | 说明 | 代码 |
getFullYear() | 获取当年 | dateobj.getFullYear() |
getMonth() | 获取当月(0-11) | dateobj.getMonth() |
getDate() | 获取当天日期 | dateobj.getDate() |
getDay() | 获取星期几(周日0-周六6) | dateobj.getDay() |
getHours() | 获取当前小时 | dateobj.getHours() |
getMinutes() | 获取当前分钟 | dateobj.getMinutes() |
getSeconds() | 获取当前秒钟 | dateobj.getSeconds() |
date.valueOf():距离1970.1.1总的毫秒数
date.getTime():同上
简单写法:var date=+new Date();
Date.now():H5新增的总的毫秒数
倒计时:
思路:输入的时间(开卖的时间)-现在时间=剩余的时间,但是不能拿时分秒相减,比如05分-25分,就变成了负的了。
用时间戳来做,输入的总毫秒数-现在时间总毫秒数=剩余时间的毫秒数。
再把剩余时间转换成时分秒
var day=parseInt(总秒数/60/60/24) ;//得到天数
var hour=parseInt(总秒/60/60%24);//小时
var minites=parseInt(总秒/60%60);//分钟
var second=parseInt(总秒%60);//秒
function countDown(time){
var nowTime=+new Date();
var inputTime=new Date(time);
var times=(inputTime-nowTime)/1000;
var d=parseInt(总秒数/60/60/24) ;//得到天数
var h=parseInt(总秒/60/60%24);//小时
var m=parseInt(总秒/60%60);//分钟
var s=parseInt(总秒%60);//秒
return d+'天'+h+'时'+m+'分'+s+'秒';
}
数组对象
检测是否是数组:instanceof 和Arrays.isArray(arr)
例子:var arr[]; console.log(arr instanceof Array);
添加删除数组元素:
方法名 | 说明 | 返回值 |
push(参数1...) | 末尾添加一个或多个元素 | 返回新的长度 |
pop() | 删除数组最后一个元素,把数组长度-1,无参数、修改原数组 | 返回删除元素的值 |
unshift(参数1...) | 向数组的开头添加一个或更多元素,注意修改原数组 | 返回新的长度 |
shift() | 删除数组的第一个元素,数组长度-1,无参数、修改原数组 | 返回第一个元素的值 |
数组排序:
方法名 | 说明 | 是否修改原数组 |
reverse() | 颠倒数组中元素的顺序,无参数 | 该方法会改变原来的数组,返回新数组 |
replace('被替换字符','替换为的字母') | 只会替换第一个字符 | |
sort() | 对数组中的元素进行排序 | 该方法会改变原来的数组,返回新数组 |
arr.sort(function(a,b)){ //升序排列,逆序return b-a;
return a-b;
}
数组索引:
方法名 | 说明 | 返回值 |
indexOf() | 数组中给定元素的第一个索引 | 存在返回索引号,不存在返回-1 |
lastIndexOf() | 在数组中的最后一个索引 | 存在返回索引号,不存在返回-1 |
数组去重:
思路:遍历数组,拿着旧数组元素去新数组中查找,如果没有就添加,没有就不加。
利用indexOf()知道元素是否存在
function unique(arr){
var newArr=[];
for(var i=0;i<arr.length;i++){
if(newArr.indexOf(arr[i])==-1){
newArr.push(arr[i]);
}else
continue;
}
return newArr;
}
数组转为字符串
方法名 | 说明 | 返回值 |
toString() | 把数组转换成字符串,逗号分隔每一项 | 返回一个字符串 |
join('分隔符') | 把数组中所有元素转为一个字符串,用指定分隔符分隔 | 返回一个字符串 |
方法名 | 说明 | 返回值 |
concat() | 连接两个以上的数组,相当于+ | 返回一个新数组 |
slice() | 数组截取slice[begin,end) | 返回被截取的新数组 |
substr(star,leng) | 从start开始,len取个数 | |
substring(start,end) | 和slice()基本相同,但是不接受负值 | |
splice() | 数组删除splice(第几个开始,删除个数) | 返回被删除的新数组 |
字符串不可变:值不可变,虽然看上去内容可以改变,实际上地址变了。
查找字符串中某个字母出现的位置及次数
思路:先找第一个字母出现位置,然后只要indexOf()返回的不是-1,就继续往后查找。
找到以后,后面的查找利用找到的参数+1,继续找。
var str="aasafdsfdsfds";
var index=str.indexOf('o');
while(index!=-1){
console.log(index);
index=str.indexOf('o',index+1);
}
根据位置返回字符:
方法名 | 说明 | 使用 |
charAt(index) | 返回指定位置的字符 | str.charAt(0) |
charCodeAt(index) | 获取指定位置处的ascii码 | str.charCodeAt(0) |
str[index] | 获取指定位置处字符 |
判断字符串中出现次数最多的字符,并统计次数
var str="sfdsfdssdfdfgrsa";
var o={};
for(var i=0;i<str.length;i++){
var chars=str.charAt(i);
if(o[chars]){
o[chars]++;
}else{
o[chars]=1;
}
}
//遍历对象
var max=0;
var ch='';
for(var k in o){
if(o[k]>max){
max=o[k];
ch=k;
}
}
console.log(ch);
console.log(max);
数据类型
简单数据类型和复杂类型
简单数据类型叫做基本数据类型或者值类型 (null属于object),放到栈中,栈中存放的是值。
复杂类型叫引用类型(通过new 出来的,比如Array()、Object()、Date()等),放到堆中,地址存放栈中,地址指向堆
简单类型传参:
函数的形参可以看成一个变量,当我们把一个值类型变量作为参数传给函数的形参时,是把变量在栈空间的值复制了一份给形参,在方法内对形参做任何修改,都不会影响到外部变量。
复杂类型传参:
形参和实参其实保存的是一个堆地址,所以操作的同一个对象。
Web API
是浏览器提供的一套浏览器功能和页面元素的API(BOM和DOM)
DOM
是一个接口,处理可扩展标记语言(HTML或XML)。简单理解就是处理页面、处理文档的接口。
W3C定义了一系列的DOM接口,通过DOM接口可以改变网页的内容、结构和样式。
文档:一个页面就是一个文档,DOM里用document表示。
元素:页面中所有的标签,DOM用element表示
节点:网页中所有的内容(标签、属性、文本、注释等),DOM中用node表示
DOM把以上内容看成对象,DOM在实际开发中主要用来操作元素的。
如何获取页面中的元素?
1.根据元素ID获取
getElementById()方法获取带有ID的元素对象
【script标签要写在id的后面,因为页面文档从上往下加载,所以得先有标签】
<div id="time">2020-9-27</div>
<script>
var timer=document.getElementById(time);//返回的是一个DOM的element对象
console.dir(timer);//打印的是我们返回的元素的对象,能更好地查看里面的属性和方法
</scrip>
2.根据标签名获取
getElementsByTagName():返回带有指定标签名的对象的集合。
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
<ul id="nav">
<li>world</li>
<li>world</li>
<li>world</li>
</ul>
<script>
var list=document.getElementsByTagName('li');
console.log(list);//以伪数组方式存储,得到的是一个对象的集合。得到的元素对象是动态的。
var nav=document.getElementById('nav');
var navList=nav.getElementsByTagName('li');//得到某个元素里面的某个标签
console.log(navList);
</script>
3.通过HTML5新增的方法获取
1.document.getElementsByClassName('类名');//根据类名返回元素对象集合
2.document.querySelector('选择器');//根据选择器返回第一个元素的对象,比如 .box、#nav、li
3.document.querySelectorAll('选择器');//根据指定选择器返回所有元素
4.特殊元素获取
获取body元素:
var bodyEle=document.body;
获取html元素:
var htmlEle=document.documentElement;
事件基础
事件:被js检测到的行为,简单理解就是触发——响应的机制。
事件由三部分(三要素)组成:事件源(事件被触发的对象)、事件类型(怎么触发?鼠标点击-onclick?鼠标经过?键盘按下?)、事件处理程序(通过一个函数赋值的方式完成)。
<body>
<button id="btn">hello</button>
<script>
var btn=document.getElementById('btn');
btn.οnclick=function(){
alert('world');
}
</script>
</body>
常见的鼠标事件:
鼠标事件 | 触发条件 |
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
操作元素
利用DOM操作可以改变元素内容、属性等。
修改元素内容:
element.innerText(从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉)
element.innerHTML(从起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行)
<body>
<button>显示当前系统时间</button>
<div>某个时间</div>
<p>1122</p>
<script>
var btn=document.querySelector('button');
var div=document.querySelector('div');
btn.οnclick=function(){
div.innerText=getDate();
}
function getDate(){
var date=new Date();
var year=date.getFullYear();
var month=date.getMonth()+1;//月份从0开始
var dates=date.getDate();
var arr=['星期日‘,‘星期一’,‘星期二’,‘星期三’,‘星期四’,‘星期五’,‘星期六’];
var day=date.getDay();//周天是0,
return '今天是'+year+'年'+month+'月'+dates+'日'+arr[day];
}
//不添加事件的写法:
var p=document.querySelector('p');
p.innerText=getDate();
</script>
</body>
innerText和innerHTML的区别:
1.innerText不识别html标签,innerHTML识别,是W3C推荐
比如:
var div=document.querySelector('div');
div.innerHTML='<strong>今天是:</strong>2020';
2.innerText会去除空格和换行,innerHTML会保留
常用元素的属性操作:
1.src、href
2.id、alt、title
eg:实现点击刘德华按钮,显示刘德华图片,点击张学友按钮,切换到张学友图片
<body>
<button id="ldh">刘德华</button>
<button id="zxy">张学友</button>
<img src="images/ldh.jpg" alt="">
<script>
//1.获取元素
var ldh=document.getElementById('ldh');
var zxy=document.getElementById('zxy');
var img=document.querySelector('img');
//2.注册事件 处理程序
zxy.οnclick=function(){
img.src='images/zxy.jpg';
img.title="张学友";
}
ldh.οnclick=function(){
img.src='images/ldh.jpg';
img.title="刘德华";
}
</script>
</body>
案例:在不同的时间,显示不同的问候语
<body>
<img src="images/s.gif" alt="">
<div>上午好</div>
<script>
var img=document.querySelector('img');
var div=document.querySelector('div');
var date=new Date();
var h=date.getHours();//得到当前小时数
//判断
if(h<12){
img.src='images/s.gif';
div.innerHTML='上午好';
}else if(h<18){
img.src='images/x.gif';
div.innerHTML='下午好';
}else{
img.src='images/w.gif';
div.innerHTML='晚上好';
}
</script>
</body>
表单元素的属性操作
比如type、value、checked、selected、disabled
案例:点击按钮后,输入框内容改变
<body>
<button>按钮</button>
<input type="text" value="输入内容">
<script>
var btn=document.querySelector('button');
var input=document.querySelector('input');
btn.οnclick=function(){
// input.innerHTML这个是普通盒子里比如div标签里面的内容,采用innerHTML
//表单里的值是通过value来修改的
input.value='被点击了';
input.disabled=true;//想让这个按钮点击一次后,禁用。this.disabled=true效果同。this指的是事件函数的调用者=btn
}
</script>
</body>
案例:点击按钮将密码框切换为文本框,可以查看密码明文
(一个按钮两个状态,点击一次切换文本框,再点击一次切换密码框)
<style>
.box{
position:relative;
width:400px;
border:1px solid #ccc;
margin:100px auto;
}
.box input{
width:370px;
height:30px;
border:0;
outline:none;
}
.box img{
position:absolute;
top:2px;
right:2px;
width:24px;
}
</style>
<body>
<div class="box">
<label for="">
<img src="images/close.png" alt="" id="eye">
</label>
<input type="password" name="" id="pwd">
</div>
<script>
var eye=document.getElementById('eye');
var pwd=document.getElementById('pwd');
var flag=0;
eye.οnclick=function(){
if(flag==0){
pwd.type='text';
flag=1;
}else{
pwd.type='password';
flag=0;
}
}
</body>
样式属性操作:
通过JS修改元素的大小、颜色、位置等样式。
1.element.style; //行内样式操作,用这个方法修改,产生的是行内样式,权重比较高
2.element.className;//类名样式操作,修改样式较多可以用这个方法,className会直接更改元素类名,会覆盖原先类名
(如果想保留原先的类名,就用多类名选择器 this.className='first change';)
通过方法一:
<style>
div{
width:200px;
height:200px;
background-color:pink;
}
</style>
<body>
<div></div>
<script>
var div=document.querySelector('div');
div.click=function(){
this.style.backgroundColor='purple';//属性采取驼峰命名法
this.style.width='250px';
}
</script>
</body>
通过方法二:
<style>
.change{
background-color:purple;
....
}
</style>
<body>
<div>文本</div>
<script>
var test=document.querySelector('div');
test.οnclick=function(){
this.className='change';
}
</script>
</body>
案例:点击x,关闭图片(利用display的显示block和隐藏none)
<style>
省略.box 和.box img
.close-btn{
position:absolute;
top:-1px;
left:-16px;
width:14px;
height:14px;
border:1px solid #ccc;
line-height:14px;
cursor:pointer;
}
</style>
<body>
<div class="box">
淘宝二维码
<img src="images/tap.png" alt="">
<i class="close-btn">x</i>
<script>
var btn=document.querySelector('.colse-btn');
var box=document.querySelector('.box');
btn.οnclick=function(){
box.style.display=none;
}
</script>
</body>
案例:循环精灵图(利用for循环修改精灵图的背景位置)
<body>
<div>
<ul>
<li></li>
<li></li>
</ul>
</div>
<script>
var list=document.querySelectorAll('li');
for(var i=0;i<list.length;i++){
var index=i*44;
list[i].style.backgroundPosition='0 -'+index+'px';
}
</script>
</body>
案例:搜索栏点击,默认字没了,点别的地方默认字出现(获得焦点onfocus,失去焦点onblur)
如果失去焦点,且表单内容为空,就给它还原默认字。如果获得焦点,判断是否是默认字,是就清空内容。
<body>
<input type="text" value="手机"></input>
<script>
var text=document.querySelector('input');
text.οnfοcus=function(){
if(this.value=='手机')
this.value='';
this.style.color='#333';//获得焦点把文本框文字颜色变黑
}
text.οnblur=function(){
if(this.value=='')
this.value='手机';
this.style.color='#999';//失去焦点把文本框文字颜色变浅色
}
</scrip>
</body>
案例:密码框提示信息:密码较短,最短支持6个字符
首先判断的事件是表单失去焦点onblur,如果输入正确,就提示正确信息,小图标变为绿色。
如果输入不是6-16位,提示错误信息,小图标变红x。
.wrong{
color:red;
background-image:url(images/wrong.png);
}
<body>
<div class="register">
<input type="password" class="pwd">
<p class="message">请输入6-16位密码</p>
</div>
<script>
var pwd=document.querySelector('.pwd');
var message=document.querySelector('.message');
pwd.οnblur=function(){
if(pwd.value.length<6||pwd.value.length>16){
message.className='message wrong';
message.innerHTML='您输入的位数不对,要求6-16位';
}else{
message.className='message right';
message.innerHTML='输入的正确';
}
}
</script>
</body>
排他思想:
假设5个按钮,点了哪个按钮,这个按钮就变红色,再点别的按钮,这个按钮恢复颜色,点击的按钮变红色。
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<script>
var btns=document.getElementsByTagName('button');
for(var i=0;i<btns.length;i++){
btns[i].οnclick=function(){
//先把所有按钮颜色去掉,再将当前点击的这个按钮颜色置为红色
for(var j=0;j<btns.length;j++)
btns[i].style.backgroundColor='';
this.style.backgroundColor='red';
}
</scrip>
</body>
案例:为浏览器换皮肤
body{
background:url(images/1.png) no-repeat center top;
}
<body>
<ul class="browser">
<li><img src="images/1.jpg"></li>
<li><img src="images/2.jpg"></li>
<li><img src="images/3.jpg"></li>
</ul>
<script>
var imags=document.querySelector('.browser').querySelectorAll('img');
for(var i=0;i<images.length;i++){
images[i].οnclick=function(){
document.body.style.backgroundImage='url('+this.src+')';
}
</script>
</body>
案例:表格隔行变色,让鼠标经过某一行,那一行就变色。
(鼠标经过onmouseover,鼠标离开onmouseout)
思路:让鼠标经过tr行,当前的行变背景颜色,鼠标离开,去掉当前的背景颜色
thead里不需要变色,我们需要的是tbody的行变色
.bg{
background-color:blue;
}
<body>
<table>
<thead>...
<thead>
<tbody>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开房债券</td>
<td>1.075</td>
</tr>
</tbody>
</table>
<script>
var trs=document.querySelector('tbody').querySelectorAll('tr');
for(var i=0;i<trs.length;i++){
trs[i].οnmοuseοver=function(){
this.className='bg';
}
trs[i].οnmοuseοut=function(){
this.className='';
}
}
</script>
</body>
案例:表单的全选和取消
1.全选和取消全选:让下面所有的复选框的checked属性(选中状态)跟随全选按钮。
2.下面所有复选框选中后,全选按钮也选中,有一个没选择,全选不选中
<body>
<div class="wrap">
<table>
<thead>
<tr>
<th>
<input type="checkbox" id="j_cbAll">
</th>
<th>商品</th>
<th>价钱</th>
</tr>
</thead>
<tbody id="j_tb">
<tr>
<td>
<input type="checkbox">
</td>
<td>iphone8</td>
<td>8000</td>
</tr>
</tbody>
</table>
</div>
<script>
var j_cbAll=document.getElementById('j_cbAll');
var j_tbs=document.getElementById('j_jb').getElementByTagName('input');
j_cbAll.οnclick=function(){
for(var i=0;i<j_tbs.length;i++){
j_tbs[i].checked=this.checked;
}
}
for(var i=0;i<j_tbs.length;i++){
j_tbs[i].οnclick=function(){
var flag=true;//控制全选按钮是否选中
for(var j=0;j<j_tbs.length;j++){
if(!j_tbs[j].checked){
flag=false;
}
}
j_cbAll.checked=flag;
}
}
</script>
</body>
获取属性的值
1.element.属性【获取的是内置属性值(即元素本身自带的属性)】
2.element.getAttribute('属性');【主要获得自定义属性(程序员自己定义的属性)】
设置属性值
1.element.属性='值';【设置内置属性的值】
2.element.setAttribute('属性','值');【主要针对自定义属性】
案例:tab栏切换(★)
比如点了商品介绍,只能显示商品介绍模块内容,不能显示其他内容,隐藏掉.
上面的选项卡,点击了一个,当前这个底色红色,其余不变。
给所有小li添加自定义属性,属性值从0开始编号,让模块与选项卡一一对应。
current{
background-color:red;
}
.item{
display:none;
}
<body>
<div class="tab">
<div class="tab_list">
<ul>//上面长方形盒子
<li class="current>商品介绍</li>
<li>规格和包装</li>
<li>售后保障</li>
<li>商品评价</li>
</ul>
</div>
<div class="tab_con">
<div class="item" style="display:block">商品介绍模块内容</div>
<div class="item">规格与包装模块内容</div>
....
</div>
</div>
<script>
var lists=document.querySelector('.tab_list').querySelectorAll('li');
var items=document.querySelectorAll('.item');
for(var i=0;i<lists.length;i++){
lists[i].setAttribute('index',i);//设置编号
lists[i].οnclick=function(){
//上面的选项卡模块
for(var j=0;j<lists.length;j++)
lists[i].className='';
this.className='current';
//下面的显示内容模块
var index=this.getAttribute('index');
for(var k=0;j<items.length;i++)
items[k].style.display='none';
items[index].style.display='block';
}
</script>
</body>
H5新增自定义属性
自定义属性的目的:为了保存并使用数据,有些数据可以保存到页面中不必保存到数据库中。
1.设置自定义属性
H5规定自定义属性:date-开头作为属性名并赋值
比如:<div date-index="1">或element.setAttribute('date-index',1);
2.获取自定义属性
兼容性获取:element.getAttribute('date-属性名');
H5新增element.dataset.属性名或者element.dateset['属性名'] (ie11才支持)
【dateset是一个集合,里面存放了所有以date开头的自定义属性,注意驼峰命名】
<div date-list-name="andy">
div.dateset['listName'];
节点操作
目的:获取元素
1.利用DOM提供的方法获取元素
document.getElementById()
document.getElementByTagName()
document.querySelector()等
缺点:繁琐、逻辑性不强
2.利用节点层级关系获取元素
利用父子兄的关系获取元素。
优点:逻辑性强
缺点:兼容性稍差
【网页中所有内容都是节点,HTML DOM树中的所有节点都可以通过js进行访问,所有HTML节点都能被修改,创建或删除】
【一般情况下,节点至少有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)三个基本属性】
【元素节点的nodeType=1,属性节点的nodeType=2,文本节点的nodeType=3(包含文字、空格、换行)】
实际开发中,主要操作元素节点。
1.父级节点
node.parentNode(得到的是离元素最近的父级节点,找不到就返回null)
2.子节点
(1)parentNode.childNodes(标准)(它的所有子节点包括元素节点和文本节点——换行 空格等,可以通过nodeType判断是否是元素节点)
var ul=document.querySelector('ul');
for(var i=0;i<ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType==1)
console.log(ul.childNodes[i]);
}
缺点:如果想只获得元素节点,还需要专门处理,一般不用这个方法。
(2)parentNode.children(非标准)(获得所有子元素节点,常用)
(3)parentNode.firstChild(获得第一个子节点,不管是文本节点还是元素节点)
parentNode.lastChild(获得最后一个子节点)
(4)parentNode.firstElementChild(获得第一个子元素)
parentNode.lastElementChild(获得最后一个子元素),这两个方法有兼容性问题,ie9以上
解决方法:
用(2)var childs=ol.children;
childs[0],childs[childs.length-1]
案例:下拉菜单
鼠标经过li,ul显示,离开ul隐藏。
<body>
<ul class="nav">
<li>
<a href="#">微博</a>
//下拉部分
<ul>
<li> <a href="">私信</a> </li>
<li> <a href="">评论</a> </li>
<li> <a href="">@我</a> </li>
</ul>
</li>
</ul>
<script>
var nav=document.querySelector('.nav');
var lists=nav.children;//获取的是li
for(var i=0;i<lists.length;i++){
lists[i].οnmοuseοver=function(){
this.children[1].style.display='block';//选的li的第1个孩子(从0开始)是ul
}
lists[i].οnmοuseοut=function(){
this.children[1].style.display='none';
}
}
</script>
</body>
3.兄弟节点
(1)node.nextSibling(得到当前元素的下一个兄弟节点,包含文本节点)
node.previousSibling(得到上一个)
(2)node.nextElementSibling(得到当前元素的下一个兄弟元素节点)
node.previousElementSibling,这两个方法有兼容性问题,ie9以上支持
解决办法:封装一个兼容性函数
function getNextElementSibling(element){
var el=element;
while(el==el.nexSibling){
if(el.nodeType==1)
return el;
}
return null;
}
1.创建节点
document.createElement('tagName');//动态创建元素节点
2.添加节点
node.appendChild(child)(将一个节点添加到指定父节点的列表末尾)
node.insertBefore(child,指定元素) (将一个节点添加到父节点的指定子节点前面)
=》
想给页面添加一个新的元素:1.创建元素 2.添加元素
案例:发布评论
思路:点击发表以后,动态创建一个li,添加到ul里面。
创建li的同时,把文本域里面的值通过li.innerHTML赋值给li
<body>
<textarea name="" id="">123</textarea>
<button>发布</button>
<ul>
</ul>
<script>
var btn=document.querySelector('button');
var text=document.querySelector('textarea');
var ul=document.querySelector('ul');
btn.οnclick=function(){
if(text.value==''){
alert('请输入内容');
return false;
}else{
var li=document.createElement('li');
li.innerHTML=text.value;
ul.insertBefore(li,ul.children[0]);
}
</script>
</body>
3.删除节点
node.removeChild(child)【删除父节点的某个子节点,返回删除的节点】
4.复制节点
node.cloneNode()【返回调用该方法节点的一个副本】
注意:如果括号参数为空或false,就是浅拷贝,只克隆复制节点本身,不克隆里面的子节点。
node.cloneNode(true):就是深拷贝,复制标签里的内容
事件
1.注册事件(绑定事件)
给元素添加事件,称为注册事件或绑定事件;
注册事件有2种方式:传统方式和方法监听注册方式
传统注册事件:on开头的,onclick等;
特点:注册事件的唯一性。同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会覆盖前面的注册处理函数
方法监听注册方式
addEventListener(type,listener,useCapture),IE9前不支持
type:事件类型字符串,比如click
listener:事件处理函数,事件发生时,会调用这个监听函数
特点:同一元素同一事件可以注册多个监听器,按注册顺序依次执行
attachEvent(eventNNameWidthOn,callback);IE9前支持的
第一个参数:事件类型字符串,要带on
第二个参数:事件处理函数,当目标触发事件时回调函数被调用
2.删除事件(解绑事件)
1.传统
eventTarget.οnclick=null;
2.方法监听注册方式
eventTarget.removeEventListener(type,listener,useCapture)
eventTarget.detachEvent(eventNameWithOn,callback)
DOM事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程就是事件流。
DOM事件流分为3个阶段:
1.捕获阶段(从上往下,从大到小)
2.当前目标阶段
3.冒泡阶段(从小到大或从里到外)
事件冒泡:IE最早提出,事件开始时由具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程
注意:JS代码只能执行捕获或者冒泡其中的一个阶段
onclick和attachEvent只能得到冒泡阶段
addEventListener(type,listener,useCapture):第三个参数是true---在事件捕获阶段调用事件处理程序
false---在事件冒泡阶段调用事件处理程序
事件对象
var div=document.querySelector('div');
div.οnclick=function(event){
}
1.这里的event就是一个事件对象,写到我们监听函数小括号里,当形参来看
2.事件对象只有有了事件才会存在,它是系统自动创建的,不需要我们传递参数
3.事件对象是我们事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击里就包含了鼠标的相关信息,鼠标坐标;
4.这个事件对象我们可以自己命名
5.事件对象也有兼容性问题,ie6 7 8通过window.event
事件对象的 常见属性和方法
事件对象属性方法 | 说明 |
e.target | 返回触发事件的对象,标准 |
e.srcElement | 返回触发事件的对象,非标准,ie6-8用 |
e.type | 返回事件的类型,比如click |
e.cancleBubble | 阻止冒泡,非标准 |
e.returnValue | 阻止默认事件,非标准 |
e.preventDefault() | 阻止默认事件,标准 |
e.stopPropagation() | 阻止冒泡,标准 |
阻止事件冒泡
冒泡有一定坏处也有一定好处
比如:我点击子盒子,我只想让子盒子传播点击事件,不想让父盒子也传播到
标准写法:
利用事件对象里面的stopPropagation()方法
非标准:IE6-8
利用事件对象cancelBubble属性,让它=true
兼容性写法:
if(e&&e.stopPropagation){
e.stopPropagation();
}else{
window.event.cancelBubble=true;
}
事件委托
是事件冒泡的应用,是带来的好处
事件委托的原理:
不是给每个子节点单独设置事件监听器,而是给父节点设置事件监听器,然后利用事件冒泡影响设置每个子节点
事件委托的作用:
只操作一次dom,提高程序性能
常用鼠标事件
1.contextmenu禁用右键菜单
document.addEventListener('contextmenu',function(e){
})
2.selectstart禁用选中文字
document.addEventListener('selectstart',function(e){
})
鼠标事件对象MouseEvent
鼠标事件对象 | 说明 |
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标,ie9支持 |
e.pageY | 返回鼠标相对于文档页面的X坐标,ie9支持 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的X坐标 |
常用键盘事件
键盘事件 | 触发条件 |
onkeyup | 某个键盘被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时触发,但不识别功能键,比如ctrl shift 箭头等 |
BOM浏览器对象模型
BOM就是浏览器对象模型,提供独立于内容而与浏览器窗口进行交互的对象,核心对象是window
window对象的常见事件
window.onload,页面加载事件,当文档内容完全加载完成会触发该事件
或者window.addEventListener('load',function(){});
注意:有了这个事件,就可以把JS代码放到页面元素上面;window.onload是传统注册事件,只能写一次,若有多个以最后一个window.onload为准。addEventListener()没有限制
document.addEventListener('DOMContentLoaded',function(){}):当DOM加载完成时触发事件,不包括样式表、图片、flash等
IE9才支持,如果页面图片很多,从用户访问到onload需要很长时间,交互效果不能实现,影响用户体验。这时用DOMContentLoaded事件比较合适。
window.onresize调整窗口大小事件,只要浏览器窗口大小发生变化就会触发
或window.addEventListener('resize',function(){})
两种定时器
1.setTimeout()
语法:window.setTimeout(调用函数,延迟时间(单位ms))
注意:window可以省略,延迟时间省略默认0
停止计时器:window.clearTineout(timeoutId)
2.setInterval()——重复调用一个函数,每隔这个时间就调用一次回调函数
语法:window.setInterval(调用函数,间隔的毫秒数)
注意:每隔多少毫秒自动调用这个函数,且重复调用的是一个函数
停止计时器:window.clearInterval(interbalId)
JS执行机制
HTML5提出用Web Worker允许建立多个线程,于是JS出现了同步和异步
同步就是需要等待结果返回才能继续执行
异步是不需要等待结果返回就能继续执行
本质区别:各个流程的执行顺序不同
比如:
console.log(1);
setTimeout(function(){
console.log(3);
},0)
console.log(2);
最后执行顺序是1 2 3
JS为了防止任务有等待时间长的问题,将任务分为两类:同步任务和异步任务
同步任务都在主线程上执行,形成一个执行栈。【setTimeout是同步任务,但是参数fn是回调函数,属于异步任务】
异步任务是通过回调函数实现的。一般异步任务有三种类型:1.普通事件,click、resize等;2.资源加载,如load、error等 ;3.定时器,包括setTimeout和setInterval等
JS执行机制:
1.先执行栈中的同步任务
2.遇到异步任务(回调函数),就把它放到任务队列中
3.一旦栈中所有同步任务执行完成,系统就会按次序读取任务队列中的异步任务,所以被读取的异步任务结束等待状态,进入执行栈,开始执行。
注意:document.οnclick=function(){} ---如果不点击,是不会出现在任务队列中的
setTimeout(fn,2000)-----2秒到了,才会出现在任务队列中
事件循环机制:
同步任务会放到执行栈中执行,异步任务(普通事件click、资源加载load、定时器)会被放到任务队列中执行。JS会先执行 执行栈中的同步任务,遇到异步任务就把它放到任务队列中,栈中所有同步任务执行完成,就会依次读取任务队列中的异步任务,把它放到执行栈执行,执行完后还会去任务队列中看有没有异步任务,有就再放入执行栈执行,如此反复就叫做事件循环机制。
location对象
window对象提供location属性,用来获取或设置窗体的url,并且可以用于解析url。因为这个属性返回的是一个对象,所以这个属性也叫location对象
location对象的属性
location对象属性 | 返回值 |
location.href | 获取或设置整个URL |
location.host | 返回主机(域名)www.baidu.com |
location.port | 返回端口号,未写就返回空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段,#后面常见于链接锚点 |
案例:有个登录页面,有个提交表单,action提交到index.html页面。提交后跳转页面,并将参数加入url
第二个页面,可以用第一个页面的参数,实现一个数据不同页面之间的传递效果,利用location.search提取参数,
第二个页面只需要?后面的参数,用substr()从?截取到末尾,再利用split('=')分割key 、value。
var params=location.search.substr(1);
var arr=params.split('=');
var div=document.querySelector('div');
div.innerHTML=arr[1];
location对象的方法:
location对象方法 | 返回值 |
location.assign() | 跟href一样,可以跳转页面(也叫重定向页面) |
location.replace() | 替换当前页面,因为不记录历史,不能后退页面 |
location.reload() | 重新加载页面,相当于F5刷新,若参数true,就强制刷新 |
navigator对象
navigator对象包含有关浏览器的信息,有很多属性,常用userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。
history对象
与浏览器历史记录进行交互,该对象包含用户(在浏览器窗口中)访问过的url。
history对象方法 | 作用 |
back() | 可以后退 |
forward() | 前进功能 |
go(参数) | 参数1,前进一个页面,-1,后退一个页面 |