一、Javascript的认识
1.1 Javascript的介绍
(1)Javascript的概念
- Javascript语言诞生主要是完成页面的数据校验,因此它运行在客户端,语言运行浏览器来解析执行Javascript代码,JS是Netscape网景公司的产品,最早取名为LiveScript;为了吸引更多的Java程序员,更名为Javascript,JS是弱类型的语言,Java是强类型的语言;
特点:
第一种方式
- 只需在html文件中的head标签或者在body标签中,使用script标签来书写Javascript代码即可
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>javascript的第一个程序</title> <script type="text/javascript"> // alert(helloworld); alert("hello javascript"); </script> </head> <body> javascript的第一个程序 </body> </html>
- 只需在html文件中的head标签或者在body标签中,使用script标签来书写Javascript代码即可
第二种方式:
在外部单独编写一个后缀名为“js”的文件,使用script标签引入
//后缀名为js的文件 alert("hello import");
<!DOCTYPE html> <html lang="en"> <head> </head> <body> javascript的第一个程序 <script type="text/javascript" src="inport.js"></script> </body> </html>
1.2 Javascript的语法
(1)输入输出语句的实现
- 输入框prompt(“”提示内容);
- 弹出警告框alert(“提示内容”);、
- 控制台输出console.log(”显示内容”);
-
(2)变量的分类与声明
变量的分类 | 变量类型 | 说明 | 举例 | | —- | —- | —- | | number | 数值类型 | 比如int、short、double等 | | string | 字符串类型 | 和Java的相同 | | object | 对象类型 | 类似于Java中的对象 | | boolean | 布尔类型 | 与Java相同 | | function | 函数类型 | 类似于Java中的方法 | | bigint | 大整数类型 | 例如:var num = 10m; |
JS变量的特殊取值
- undefined:未定义,所有js变量未赋值的初始取值;
- null:空值
- NAN:全称是Not a Number,非数值,非数字;
- JS变量的定义格式
- var 变量名;或者是 let 变量名;
- var 变量名=值; 或者是 let 变量名 = 值; ```javascript //alert(“hello import”); //变量的定义 var i ; alert(i);//弹窗结果为undefined i = 10; alert(i); //弹窗结果为10 alert(typeof(i)); //弹窗结果为number //给i重新赋值 i=”HausenLee”; alert(typeof(i));//弹窗结果为string
//1.定义局部变量
let name = “张三”;
let age = 23;
document.write(name + “,” + age +”
“);
- 全局变量的定义 变量名 = 值;
```javascript
//2.定义全局变量
{
let l1 = "aa";
l2 = "bb";
}
//document.write(l1);
document.write(l2 + "<br>");
- 常量的定义 const 常量名 = 值;
//3.定义常量 const PI = 3.1415926; //PI = 3.15; document.write(PI);
(2)Javascript的运算符
、<、>=、<=和Java中相同
不同的点
- == :比较的是两个数字直接的大小是否相等
- ===:既比较两个数字的大小是否相等,还比较两个变量的类型是否一致
var j = "20"; var k = "20"; var l =20; alert(j==k);//弹窗结果为true alert(k==l);//弹窗结果为true
逻辑运算:
- 前提:在Javascript语言中,所有的变量都可以作为一个boolean类型的变量使用,其中null、undefined、””(空字符串)都认为false
- &&与(且)运算的两种情况
- 第一种情况:当表达式全为真值时,返回最后一个表达式的值
- 第二种情况:当表达式中,有一个为假值时,返回第一个为假的表达式的值
- 代码举例: ```javascript var a = “abc”; var b = true; var c = false; var d = null; //与运算第一种情况:当表达式全为真时:返回最后一个表达式的值 alert(a&&b);//弹窗结果为b的值:true alert(b&&a);//弹窗结果为a的值:abc //与运算第二种情况:当表达式全为假时:返回第一个表达式的值 alert(c&&d);//弹窗结果为c的值:false alert(d&&c);//弹窗结果为d的值:null //与运算第三种情况:有一个表达式为假时,返回第一个为假的表达式的值 alert(b&&c&&d);//弹窗结果为c的值:false
//或运算第一种情况:当表达式全为真值时,返回第一个表达式的值 alert(a||b);//弹窗结果为a的值:abc alert(b||a);//弹窗结果为b的值:true //或运算第二种情况:当表达式全为假时,返回最后一个表达式的值 alert(d||c);//弹窗结果为c的值:false alert(c||d);//弹窗结果为d的值:null //或运算第三种情况:有一个表达式为真时,就会把第一个为真的表达式的值返回 alert(c||b||a);//弹窗结果为b的值:true alert(a||b||d);//弹窗结果为a的值:abc
- 三元运算符
- 格式:(比较表达式)?表达式1:表达式2;
- 执行流程
- 如果表达式为true,则取表达式1
- 如果表达式为false,则取表达式2-
<a name="p3RCk"></a>
### (3)流程控制与循环语句
- if语句
```javascript
//if语句
let month = 3;
if(month >= 3 && month <= 5) {
document.write("春季");
}else if(month >= 6 && month <= 8) {
document.write("夏季");
}else if(month >= 9 && month <= 11) {
document.write("秋季");
}else if(month == 12 || month == 1 || month == 2) {
document.write("冬季");
}else {
document.write("月份有误");
}
document.write("<br>");
- switch语句
```javascript
//switch语句
switch(month){
case 3:
case 4:
case 5:
case 6: case 7: case 8:document.write("春季"); break;
case 9: case 10: case 11:document.write("夏季"); break;
case 12: case 1: case 2:document.write("秋季"); break;
default:document.write("冬季"); break;
}document.write("月份有误"); break;
document.write(“
“);for 循环
- for循环
```javascript
//for循环
for(let i = 1; i <= 5; i++) {
document.write(i + "<br>");
}
- while循环
//while循环 let n = 6; while(n <= 10) { document.write(n + "<br>"); n++; }
(4)Javascript数组的定义与使用
- 数组的定义格式
- 在Javascript中即使是一个空数组,也可以通过下角标进行赋值,并且通过下角标获取值,它会实现自动扩容操作,还可以同时存入不同类型的元素 ```javascript var arr = []; arr[0] = 1; alert(“数组长度为:”+arr.length);//弹窗结果为1 alert(“第一个元素为:”+arr[0]); arr[1] = “HausenLee”; alert(“第二个元素为:”+arr[1]); arr[3] = 10; alert(“会出错吗?”+arr[3]); alert(“数组长度为:”+arr.length); //如果不是根据顺序(下角标)进行赋值,那么赋了值的元素之前的元素全是undefined,数组长度就i是这个元素下角标加一
//遍历数组 for(var i = 0; i<arr.length; i++){ alert(arr[i]); }
<a name="A4gRw"></a>
### (5)Javascript函数的定义方式
- 方式一:
- function 函数名(形参列表){函数体 }
```javascript
//函数的定义(无参函数)
function method (){
alert("method函数执行了");
}
//调用函数才执行函数中的逻辑
method();
//定义有返回值的函数
function sum (a,b){
return a+b;
}
//调用函数
var s = sum(5,5);
alert("和为:"+s);
方式二:
- var 变量名 = function (形参列表){函数体 }
//定义函数的第二种方式 var fun = function method(){ alert("第二种方式定义函数"); } //调用函数 fun() //定义有形参有返回值的函数 var fun01 = function (a,b){ return a+b; } //调用函数 alert("调用函数"+fun01(1,2));
- var 变量名 = function (形参列表){函数体 }
注意:JS不允许函数被重载,否则直接覆盖上面定义好的函数
函数的arguments隐形参数(只在function函数内)
- 就是在function函数种不需要定义形参,但却可以直接用来获取所有参数的变量,我们管家叫隐形参数,隐形参数特别像Java种的可变参数,public void fun(Object … args);那么在JS中的隐形参数也跟Java的可变参数一样,操作类似于数组;
function fun (){ var result = 0; // alert(arguments.length); for(var i = 0; i<arguments.length; i++){ result +=arguments[i]; } return result; } var sum = fun(1,2,3,4,5,6,7,8,9,10); alert(sum);
(6)object类型的变量
- 就是在function函数种不需要定义形参,但却可以直接用来获取所有参数的变量,我们管家叫隐形参数,隐形参数特别像Java种的可变参数,public void fun(Object … args);那么在JS中的隐形参数也跟Java的可变参数一样,操作类似于数组;
object类型变量的定义格式(方式一)
- 对象的定义:var 变量名 = new Object(); //对象实例(空对象);变量名.属性名 = 值; //定义一个属性;变量名.函数名 = function(){}; //定义一个函数
- 对象的访问:变量名.属性/函数名;
var object = new Object(); object.name = "HausenLee"; object.age = 23; object.explain = function(){ alert("explain:我是一个学生") } alert(object.name); alert(object.age); object.explain();
object类型变量的定义格式(方式二——属性和方法都是静态的)
- 对象的定义:var 变量名 = {//空对象 属性名1:值1,属性名2:值2,函数名:function(){} };
var object = { name:"HausenLee", age:23, explain:function(){ alert("explain:我是"+this.name+"今年"+this.age+"岁了") } } //访问/调用对象的函数 object.explain();
- 对象的定义:var 变量名 = {//空对象 属性名1:值1,属性名2:值2,函数名:function(){} };
object类型变量的定义(三): ```javascript //其实跟Java中的构造方法一样 //构造函数的声明定义 function 构造方法(形参列表){ this.属性名 = 值; this.方法名 = function(){} }
new 构造函数名(形参列表);
- 遍历对象中的属性:
```javascript
//格式
//for (var 变量名 in 对象名){}
for(var k in obj){
console.log(k);//k 变量输出的是属性名
console.log(obj[k]);//输出的是属性值;
}
(7)预解析
- js引擎运行js分为两步:预解析和代码执行
- 预解析:js引擎将js里面的var(变量提升)还有function(函数提升)提升到当前作用域最前面,不做赋值操作
- 代码执行:就是从上到下执行代码
(8)MDN 官网
1.4 Javascript DOM
(1)DOM介绍
- DOM(Document Object Model):文档对象模型
将HTML文档的各个组成部分,封装成对象,借助这些对象,可以对HTML文档进行增删改查的动态操作
(2)Elemen元素的获取操作
具体的方法
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>元素的获取</title> </head> <body> <div id="div1">div1</div> <div id="div2">div2</div> <div class="cls">div3</div> <div class="cls">div4</div> <input type="text" name="username"/> </body> <script type="text/javascript"> //1. getElementById() 根据id属性值获取元素对象 let div1 = document.getElementById("div1"); //alert(div1); //2. getElementsByTagName() 根据元素名称获取元素对象们,返回数组 let divs = document.getElementsByTagName("div"); //alert(divs.length); //3. getElementsByClassName() 根据class属性值获取元素对象们,返回数组 let cls = document.getElementsByClassName("cls"); //alert(cls.length); //4. getElementsByName() 根据name属性值获取元素对象们,返回数组 let username = document.getElementsByName("username"); //alert(username.length); //5. 子元素对象.parentElement属性 获取当前元素的父元素 let body = div1.parentElement; alert(body); //6. querySelector 返回指定的选择器的第一个元素对象 var firstBox = document.querySelector('.box'); console.log(firstBox); //7. querySelectorAll 返回指定选择器的所有元素对象的集合 var allBox = document.querySelectorAll('.box'); console.log(allBox); //parentNode 获取子元素(节点)的父元素(节点):得到的是离子元素最近的父节点,找不到则返回null var body = div1.parentNode; //childNodes 获取所有的子节点(包括了元素节点,文本节点等等)一般不用 body.childNodes //children ,一般用这个属性 </script> </html>
(3)Element元素的正删改操作
具体的方法
代码实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>元素的增删改</title> </head> <body> <select id="s"> <option>---请选择---</option> <option>北京</option> <option>上海</option> <option>广州</option> </select> </body> <script> //1. createElement() 创建新的元素 let option = document.createElement("option"); //为option添加文本内容 option.innerText = "深圳"; //2. appendChild() 将子元素添加到父元素中 let select = document.getElementById("s"); select.appendChild(option); //3. removeChild() 通过父元素删除子元素 //select.removeChild(option); //4. replaceChild() 用新元素替换老元素 let option2 = document.createElement("option"); option2.innerText = "杭州"; select.replaceChild(option2,option); </script> </html>
(4)Attribute属性的操作
具体的方法
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>属性的操作</title> <style> .aColor{ color: blue; } </style> </head> <body> <a>点我呀</a> </body> <script> //1. setAttribute() 添加属性 let a = document.getElementsByTagName("a")[0]; a.setAttribute("href","https://www.baidu.com"); //2. getAttribute() 获取属性 let value = a.getAttribute("href"); //alert(value); //3. removeAttribute() 删除属性 //a.removeAttribute("href"); //4. style属性 添加样式 //a.style.color = "red"; //5. className属性 添加指定样式 元素对象名.className = "样式选择器名" 原理是更矮类名匹配类选择器 .aColor{ color: blue; } a.className = "aColor"; // 元素对象.cloneNode(false/true) </script> </html>
(5)Text文本的操作
具体的方法
代码演示 ```javascript <!DOCTYPE html>
<a name="qHKe7"></a> ## 1.3 Javascript中的事件 <a name="jgrp2"></a> ### (1)事件的概念 - 什么是事件?事件是电脑输入设备与页面进行交互的响应,我们称之为事件 - 常用的事件 | 事件名 | 说明 | 备注 | | --- | --- | --- | | onload | 加载完成事件 | 页面加载/解析完成之后,常用于做页面Javascript代码初始化操作 | | onclick | 单击事件 | 常用于按钮的点击响应操作 | | onblur | 失去焦点事件 | 常用于输入框失去鼠标/焦点后验证其输入的内容是否合法 | | onchange | 内容发生改变事件 | 常用于下拉列表和输入框内容发生改变后操作 | | onsubmit | 表单提交事件 | 常用于表单提交时,验证所有表单项是否合法 | - 了解的事件 ![](https://cdn.nlark.com/yuque/0/2021/png/12492094/1622555083519-38313315-7f54-4908-b906-e070bce31dc5.png#id=xkwkS&originHeight=312&originWidth=640&originalType=binary&ratio=1&status=done&style=none) - 事件的注册(绑定):当事件响应时,执行所想要执行的代码逻辑 - 事件注册(绑定)的分类 - 静态注册(绑定)事件:通过html标签的事件属性直接赋予事件响应后的代码,这种方式我们叫静态注册(绑定) - 动态注册(绑定)事件:是指先通过Javascript代码得到标签的dom对象,然后再通过 dom对象.事件名 = function(){}这种方式赋予事件响应后的代码,叫动态注册(绑定);动态绑定的基本步骤: - 获取标签对象; - 标签对象.事件名 = function(){} <a name="eGI5a"></a> ### (2)onload事件 - 静态注册(绑定)演示 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onload event</title> <script type="text/javascript"> function onload(){ alert("静态注册onload事件"); } </script> </head> <body onload="onload()"></body> </html>
动态注册(绑定)演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onload event</title> <script type="text/javascript"> //动态注册,是固定的写法 window.onload = function(){ alert("动态注册onload事件"); } </script> </head> <body> </body> </html>
(3)onclick事件
静态注册(绑定)演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onclick</title> <script type="text/javascript"> function onclickfun(){ alert("静态注册onclick演示"); } </script> </head> <body> <button onclick="onclickfun()">按钮1</button> <button>按钮2</button> </body> </html>
动态注册(绑定)演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onclick</title> <script type="text/javascript"> //动态注册(绑定) window.onload = function(){ //1.获取标签对象 //document是Javascript语言提供的一个对象(文档) //getElementById 通过标签的id属性获取标签对象 var element = document.getElementById("but"); //2.通过标签对象.事件名 = function(){}绑定事件 element.onclick = function(){ alert("动态注册onclick演示"); //删除事件 element.onclick = null; } } </script> </head> <body> <button onclick="onclickfun()">按钮1</button> <button id="but">按钮2</button> </body> </html>
(4)onsubmit事件
静态注册(绑定)演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onsubmit</title> <script type="text/javascript"> function onsubmitFun(){ alert("静态注册表单提交事件----发现有表单不合法"); return false; } </script> </head> <body> <form action="#" method="get" autocomplete="off" onsubmit="return onsubmitFun();"> <button type="submit">静态注入</button> </form> </body> </html>
(6)事件监听方式addEventListener
- 语法:eventTarget.addEventListener(type,listener,[useCapture]);该方法将指定的监听器注册到目标对象上,当该对象触发了指定的事件时,就会执行事件处理函数; 其中type指的是事件类型字符串,比如click、mouseover等等、listener指的是,回调事件执行函数、useCapture指的是事件处理的方式(true是捕获阶段,false是冒泡阶段也是默认值,也用多比较多)
- 特点,同一个元素可以注册多个监听器
(7)事件对象event
- event是一个对象, 写在事件处理函数的形参中;事件对象只有绑定了事件才会存在,它是系统自动创建的;事件对象是由某个事件的一系列相关数据的集合,比如mouseover相关的事件包含了鼠标坐标等等;这个事件可以自己命名;它有兼容性的问题,在ie678需要通过window.event获取事件对象
- 常用的事件对象的属性和方法: | 属性and方法 | 说明 | | —- | —- | | e.target | 返回触发事件的对象(标准) | | e.srcElement | 返回触发事件的对象(非标准ie678使用) | | e.type | 返回事件类型 | | e.cancelBubble | 阻止冒泡(非标准ie678使用) | | e.returnValue | 阻止默认事件(默认行为、非标准ie678使用)比如不让超链接跳转事件等等 | | a.preventDefault() | 阻止默认事件(默认行为、标准)比如不让超链接跳转事件等等 | | e.stopPropagation() | 阻止冒泡(标准) |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>onclick</title> <script type="text/javascript"> //动态注册(绑定) window.onload = function(){ //1.获取标签对象 //document是Javascript语言提供的一个对象(文档) //getElementById 通过标签的id属性获取标签对象 var element = document.getElementById("but"); element.addEventListener('click',fn); function fn (event){ alert("事件监听注册事件") element.removeEventListener('click',fn) } } </script> </head> <body> <button onclick="onclickfun()">按钮1</button> <button id="but">按钮2</button> </body> </html>
(8)事件委托(委派)
- 在父节点上添加事件监听器,利用冒泡传播原理影响每个子节点,提高性能
1.5 javascript综合案例
(1)案例效果介绍
- 在姓名、年龄、性别三个文本框中填写信息后,添加到学生信息表中
(2)添加功能说明
- 为添加按钮绑定单击事件。
- 创建 tr 元素。
- 创建 4 个 td 元素。
- 将 td 添加到 tr 中。
- 获取文本框输入的信息。
- 创建 3 个文本元素。
- 将文本元素添加到对应的 td 中。
- 创建 a 元素。
- 将 a 元素添加到对应的 td 中。
将 tr 添加到 table 中。
添加功能实现 ```java <!DOCTYPE html>
学生信息表 姓名 年龄 性别 操作 张三 23 男 删除 李四 24 男 删除 (3)删除功能的说明
- 删除功能的介绍
- 为每个删除超链接添加单击事件属性。
- 定义删除的方法。
- 获取 table 元素。
- 获取 tr 元素。
- 通过 table 删除 tr。
- 浏览器对象模型,对象是window
常用的事件: | 事件名称 | 说明 | | —- | —- | | load | 页面加载完毕执行 | | resize | 浏览器窗口发生变化时触发的事件 |
window常用的方法跟属性以及对象 | 方法and属性and对象 | 说明 | | —- | —- | | innerwidth/innerheight | 获取浏览器窗口的宽度跟高度 | | setTimeout(回调函数,倒计时间毫秒值) | 达到时间执行参数中的回调函数 | | clearTimeout(倒计时方法标识符) | 清除时间定时 | | setInterval(回调函数,倒计时间毫秒值) | 到达时间反复执行回调函数 | | location对象 | 属性and方法:
location.href:获取or设置整个url
location.host:返回主机名(域名)
location.port:返回端口好,没有则为空字符
location.pathname:返回路径
location.search:返回参数
location.hash:返回片段(#后面的内容常见于链接、锚点等)
location.assign(‘url’):重定向页面
location.replace(‘url’):替换当前页面
location.reload(Boolean):刷新页面,如果形参为true则为强制刷新 | | navigator对象 | navigator.userAgent.match():返回用户所使用的浏览器是pc端的还是手机端的 | | history对象 | back():后退
forward():前进
go(退进次数不加双引号):根据参数进退 |判断用户使用的浏览器跳转至相关用户端的页面
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|WOSBrowser|BrowserNG|Webos|Symbian|Windows Phone|)/i))){ window.location.href="跳转页面地址";//手机端的 }else{ window.location.href="跳转页面地址";//电脑端的 }
二、pc端网页布局特效交互
2.1 offset系列
(1)offset的认识
- offset就是偏移量的意思,它的一系列相关的属性可以动态的得到该元素的位置(偏移)、大小等等,但返回的值不带单位的;
- 常见的属性有: | offset系列属性值 | 说明 | | —- | —- | | element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级元素没有定位则返回body | | element.offsetTop | 返回元素相对带有定位父元素上方的偏移,相当于margin-top值 | | element.offsetLeft | 返回元素相对带有定位父元素左方的偏移,相当于margin-Left值 | | element.offsetWidth | 返回包括自身的padding、边框、内容区的宽度,值不带单位 | | element.offsetHeight | 返回包括自身的padding、边框、内容区的高度,值不带单位 |
Javascript拖拽登录模拟框案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>登录页面</title> <style> body { margin: 0; padding: 0; /*body不能给高度*/ /* height: 600px; */ background-color: rgb(179, 171, 171); } /* 清除浮动 */ /* .clearfix:before, .clearfix:after { content: ""; display: table; } .clearfix:after { clear: both; } .clearfix { *zoom: 1; } */ .title, h3 { text-align: center; margin-top: 15px; font-weight: 400; } .loginbox { display: none; position: fixed; /* top: 57px; left: 330px; */ top: 50%; left: 50%; width: 579px; height: 315px; transform: translate(-50%, -50%); background-color: rgb(255, 255, 255); ; } .username::before { content: "用户名:"; display: inline-block; height: 35px; line-height: 35px; margin-left: 14px; } .password::before { content: "登录密码:"; display: inline-block; line-height: 35px; height: 35px; } .username, .password { float: right; width: 439px; height: 35px; margin: 21px 70px 0 0; } input { width: 351px; height: 29px; float: right; } .submit { position: absolute; bottom: 63px; left: 50%; transform: translate(-50%, 0); width: 205px; height: 35px; margin: 0 auto; } button { display: block; width: 205px; height: 35px; } .close { position: absolute; right: -25px; top: -25px; width: 50px; height: 50px; text-align: center; line-height: 50px; border-radius: 50%; background-color: rgb(235, 235, 235); } </style> <script type="text/javascript"> window.addEventListener('load', function () { var title = document.querySelector(".title"); var loginBox = document.querySelector(".loginbox"); title.addEventListener("click", function () { console.log(loginBox); //todo 显示登录框 loginBox.style.display = "block"; }); loginBox.addEventListener("mousedown", function (evente) { // console.log("页面的x轴坐标" + (event.pageX - this.offsetLeft)); // console.log("页面的y轴坐标" + (event.pageY - this.offsetTop)); var boxInY = event.pageY - this.offsetTop; var boxInX = event.pageX - this.offsetLeft; this.addEventListener("mousemove",move); function move(e) { this.style.top = (e.pageY - boxInY) + "px"; this.style.left = (e.pageX - boxInX) + "px"; } this.addEventListener("mouseup",function(){ this.removeEventListener("mousemove",move); }); }); }); </script> </head> <body> <h1 class="title">点击登录弹出登录框</h1> <div class="loginbox clearfix"> <h3>登录会员</h3> <form method="get" action="#"> <div class="username"> <!--用户名:--><input type="text" name="username" placeholder="请输入用户名"> </div> <div class="password"> <!--登录密码:--><input type="password" name="password" placeholder="请输入密码"> </div> <div class="submit"> <button type="submit">登录会员</button> </div> </form> <div class="close">关闭</div> </div> </body> </html>
(2)client系列属性
- 常见的属性 | client系列属性 | 说明 | | —- | —- | | element.clientTop | 返回元素上边框的大小 | | element.clientLeft | 返回元素左边框的大小 | | element.clientWidth | 返回自身包括padding、内容区的宽度,不包含边框,不带单位 | | element.clientHeight | 返回自身包括padding、内容区的高度,不包括边框,不带单位 |
(3)立即执行函数
- 相当于Java中的static静态域,不用调用即可执行
- 语法: (function(){}()) 或者(function(){})();,参数传递现在后面的小括号中即可
作用: 创建一个独立的作用域,解决变量重名冲突问题,起到闭包作用
(4)scroll系列
scroll是滚动的意思,动态的得到元素的大小,滚动距离等
相关的属性 | scroll系列属性 | 作用 | | —- | —- | | element.scrollTop | 返回被卷去的上侧距离,不带单位 | | element.scrollLeft | 返回被卷去的左侧距离,不带单位 | | element.scrollWidth | 返回自身实际的宽度,不包括边框,不带单位 | | element.scrollHeight | 返回自身实际的高度,不包括边框,不带单位 |
例子 ```html <!DOCTYPE html>
我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容- ![Snipaste_2021-10-12_09-45-23.png](https://cdn.nlark.com/yuque/0/2021/png/12492094/1634003206511-daa65323-7b73-4c64-abb4-5da94d7c7e11.png#clientId=u16e17d2f-4750-4&from=ui&id=uc6e43ffb&margin=%5Bobject%20Object%5D&name=Snipaste_2021-10-12_09-45-23.png&originHeight=573&originWidth=1443&originalType=binary&ratio=1&size=276953&status=done&style=none&taskId=u44ae3296-56fc-4a56-b847-869594b5883) <a name="O9UNZ"></a> ## 2.2 js动画 <a name="BwN4Q"></a> ### (1)动画原理
html <!DOCTYPE html><a name="gcivW"></a> ### (2)函数封装动画功能代码
html <!DOCTYPE html> 夏雨荷```html <!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> div { position: absolute; left: 0; width: 100px; height: 100px; background-color: pink; } span { position: absolute; left: 0; top: 200px; display: block; width: 150px; height: 150px; background-color: purple; } </style> </head> <body> <button>点击夏雨荷才走</button> <div></div> <span>夏雨荷</span> <script> // var obj = {}; // obj.name = 'andy'; // 简单动画函数封装obj目标对象 target 目标位置 // 给不同的元素指定了不同的定时器 function animate(obj, target) { // 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是 让我们元素只有一个定时器执行 // 先清除以前的定时器,只保留当前的一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function() { if (obj.offsetLeft >= target) { // 停止动画 本质是停止定时器 clearInterval(obj.timer); } obj.style.left = obj.offsetLeft + 1 + 'px'; }, 30); } var div = document.querySelector('div'); var span = document.querySelector('span'); var btn = document.querySelector('button'); // 调用函数 animate(div, 300); btn.addEventListener('click', function() { animate(span, 200); }) </script> </body> </html>
(3)缓动画原理
<!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> div { position: absolute; left: 0; width: 100px; height: 100px; background-color: pink; } span { position: absolute; left: 0; top: 200px; display: block; width: 150px; height: 150px; background-color: purple; } </style> </head> <body> <button>点击夏雨荷才走</button> <span>夏雨荷</span> <script> // 缓动动画函数封装obj目标对象 target 目标位置 // 思路: // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。 // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长 // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器 function animate(obj, target) { // 先清除以前的定时器,只保留当前的一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function() { // 步长值写到定时器的里面 var step = (target - obj.offsetLeft) / 10; if (obj.offsetLeft == target) { // 停止动画 本质是停止定时器 clearInterval(obj.timer); } // 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10 obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } var span = document.querySelector('span'); var btn = document.querySelector('button'); btn.addEventListener('click', function() { // 调用函数 animate(span, 500); }) // 匀速动画 就是 盒子是当前的位置 + 固定的值 10 // 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10) </script> </body> </html>
<!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> div { position: absolute; left: 0; width: 100px; height: 100px; background-color: pink; } span { position: absolute; left: 0; top: 200px; display: block; width: 150px; height: 150px; background-color: purple; } </style> </head> <body> <button class="btn500">点击夏雨荷到500</button> <button class="btn800">点击夏雨荷到800</button> <span>夏雨荷</span> <script> // 缓动动画函数封装obj目标对象 target 目标位置 // 思路: // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。 // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长 // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器 function animate(obj, target) { // 先清除以前的定时器,只保留当前的一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function() { // 步长值写到定时器的里面 // 把我们步长值改为整数 不要出现小数的问题 // var step = Math.ceil((target - obj.offsetLeft) / 10); var step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { // 停止动画 本质是停止定时器 clearInterval(obj.timer); } // 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10 obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } var span = document.querySelector('span'); var btn500 = document.querySelector('.btn500'); var btn800 = document.querySelector('.btn800'); btn500.addEventListener('click', function() { // 调用函数 animate(span, 500); }) btn800.addEventListener('click', function() { // 调用函数 animate(span, 800); }) // 匀速动画 就是 盒子是当前的位置 + 固定的值 10 // 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10) </script> </body> </html>
<!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> div { position: absolute; left: 0; width: 100px; height: 100px; background-color: pink; } span { position: absolute; left: 0; top: 200px; display: block; width: 150px; height: 150px; background-color: purple; } </style> </head> <body> <button class="btn500">点击夏雨荷到500</button> <button class="btn800">点击夏雨荷到800</button> <span>夏雨荷</span> <script> // 缓动动画函数封装obj目标对象 target 目标位置 // 思路: // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。 // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长 // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器 function animate(obj, target, callback) { // console.log(callback); callback = function() {} 调用的时候 callback() // 先清除以前的定时器,只保留当前的一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function() { // 步长值写到定时器的里面 // 把我们步长值改为整数 不要出现小数的问题 // var step = Math.ceil((target - obj.offsetLeft) / 10); var step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { // 停止动画 本质是停止定时器 clearInterval(obj.timer); // 回调函数写到定时器结束里面 if (callback) { // 调用函数 callback(); } } // 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10 obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } var span = document.querySelector('span'); var btn500 = document.querySelector('.btn500'); var btn800 = document.querySelector('.btn800'); btn500.addEventListener('click', function() { // 调用函数 animate(span, 500); }) btn800.addEventListener('click', function() { // 调用函数 animate(span, 800, function() { // alert('你好吗'); span.style.backgroundColor = 'red'; }); }) // 匀速动画 就是 盒子是当前的位置 + 固定的值 10 // 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10) </script> </body> </html>
(4)轮播图案例
window.addEventListener('load', function() { // 1. 获取元素 var arrow_l = document.querySelector('.arrow-l'); var arrow_r = document.querySelector('.arrow-r'); var focus = document.querySelector('.focus'); var focusWidth = focus.offsetWidth; // 2. 鼠标经过focus 就显示隐藏左右按钮 focus.addEventListener('mouseenter', function() { arrow_l.style.display = 'block'; arrow_r.style.display = 'block'; clearInterval(timer); timer = null; // 清除定时器变量 }); focus.addEventListener('mouseleave', function() { arrow_l.style.display = 'none'; arrow_r.style.display = 'none'; timer = setInterval(function() { //手动调用点击事件 arrow_r.click(); }, 2000); }); // 3. 动态生成小圆圈 有几张图片,我就生成几个小圆圈 var ul = focus.querySelector('ul'); var ol = focus.querySelector('.circle'); // console.log(ul.children.length); for (var i = 0; i < ul.children.length; i++) { // 创建一个小li var li = document.createElement('li'); // 记录当前小圆圈的索引号 通过自定义属性来做 li.setAttribute('index', i); // 把小li插入到ol 里面 ol.appendChild(li); // 4. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件 li.addEventListener('click', function() { // 干掉所有人 把所有的小li 清除 current 类名 for (var i = 0; i < ol.children.length; i++) { ol.children[i].className = ''; } // 留下我自己 当前的小li 设置current 类名 this.className = 'current'; // 5. 点击小圆圈,移动图片 当然移动的是 ul // ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值 // 当我们点击了某个小li 就拿到当前小li 的索引号 var index = this.getAttribute('index'); // 当我们点击了某个小li 就要把这个li 的索引号给 num num = index; // 当我们点击了某个小li 就要把这个li 的索引号给 circle circle = index; // num = circle = index; console.log(focusWidth); console.log(index); animate(ul, -index * focusWidth); }) } // 把ol里面的第一个小li设置类名为 current ol.children[0].className = 'current'; // 6. 克隆第一张图片(li)放到ul 最后面 var first = ul.children[0].cloneNode(true); ul.appendChild(first); // 7. 点击右侧按钮, 图片滚动一张 var num = 0; // circle 控制小圆圈的播放 var circle = 0; // flag 节流阀 var flag = true; arrow_r.addEventListener('click', function() { if (flag) { flag = false; // 关闭节流阀 // 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0 if (num == ul.children.length - 1) { ul.style.left = 0; num = 0; } num++; animate(ul, -num * focusWidth, function() { //执行完动画后回调该函数 flag = true; // 打开节流阀 }); // 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放 circle++; // 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原 if (circle == ol.children.length) { circle = 0; } // 调用函数 circleChange(); } }); // 9. 左侧按钮做法 arrow_l.addEventListener('click', function() { if (flag) { flag = false; if (num == 0) { num = ul.children.length - 1; ul.style.left = -num * focusWidth + 'px'; } num--; animate(ul, -num * focusWidth, function() { flag = true; }); // 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放 circle--; // 如果circle < 0 说明第一张图片,则小圆圈要改为第4个小圆圈(3) // if (circle < 0) { // circle = ol.children.length - 1; // } circle = circle < 0 ? ol.children.length - 1 : circle; // 调用函数 circleChange(); } }); //改变小圆点样式的方法 function circleChange() { // 先清除其余小圆圈的current类名 for (var i = 0; i < ol.children.length; i++) { ol.children[i].className = ''; } // 留下当前的小圆圈的current类名 ol.children[circle].className = 'current'; } // 10. 自动播放轮播图 var timer = setInterval(function() { //手动调用点击事件 arrow_r.click(); }, 2000); })
三、移动端网页布局特效交互
3.1 触摸事件
(1)touch
拖拽元素案例
// (1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置 // (2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子 // (3) 离开手指 touchend: var div = document.querySelector('div'); var startX = 0; //获取手指初始坐标 var startY = 0; var x = 0; //获得盒子原来的位置 var y = 0; div.addEventListener('touchstart', function(e) { // 获取手指初始坐标 startX = e.targetTouches[0].pageX; startY = e.targetTouches[0].pageY; x = this.offsetLeft; y = this.offsetTop; }); div.addEventListener('touchmove', function(e) { // 计算手指的移动距离: 手指移动之后的坐标减去手指初始的坐标 var moveX = e.targetTouches[0].pageX - startX; var moveY = e.targetTouches[0].pageY - startY; // 移动我们的盒子 盒子原来的位置 + 手指移动的距离 this.style.left = x + moveX + 'px'; this.style.top = y + moveY + 'px'; e.preventDefault(); // 阻止屏幕滚动的默认行为 });
移动端点击延迟解决方案
- 插件解决方案
(2)轮播图插件
3.1 本地存储
(1)window.sessionStorage对象
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享的;
- 以键值对的形式存储和使用
- 常见的方法
- sessionStorage.setItem(key,value)
- sessionStorage.getItem(key);
- sessionStorage.removeItem(key)
- sessionStorage.clear();
(2)window.localStorage对象
- 生命周期为永久
- 可以在同一浏览器的多窗口(页面)共享数据
- 以键值对方式存储和使用
- 常见的方法跟sessionStroage 一样的;