一、JS基础
学习目标:
- 能够说出什么是编程语言
- 能够区分编程语言和标记语言的不同
- 能够说出常见的数据存储单位及其换算关系
- 能够说出内存的主要作用以及特点
1、编程语言
1.1编程
编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。
计算机程序:就是计算机所执行的一系列的指令集合,而程序全部都是我们所掌握的语言来编写的,所以人们要控制计算机一定要通过计算机语言向计算机发出命令。
注意:上面所定义的计算机指的是任何能够执行代码的设备,可能是智能手机、ATM机、黑莓PI、服务器等等
1.2计算机语言
计算机语言指的是用于人与计算机之间通讯的语言,它是人与计算机之间传递信息的媒介。
计算机语言的种类非常的多,总的来说可以分为机器语言,汇编语言和高级语言三大类
实际上计算机最终所执行的都是机器语言,它是由"0"和"1"组成的二进制数,二进制是计算机语言的基础。
例如:
0=00000000 1=00000001 2=00000010 3=00000011 4=00000100 5=00000101 6=00000110 7=00000111 8=00001000 9=00001001 10=00001010
1.3编程语言
可以通过类似人类语言的“语言”来控制计算机,让计算机为我们做事情,这样的语言就叫做编程语言。
编程语言是用来控制计算机的一系列指令,他有固定的格式和词汇(不同编程语言的格式和词汇不一样),必须遵守。
如今通用的编程语言有两种形式:汇编语言就和高级语言。
- 汇编语言和机器语言实质是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。
- 高级语言主要是相对于低级语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,常用的有c语言、c++、java、c# 、python、php、go语言、objective-c、swift等
1.4翻译器
高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,为此,我们需要一个翻译器。
翻译器可以为我们所编写的源代码转换为机器语言,这也被称为二进制化。记住1和0.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VDsrwtYR-1575368198355)(image/jm/3.png)]
1.5编程语言和编辑语言区别
- 编程语言有很强的逻辑和行为能力。在编程语言里,你会看到很多if else、for、while等具有逻辑性和行为能力的指令,这是主动的。
- 标记语言(html)不同于向计算机发出指令,常用语格式化和链接。编辑语言的存在是用来被读取的,他是被动的。
总结:
- 计算机可以帮助人类解决某些问题
- 程序员利用编程语言编写程序发出指令控制计算机来实现这些任务
- 编程语言有机器语言、汇编语言、高级语言
- 高级语言需要一个翻译器转换为计算机识别的机器语言
- 编程语言是主动的有很强的逻辑性
2、计算机基础
2.1计算机组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lgg9yfVe-1575368198357)(image/jm/4.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCJmUTeM-1575368198357)(image/jm/5.png)]
2.2数据存储
1.计算机内部使用二进制0和1来表示数据
2.所有数据,包括文件、图片等最终都是以二进制数据的形式放在硬盘中的
3.所有程序,包括操作系统,本质都是各种数据,也以二进制数据的形式放在硬盘中。平时我们所说的安装软件,其实就是把程序文件复制到硬盘中。
4.硬盘、内存都是保存的二进制数据。
2.3数据存储单位
bit<byte<kb<Gb<Tb<…
- 位(bit):1bit可以保存一个0或者1(最小的存储单位)
- 字节(Byte):1B=8b
- 千兆节(KB):1kb=1024b
- 兆字节(MB):1mb=1024kb
- 吉字节(GB ): 1GB=1024MB
2.4程序运行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F1gtHqVE-1575368198358)(image/jm/6.png)]
1.打开某个程序时,先从硬盘中把程序的代码加载到内存中
2.cpu执行内存中的代码
注意:之所以要内存的一个重要原因,是因为cpu运行太快了,如果只从硬盘中读数据,会浪费cpu性能,所以,才使用存储速度更快的内存来保存运行时的数据(内存是电,硬盘是机械)。
3、认识javascript
目标:
- 能够说出javascript是什么
- 能够知道javascript的发展历史
- 能够说出浏览器执行的javascript的原理
- 能够说出javascript有哪三个部分组成
- 能够写出javascript三个输入输出语句
3.1javascript是什么
- javascript是世界上最流行的语言之一,是一种运行在客户端的脚本语言(script是脚本的意思)。
- 脚本语言:不需要编译,运行过程中由js解释器(js引擎)逐行进行解释并执行
- 现在也可以基于node.js技术进行服务器编程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ECCD7hhx-1575368198359)(image/jm/7.png)]
3.2 javascript的作用
- 表单动态校验(密码强度检测)(js产生最初的目的)
- 网页特效
- 服务端开发(node.js)
- 桌面程序(elctron)
- app(sordova)
- 控制硬件-物联网(ruff)
- 游戏开发(cocos2d-js)
3.3 html/css/js的联系
html/css标记语言–描述类语言
- html决定网页结构和内容(决定看到什么),相当于人的身体
- css决定网页呈现给用户的模样(决定好不好看),相当于给人穿衣服和化妆
js脚本语音–编程类语言
实现业务逻辑和页面控制(决定功能),相当于人的各种动作
3.4浏览器执行js简介
浏览器分成两部分:渲染引擎和js引擎
-
渲染引擎:用来解析html与css,俗称内核,比如chrome浏览器的blink,老版本的webkit
-
js引擎:也称为js解析器。用来读取网页中的javascript代码,对其处理后运行,比如chrome浏览器的v8
注意:浏览器本身并不会执行js代码,而是通过内置javascript引擎来执行js代码。js引擎执行代码时逐行解释每一句源码(转换为机器语言),然后有计算器去执行,所以javascript语言归为脚本语言,会逐行解释执行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sds0ryfi-1575368198360)(image/jm/8.png)]
3.5 js的组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s7pVXhW3-1575368198361)(image/jm/9.png)]
- ECMAscript
ECMAscript是由ECMA国际进行标准化的一门编程语言,这种语言在万维网上应用广泛,他往往被称为javascript或jscript,但实际上两者是ECMAscript语言的实现和扩展。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwqPFpHQ-1575368198362)(image/jm/10.png)]
ECMAscript:ECMAscript规定了js的编程语法和基础核心知识,使所有浏览器厂商共同遵守的一套js语法工业标准。
-
DOM-文档对象模型
文档对象模型,是w3c组织推荐的处理可扩展标记语言的标准编程接口。通过dom提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。
-
BOM-浏览器对象模型
BOM是指浏览器对象模型,他提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。
3.6js的三种书写方式
js有三种书写位置,分别为行内、内嵌和外部。
1.行内式
<input type="button" onclick="alert('你好')">
-
可以将单行或少量js代码卸载html标签的事件属性中(以on开头的属性),如onclick
-
注意单双引号的使用:在html中我们推荐使用的是双引号,js中我们推荐使用的是单引号
-
可读性差,在html中编写js大量代码时,不方便阅读
-
引号易错,引号多层嵌套匹配时,非常容易弄混
-
特殊情况下使用
2.内嵌式
<script>
alert("hello");
</script>
特点:
- 可以将多行js代码写道
3.外部式
<script scr="js/index.js"></script>
- 利于html页面代码结构化,把js代码独立到html页面之外,既美观,也方便文件级别的复用
- 引用外部js文件的script标签中间不可以写代码
- 适用于js代码量比较大的情况
4、javascript注释
<script>
//单行注释
/*多行注释
多行注释*/
</script>
5、javascript输入输出语句
为了方便信息的输入输出,js中提供了一些输入输出语句,其常用的语句如下:
方法 | 说明 | 归属 |
---|---|---|
alert) | 浏览器弹出警示框 | 浏览器 |
console.log() | 浏览器控制台打印输出信息 | 浏览器 |
prompt() | 浏览器弹出输入框,用户可以输入 | 浏览器 |
<script>
prompt("请输入您的年龄:");
alert("你好");
console.log(11);
</script>
6、变量
目标:
- 能够说出变量的主要作用
- 能够写出变量的初始化
- 能够说出变量的命名规范
- 能够画出变量是如何在内存中存储的
- 能够写出交换变量的案例
6.1变量的概述
-
什么是变量
白话:变量就是一个装东西的盒子
通俗:变量是用于存放数据的容器。我们通过变量名获取数据,甚至数据可以修改。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W36WWpSI-1575368198364)(image/jm/11.png)]
-
变量的本质:变量是程序在内存中申请的一块用来存放数据的空间
类似我们酒店的房间,一个房间就可以看作是一个变量。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AfmJuV19-1575368198370)(image/jm/12.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J9kirSJG-1575368198371)(image/jm/13.png)]
6.2变量的使用
变量在使用时分为两步:1.声明变量2.赋值
1.声明变量
var age;//就是声明了一个名称为age的变量
- var 是一个js关键字,用来声明变量。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管
- age是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间
2.赋值
age=10;//给age这个变量赋值为10
- =用来把右边的值赋给左边的变量空间中,此处代表赋值的意思
- 变量值是程序员保存到变量空间的值
3.变量的初始化
var age=10;//赋值的同时赋值为10
声明一个变量并赋值,我们称为变量的初始化
4.变量的使用案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OjnIeDYO-1575368198371)(image/jm/14.png)]
<script>
var name="旗木卡卡西";
var address="火影村";
var age=30;
var email="kakaxi@itcast.cn";
var gz=2000;
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2SLhUQt-1575368198372)(image/jm/15.png)]
<script>
var myname=prompt("请输入您的姓名:");
alert(myname);
</script>
6.3变量的语扩展
1.更新变量
一个变量被重新赋值以后,它原有的值就会被覆盖,变量将以最后一次赋的值为准
var age=18;
age=81;
console.log(age);//最后输出的结果为81,因为18被覆盖掉了
2.同时声明多个变量
同时声明多个变量时,只需要写一个var ,多个变量名之间使用英文逗号隔开。
var age=10,name="zs",sex=2;
3.声明变量特殊情况
情况 | 说明 | 结果 |
---|---|---|
var age;console.log(age); | 只声明,不赋值 | undefined |
console.log(age) | 不声明,不赋值,直接使用 | 报错 |
age=10;console.log(age) | 不声明,不赋值 | 10 |
6.4变量的命名规范
-
由字母、数字、下划线、$组成。
-
严格区分大小写
-
不能以数字开头
-
不能使关键字
-
变量名必须要有意义
-
遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。
-
推荐使用翻译网站:有道 爱词霸
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j1DIWjLF-1575368198373)(image/jm/16.png)]
<script>
var temp;
var apple1="青苹果";
var apple2="红苹果";
temp=apple1;
apple1=apple2;
apple2=temp;
console.log(apple1);
console.log(apple2);
</script>
变量总结:
-
为什么需要变量
因为我们一些数据需要保存,所以需要变量
-
变量是什么
变量就是一个容器,用来存放数据的。方便我们以后使用里面的数据
-
变量的本质是什么
变量是内存里的一块空间,用来存储数据的。
-
变量怎么使用的
我们使用变量的时候,一定要声明变量,然后赋值。声明变量本质是去内存申请空间。
-
什么是变量的初始化
声明变量并赋值就是变量的初始化
-
变量的命名规范有那些
详情请看变量的命名规范
-
交换2个变量值的思路是什么
看上面的案例
7、数据类型
目标:
- 能够说出5种简单数据类型
- 能够使用typeof获取变量的类型
- 能够说出1-2中转换树脂型的方法
- 能够说出1-2中转换为字符型的方法
- 能够说出什么是隐式转换
7.1数据类型简介
1.为什么需要数据类型
在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需要内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。简单来说,数据类型就是数据的类别型号。
2.变量的数据类型
变量是用来存储值的所在处,他们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。javascript是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
var age=10;//这是一个数字型
var hello="你好";//这是一个字符串
在代码运行时,变量的数据类型是由js引擎根据=右边变量值的数据类型来判断的,运行完毕之后,变量就确定了数据类型。
js拥有动态类型,同时也意味着相同的变量可用作不同的类型
var x=6;//x为数字
var x="bill";//x为字符串
3.数据类型的分类
js把数据类型分为两类:
- 简单数据类型:number、string、boolean、undefined、null
- 复杂数据类型:object
7.2简单数据类型
1.简单数据类型
javaScript中的简单数据类型及其说明如下:
简单数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含整数和浮点数,如21、0.123 | 0 |
Boolean | 布尔值类型,如true、false,等价于1和0 | false |
String | 字符串类型,如”张三“,注意咱们js里面,字符串都带引号 | ”“ |
Undefined | var a;声明了变量a但是没有给值,此时a=undefined | undefined |
Null | var a=null;声明了变量a为空值 | null |
2.数值型Number
js数字类型既可以用来保存整数值,也可以保存小数。
var age=21;//整数
var Age=0.2435;//小数
-
数字型进制
最常见的进制有二进制、八进制、十进制、十六进制。
//1.八进制数字序列范围:0-7 var num1=07;//对应的十进制的7 var num2=019;//对应十进制的19 //2.十六进制数字序列范围:0-9以及A-F var num=0xA;
现在阶段我们只需要记住,在js中八进制前面加0,十六十进制加0x
-
数字型范围
alert(Number.MAX_VALUE); alert(Number.MIX_VALUE)
-
数值型的三个特殊值
infinity,代表无穷大,大于任何数值
-infinity,代表无穷小,小于任何数值
NaN,Not a number,代表一个非数值
-
isNaN()
用来判断一个变量是否为非数字的类型,返回true或者false。
如果是数字则返回false,不是数字返回true
console。log(isNaN(12));//返回false,12是数字 console。log(isNaN("nihao"));//返回true,nihao不是数字
3.字符串型
字符串可以是引号中的任意文本,其语法为双引号和单引号。
var str="niho";
var str1='1';
因为html中标签里面的属性使用的是双引号,js这里我们更推荐使用单引号。
-
字符串引号嵌套
js可以用单引号嵌套双引号,或者用双引号嵌套单引号,注意不能单双引号搭配
var str="小花是一个非常'漂亮'的语文老师"; var str='小花是一个非常"漂亮"的语文老师'; var str='小花是一个非常漂亮的语文老师";//单双引号搭配报错
-
字符串转义符
类似于html里面的特殊字符,字符串中也有特殊的字符,我们成为转义符
转义符要写道引号里面
转义符都是\开头的,常见的转义符及其说明如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x7mFh811-1575368198374)(image/jm/17.png)]
-
检测获取字符串的长度 length
var str="my name is andy"; console.log(str.length);//返回结果是15
-
字符串的拼接
多个字符串之间可以使用+进行拼接,其拼接方式为字符串+任何类型=拼接之后的新字符串
拼接前会把字符串相加的任何类型转成字符串,再拼接成一个新的字符串
console.log("你好"+"小明");//返回结果为你好小明 console.log("hello"+12);//返回结果hello12 console.log("12"+12);//1212
-
字符串拼接加强
console.log("小明今年18了"); var age=10; console.log("小明今年age岁了");//这样的返回结果为小明今年age岁了 console.log("小明今年"+age+"岁了");//这种方式是对的
我们经常会将字符串和变量来拼接,因为变量可以很方便的修改里面的值
变量是不能添加引号的,因为加引号的变量会变成字符串
如果变量两侧都有字符串拼接,口诀为”引引加加“,删掉数字,变量写加号中间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z9mR7jE5-1575368198375)(image/jm/18.png)]
<script>
var age=prompt("请输入您的年龄");
var str="您今年"+age+"岁了";
alert(str);
</script>
4.布尔值Boolean
布尔值有两个值:true和false,其中true表示真,false表示假。
在布尔值和数值型相加的时候,true的值是1,false的值是0
console.log(true+1);//2
console.log(false+1);//1
5.undefined和null
-
undefined是一个声明后没有被赋值的变量会有一个默认值undefined(如果进行相加或者相连的时候,注意结果)。
如果undefined和数字相加,结果是NaN
var i; console.log(i+0);//返回的结果为是NaN
如果和字符串相加,最后结果则是一个拼接的字符串
console.log(i+"hello");//undefinedhello
-
null: 一个声明变量给null值,里面存的值为空。
null和数值相加的时候就相当于0
var vari=nill; console.log(vari+"你好");//null你好 console.log(1+vari);//1 console.log(true+vari);//1
7.3获取变量数据类型
1.typeof可以用来检测变量的数据类型
数字型的返回结果为number,布尔值类型的返回结果为boolean,字符串型的返回结果为string,undefined型返回的是undefined,null的返回结果为object。
例如:
var n=null;
console.log(typeof n);//返回结果为object。
var num=12;
console.log(typeof num);//返回结果为number
2.字面量
字面量是在源代码中的一个固定值的表示法,通俗来说,就是字面量表示如何表达这个值。
- 数字字面量:0,1,3等等
- 字符串字面量:“helou”,“true”;
- 布尔值字面量:true、false
7.4数据类型转换
数据类型:就是把一种数据类型转换为另外一种数据类型
一般我们会实现三种方式的转换:转换为字符串,转化为数字型,转换为布尔值
1.转换为字符串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-URmEpLBp-1575368198375)(image/jm/19.png)]
<script>
//第一种方法 变量.toString()
var num=10;
str=num.toString();
console.log(typeof str);
//第二种方法String(变量)
console.log(String(num));
//隐式转化,用+拼接
console.log(num+"");
</script>
2.转化为数字型(重点)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vyyk3t8C-1575368198376)(image/jm/20.png)]
注意:
- paserInt和parseFloat单词的大小写,这两个是转换数值的重点
- 隐式转换是我们在进行运算的时候,js自动转换了数据类型
<script>
//取整 parseInt()
console.log(parseInt("3.14"));//3
console.log(parseInt("78ad"));//78
console.log(parseInt("ab12cd"));//NaN
//取小数parseFloat()
console.log(parseFloat("3.14"));//3.14
console.log(parseFloat("5.6we"));//5.6
console.log(parseFloat("re3.14"));//"NaN
//Number()
console.log(typeof Number("12"))//number
//隐式转换-0 *1 /1
console.log("12"-0);//12
console.log("12"*1);//12
console.log("12"/1);//12
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2CLsUWY1-1575368198377)(image/jm/21.png)]
var year=prompt("请输入您的出生年份");
var age=2018-year;
alert("您今年"+age+"岁了");
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iu53zjAn-1575368198377)(image/jm/22.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-etQAvg8g-1575368198378)(image/jm/23.png)]
var num1=prompt("请您输入第一个值");
var num2=prompt("请您输入第二个值");
var result=parseFloat(num1)+parseFloat(num2);
alert("这两个值的结果是"+result);
3.转换为布尔值
转换方式用Boolean()函数
-
代表空、否定的值都会转换为false,如:空串“”、NaN、null、undefined
-
其余的值都是true
console.log(Boolean(""));//false console.log(Boolean(null));//false console.log(Boolean(0));//false console.log(Boolean(undefined));//false console.log(Boolean(NaN));//false console.log(Boolean("nihao"));//true console.log(Boolean(2));//true
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7fZJbF5f-1575368198379)(image/jm/24.png)]
var name=prompt("请输入您的姓名:");
var age=prompt("请输入您的年龄:");
var sex=prompt("请输入您的性别:");
alert("您的姓名是"+name+"\n您的年龄是"+age+"\n您的性别为"+sex);
8、运算符
目标:
- 能够使用常用的运算符
- 能够说出前置递增和后置递增的区别
- 能够说出运算符的优先级
运算符:也被称为操作符,是用于实现赋值、比较和执行算数运算符等功能的符号。
js中常用的运算符有:.算术运算符、递增和递减运算符、比较运算符、逻辑运算符、赋值运算符、
1.算术运算符
算术运算符使用的符号,用于执行两个变量或值的算数运算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8kJd0tyk-1575368198380)(image/jm/25.png)]
console.log(1 + 1);//2
console.log(5%3);//5/3余数为2
-
注意:浮点数的精度问题
浮点数值的最高精确度是17位小数,但是在进行计算时精确度远远不如整数。
console.log(0.2+0.1);//返回结果为0.30000000000000004 var result=0.1+0.2; console。log(result==0.3);//false
因此,千万不要判断两个浮点数是否相等
-
表达式和返回值
表达式:就是由数字、运算符、变量等组成的式子。
congsole.log(1+1);//返回结果2 //其中1+1就是表达式 //2则是返回值 //在我们程序里面2=1+1就是把我们的右边表达式计算完毕之后把返回值给左边
2.递增和递减运算符
如果需要反复给数字变量添加或者减去1,可以使用递增(++)和递减(- -)运算符来完成
在js中,递增和递减既可以放在变量的前面也可以放在变量的后面。放在变量前面时,称为前置递增或者前置递减运算符,放在变量后面时,我们可以成为后置递增运算符或者后置递减运算符。
注意:递增和递减必须和变量配合使用。
-
前置递增
++num前置递增,就是自加1,相当于num=num+1
使用口诀是:先自增1,再返回值
var num=10; ++num; console.log(num);//返回结果为11; //++num相当于num=num+1; var p=10; //++p前置递增,就是先自增1,再返回值 console.log(++p + 10);//返回值为21
-
后置递增
num++后置递增,就是自加1,相当于num=num+1,但是num++写起来更加方便
使用口诀:先返回原值,再自增
var num=10; num++;//和++num的效果一样 console.log(num);//11 var num=10; console.log(num++ +10);//20 console.log(num);//11
前置和后置的递增小题:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9LEsUBJ8-1575368198381)(image/jm/26.png)]
小结:
- 潜质递增和后置递增运算符可以简化代码的编写,让变量的值+1,比之前写法简单
- 单独使用时,运行结果相同
- 与其他代码联用时,执行结果会不同。
- 后置:先原值运算,后自加
- 前置:先自加,后运算。
- 在开发中,法多使用后置的运算符,num++或者num–。
3.比较运算符
比较运算符是两个数据进行比较时所使用的运算符,比较远算后,会返回一个布尔值true或者false作为比较运算的结果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8cC7Q9Lm-1575368198382)(image/jm/27.png)]
注意:=等号的总结
- =的作用就是赋值,把右边给左边
- ==的作用是判断,判断两边的值是否相等
- ===的作用是全等,判断两边的值和数据类型是否完全相等
4.逻辑运算符
逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值,开发中经常用于多个条件的判断。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HtvbAHPG-1575368198382)(image/jm/28.png)]
-
逻辑与 &&
两边都是true才能返回true,有一个false就返回false
console.log(3>1 && 5>2);//true console.log(3>5 && 5>2);//false
-
逻辑 ||
两边都是false才返回false,如果有一个是true则会返回true。
console.log(3>5 || 5>2);//true console.log(3>5 || 5<2);//false
-
逻辑非 !
!也叫做取反符,用来区一个布尔值相反的值,如true的相反值是false
var isOk=!true; console.log(isOk);//false
-
短路运算
原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边表达式的值。
1.逻辑与&&
-
语法:表达式1&&表达式2
-
如果第一个表达式的值为真,则返回表达式2
-
如果第一个表达式的值为假,则返回表达式1
console.log(2&&3);//3 console.log(7&&3-2);//1 console.log(0 && 2)//0 console.log("" && 2-1 &&3+3);//""
2.逻辑或 ||
-
语法:表达式1 || 表达式2
-
如果第一个表达式的值为真,则返回第一个表达式
-
如果第一个表达式的值为假,则返回表达式2
console.log(123 || 456);//123 console.log(0|| 456);//456 console.log(123 || 456 || 789);//123
-
5.赋值运算符
概念:用来把数据赋值给变量的运算符。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWIAWMWe-1575368198383)(image/jm/29.png)]
var age=10;
age+=5;//相当于age=age+5
age—=5;//相当于age=age-5
age*=5;//相当于age=age*5
age/=5;//相当于age=age/5
age%=5;//相当于age=age%5
6.运算符优先级
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zODjnrYM-1575368198384)(image/jm/30.png)]
注意:
- 一元运算符里面的逻辑非优先级很高
- 逻辑与比逻辑或优先级高
console.log(4 >= 6 || '人' != '阿凡达' && !(12*2===144)&& true);//true
var num=10;
console.log(5==num/2 && (2+2*num).toString()==="22");//true
9、流程控制分支语句
目标:
- 能够使用if分支语句
- 能够使用swich分支语句
- 能够使用三元表达式
1.流程控制
流程控制就是来控制我们的代码按照什么控制顺序来执行的。
流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,这三种结构代表三种代码执行的顺序。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8np0eUSX-1575368198385)(image/jm/31.png)]
2.顺序流程控制
顺序结构是程序中最简单最基本的流程控制,他没有特定的语法结构,程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KB0CsR5Y-1575368198385)(image/jm/32.png)]
3.分支流程控制if语句
-
分支结构:从上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eKnET0D1-1575368198386)(image/jm/33.png)]
在js语言中提供了两种分支结构语句:if语句和swich语句
-
if语句
语法结构:
if(条件表达式){
执行语句
}
备注:里面的执行语句可以理解为一个行为,循环语句和分支语句就是典型的语句。一个程序是由多个语句组成,一般情况下,会分割成一个一个的语句。
执行思路是:如果if里面的条件表达式结果为真,则执行大括号里面的执行语句,如果if条件表达式结果为假,则不执行大括号里面的语句,则执行if语句后面的代码。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O4WCw9TG-1575368198387)(image/jm/34.png)]
//1。用输入框,输入年龄,并把里面的内容赋值给一个新的变量
//2.用if语句进行判断,如果超过18岁则可以进入网吧,不到18岁就不用做任何操作
var age=prompt("请输入您的年龄:");
if(age>=18){
alert("您可以进入网吧");
}
-
if else 双分支语句
if就是如果的意思,else就是否则的意思
语法结构:
if(条件表达式){
执行语句1
}else{
执行语句2
}
执行思路: 如果条件表达式的结果为真,则执行语句1,如果条件表达式为假,则执行语句2.
var age=prompt("请输入您的年龄:"); if(age>=18){ alert("您可以进入网吧"); }else{ alert("您的年龄不够,不能来网吧玩"); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dIOrVMo8-1575368198388)(image/jm/35.png)]
//输入年份并保存到变量year中 var year=prompt("请输入年份"); //进行判断 if(year%4==0 && year%100 !=0 || year%400 ==0){ alert(year+"是闰年"); }else{ alert(year+"不是闰年,是平年"); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YKOIMoXY-1575368198389)(image/jm/36.png)]
//输入框接受一个姓名,并把姓名赋值给一个新的变量保存
//进行if..else判断
var uname=prompt("请输入您的名字:");
if(uname=="刘德华"){
alert("您中奖了5块钱");
}else{
alert("您没有中奖");
}
-
if…else if多分支语句
语法结构:
if(条件表达式1){
执行语句1
}else if(条件表达式2){
执行语句2
}else if(条件表达式2=3){
执行语句3
}else{
最后的语句
}
执行思路:
如果条件表达式1满足就执行语句1,执行完毕后,退出整个if分支语句;
如果条件表达式1不满足,则会判断条件表达式2,满足的话,就会执行语句2,以此类推。
如果上面的所有条件表达式都不成立,则执行else里面的语句。
注意:
- 分支语句还是多选1,最后只能有一个语句执行
- else if里面的条件理论上是可以任意多个的
- else if 中间有个空格,并且else if后面有个小括号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xfh6Eh6I-1575368198390)(image/jm/37.png)]
//要用从大到小的思路
//语句较多应该用if else if
var score=prompt("请输入您的成绩:");
if(score>=90){
alert("你的成绩是A");
}else if(score>=80){
alert("你的成绩是B");
}else if(score>=70){
alert("你的成绩是C");
}else if(score>=60){
alert("你的成绩是D");
}else {
alert("你的成绩不合格");
}
4.三元表达式
三元表达式也能做一些简单的条件选择,有三元运算符组成的式子成为三元表达式。(和if else 双分支语句类似)
语法结构:
条件表达式? 表达式1:表达式2
执行思路:如果条件表达式结果为真,则返回表达式1的值,如果条件表达式结果为假,则返回表达式2的值。
var num=10;
var result=num>5 ? "是的":"不是";
console.log(result);//是的
//下面的if else的写法和上面的三元表达式类似
/*if(num>5){
console.log("是的");
}else{
console.log("不是的")
}*/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfgTXxAJ-1575368198391)(image/jm/38.png)]
var time=prompt("请输入一个1-59的数字");
var result=time<10 ? "0"+time : time
alert(result);
5.分支流程控制switch语句
switch语句也是多分支语句,它用于基于不同的条件来执行不同的代码,当要针对变量设置一系列的特定值的选项时,就可以用swich。
注意:
- swich语句也是多分支语句,也可以实现多选1;
- switch的意思是转换、开关,case是小例子或者选项的意思
语法结构:
switch(表达式){
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
…
default:
执行最后的语句;
}
执行思路:利用我们的表达式的值和case后面的选项相匹配,如果匹配的上,就执行case1里面的语句,如果都没有匹配上,那么执行defalut里面的语句。
switch(2){
case 1:
console.log("这是1");
break;
case 2:
console.log("这是2");
break;
case 3:
console.log("这是3");
break;
default:
console.log("没有可以匹配的值");
}
注意事项:(以为下案例可以体现出)
- 我们开发中,表达式经常写成变量
- 我们num的值和case的值相匹配的时候是全等的,必须是值和数据类型全等
- break 如果当前的case里面没有break则不会退出switch,是继续执行下一个case的。
var num=3;
switch(num){
case 1:
console.log("这是1");
break;
case 2:
console.log("这是2");
break;
case 3:
console.log("这是3");
break;
default:
console.log("没有可以匹配的值");
}
//最后输出的结果为这是3,如果把上面的变量值num="3",那么最后的输出结果为没有可以匹配的值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vZanAzi4-1575368198391)(image/jm/39.png)]
var fruit=prompt("请输入水果名");
switch(fruit){
case "苹果":
alert("苹果是3.5元/斤");
break;
case "榴莲":
alert("榴莲是35元/斤");
break;
default:
alert("没有此类水果");
}
switch…case语句和if… else if语句的区别:
- 一般情况下,他们两个语句可以相互替换
- switch…case语句通常处理case为比较确定值的情况,而if… else if语句更加灵活,常用于范围判断(大于、等于某个范围)
- switch语句进行条件判断后直接执行到程序的条件语句,效率更高。而if… else 语句有几种条件,救得判断多少次。
- 当分支语句比较少时,if… else语句的执行效率比switch语句高。
- 当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。
6.分支练习案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cCH0NW3Q-1575368198392)(image/jm/40.png)]
10、流程控制循环
目标:
- 能够说出循环的目的
- 能够说出for循环的执行过程
- 能够使用断点调试来观察代码的执行过程
- 能够使用for循环完成累加求和等案例
- 能够使用双重for循环完成乘法表等案例
- 能够说出while循环和do while循环的区别
- 能够说出break和continue的区别
1.循环
循环的目的:在许多实际问题中,有很多具有规律性的重复操作,因此在程序中要完成这类操作就需要重复执行某些语句。
js中的循环主要有三种类型的循环语句:for循环、while循环、do…while循环
2.for循环
在程序中,一组被重复执行的语句被称为循环体,能否继续重复执行,取决于循环的终止条件。由循环体以及循环的终止条件组成的语句,被称为循环语句。
-
语法结构:
for循环主要用于把某些代码循环若干次,是和计数器有关系。
for(变量初始化;条件表达式;操作表达式){
//循环体
}
其中初始化变量:就是var声明的一个普通变量,通常用于作为计数器使用。
条件表达式:就是用来决定每一次循环是否继续执行,就是终止的条件。
操作表达式: 是每次循环最后执行的代码,经常用于我们计数器变量进行更新(递增或者递减)。
for(var i = 1; i <=100; i++){ console.log("你好吗") ; }
-
for循环的执行过程
首先执行里面的计数器变量,var i=1,但是这句话在for循环中只执行一次,然后去i<=100来判断是否满足条件,如果满足条件就去执行循环体,不满足条件就退出循环,最后去执行i++,第一轮循环结束,接着去执行i<=100,如果满足条件就去执行循环体,不满足就退出循环,以此类推。
-
断点调试:
断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码就可以显示明显错误停下。
断点调试可以帮我们观察程序的运行过程
浏览器中按f12-sources-找到需要调试的文件-在程序的某一行设置断点。
watch:监视,通过watch可以监视变量的值的变化,非常的常用。
f11:程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的值的变化。
-
for循环可以执行相同的代码
for(var i = 1; i <=100; i++){ console.log("你好吗") ; }
-
for循环也可以执行不同的代码
for(var i=1;i<=100;i++){ console.log("这个人今年"+i+"岁了") }
-
for循环重复某些相同操作:因为有了计算器的存在,我们还可以重复的执行某些操作,比如一些算数运算。
//求1-100之间所有整数的累加和 var sum=0; for(var i=1;i<=100;i++){ sum=sum+i; } console.log(sum);
案例:
//1.求1-100之间所有数的平均值 var sum=0; for(var i=1;i<=100;i++){ sum=sum+i; } var average=sum/100; console.log("1-100之间所有数的平均值是"+average) //2.求1-100之间所有偶数和奇数的和 //偶数是能被2整除的数,奇数是不能被2整除的数 var sum1=0;//偶数的和的变量 var sum2=0;//奇数的和的变量 for(var i=1;i<=100;i++){ if(i%2==0){ sum1=sum1+i; }else{ sum2=sum2+i; } } console.log("偶数的和"+sum1); console.log("奇数的和"+sum2); //3.求1-100之间所有能被3整除的数字的和 var sum=0; for(var i=1;i<=100;i++){ if(i%3==0){ sum=sum+i; } } console.log("1-100之间所有能被3整除的数字的和是:"+sum)
求学生成绩的案例
var num=prompt("请输入班级总人数:"); var sum=0; var average=0; for(var i=1;i<=num;i++){ var score=prompt("请输入第"+i+"个学生的成绩"); sum=sum+parseFloat(score); } average=sum/num; alert("班级总成绩为:"+sum); alert("班级总成绩的平均值为:"+average);
-
一行打印5个星星*****,我们可以采取拼接字符串的方式打印
var str=""; for(var i=1;i<=5;i++){ str=str+"*"; } console.log(str);`
3.双重循环
-
双重for循环介绍
在很多情况下,单层的for循环并不能满足我们的需求,比如我们打印一个5行5列的图形、打印一个倒直角三角形,此时就可以通过循环嵌套来实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CIzt2VPO-1575368198393)(image/jm/41.png)]
循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,例如在for循环里面再套一个for循环,这样的for循环语句我们称之为双重for循环。
-
双重for循环的语法结构
for(外层的初始化变量;外层的条件表达式;外层的操作表达式){ for(里层的初始化变量;里层的条件表达式;里层的操作表达式){ //执行语句 } }
注意:我们可以把里面的循环看作是外层循环的语句,外层循环循环一次,里面的循环执行全部。
for(var i=1;i<=3;i++){ console.log("这是外层的第"+i+"层"); for(var j=1;j<=3;j++){ console.log("这是外层的第"+j+"层"); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WHvraIkD-1575368198394)(image/jm/42.png)]
//打印几行几列的星星
var rows=prompt("请输入您要打印星星的行数:");
var cols=prompt("请输入您要打印星星的列数:");
var str="";
for(var i=1;i<=rows;i++){
for(var j=1;j<=cols;j++){
str=str+"*";
}
str=str+"\n";
}
console.log(str);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jCGbLVxD-1575368198395)(image/jm/43.png)]
var str="";
for(var i=1;i<=10;i++){//外边的for控制行
for(var j=i;j<=10;j++){//里面的for控制列
str=str+"*";
}
}
console.log(str);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PEYeruFo-1575368198395)(image/jm/44.png)]
var str="";
for(var i=1;i<=10;i++){//外边的for控制行
for(var j=1;j<=i;j++){//里面的for控制列
str=str+"*";
}
str=str+"\n";
}
console.log(str);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IOW8k52D-1575368198396)(image/jm/45.png)]
for(var i=1;i<=9;i++){
for(var j=1;j<=i;j++){
document.write(j+" * "+i +" = " +i*j +"  ");
}
document.write("<br/>");
}
-
for循环小结
for循环可以重复执行某些相同的代码
for循环可以重复执行一些不同的代码,因为我们有计数器
for循环可以重复执行某些操作,比如算数运算符加法操作
随着需求增加,双重for循环可以做更多、更好看的效果
双重for循环,外层循环一次,内层for循环全部执行
for循环是循环条件和数字直接相关的循环
分析要比写代码更重要
一些核心算法想不到,但是要学会,分析他执行的过程
举一反三,自己要经常总结,做一些相似的案例
4.while循环
while语句可以在条件表达式为真的前提下,循环执行指定的一段代码,直到表达式不为真时结束循环。
-
while的语法结构如下:
while(条件表达式){ //循环体 }
执行思路:
- 限制性条件表达式,如果结果为真,则执行循环体代码;如果为false,则退出循环,执行后面代码。
- 执行循环体代码
- 循环体代码执行完毕后,程序会继续判断执行条件表达式,如条件仍为true,则会继续执行循环体,直到循环条件为false时,整个循环过程才会结束。
var num=1;
while(num<=100){
console.log("你好呀")
num++;
}
案例
//1.打印人的一生,从1岁到100岁
var i=1;
while(i<=100){
console.log("你今年"+i+"岁了");
i++;
}
//2.计算1-100之间所有整数的和
var num=1;
var sum=0;
while(num<=100){
sum=sum+num;
num++;
}
console.log(sum);
//3.弹出一个提示框,你爱我吗?如果输入我爱你,就提示结束,否则一直询问message
var message=prompt("你爱我吗?");
while(message !=="我爱你"){
message=prompt("你爱我吗?");
}
alert("我也爱你");
5.do while循环
do…while语句其实是while语句的一个变体。该循环会先执行一次代码块,然后对条件表达式进行判断,如果条件为真,就会重复执行循环体,否则退出循环。
-
语法结构:
do{
//循环体
}while(条件表达式)
执行思路为:
- 先执行一次循环体代码
- 在执行条件表达式,如果结果为真,则继续执行循环体代码,如果为false,则退出循环循环,继续执行后面的代码。
注意:先执行循环体,再进行判断,我们会发现do
while循环语句至少会执行一次循环体代码。
var i=1; do{ console.log("你好!"); i++; }while(i<=100)
6.continue 和 break
-
continue是退出本次循环,继续执行剩余次数循环
for(var i=1;i<=5;i++){ if(i == 3){ continue; } console.log("我正在吃第"+i+"个包子"); } /*返回结果为: * 我正在吃第1个包子 *我正在吃第2个包子 *我正在吃第4个包子 *我正在吃第5个包子 */ //求1-100之间,除了能被7整除的数字的和 var sum=0; for(var i=1;i<=100;i++){ if(i%7==0){ continue; } sum=sum+i; } console.log(sum)
-
break关键字
break关键字用于立即跳出整个循环(循环结束)。
例如:吃了五个包子,迟到第三个发现包子厘米那有个虫子,其余的不吃了。
for(var i=1;i<=5;i++){ if(i == 3){ break; } console.log("我正在吃第"+i+"个包子"); } /*返回结果为: * 我正在吃第1个包子 我正在吃第2个包子*/
7.循环小结
- js中循环有for、while、do…while
- 三个循环很多情况下都可以相互替代使用
- 如果是用来计次数,跟数字相关的,三者使用基本相同,但是我们更喜欢用for
- while和do while可以做更加复杂的判断条件,比for循环灵活一些
- while和do while执行顺序不一样,while先判断再执行,do while先执行一次,再判断执行
- while和do while执行次数不一样,do while至少会执行一次循环体,而while可能一次也不执行
- 实际工作中,我们更常用for循环语句,它写法更简洁直观,以后开发中是重点。
循环作业
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script>
//1.求1-100之间所有数的总和与平均值
/*var sum = 0;
for (var i = 1; i <= 100; i++) {
sum = sum + i;
}
var average = sum / 100;
console.log("总和" + sum);
console.log("平均值为" + average);*/
//2.求1-100之间所有偶数的和
/*var sum=0;
for(var i=1;i<=100;i++){
if(i % 2 == 0){
sum=sum+i;
}
}
console.log("偶数的和为"+sum);*/
//3.求100以内7的倍数的总和
/*var sum=0;
for(var i=1;i<=100;i++){
if(i % 7 == 0){
console.log(i);
sum=sum+i;
}
}
console.log("100以内7的倍数的总和为"+sum);*/
//4.使用for循环打印矩形,要求每次只能输出一个*
/*for(var i=1;i<=5;i++){
for(var j=1;j<=5;j++){
document.write("*");
}
document.write(" <br/> ");
}*/
/*var str="";
for(var i=1;i<=5;i++){
for(var j=1;j<=5;j++){
str=str+"*";
}
str=str+"\n";
}
console.log(str);*/
//5.使用for循环打印正三角形
/*for(var i=1;i<=5;i++){
for(var j=1;j<=i;j++){
document.write("*");
}
document.write("<br/>");
}*/
//6.打印倒三角形
/*for(var i=1;i<=5;i++){
for(var j=i;j<=5;j++){
document.write("*");
}
document.write("<br/>");
}*/
//7.使用for循环打印99乘法表
/*for(var i=1;i<=9;i++){
for(var j=1;j<=i;j++){
document.write(j+"*"+i+"="+j*i+" ");
}
document.write("<br />");
}*/
//8.接受用户输入的用户名和密码,若用户名为"admin",密码为"123456",则提示用户登陆成功,负责让 用户一直输入
/*do{
var user=prompt("请输入用户名:");
var miMa=prompt("请输入密码:");
}while(!(user=="admin" && miMa=="123456"))
alert("用户登陆成功");*/
/*for(;;){
var user=prompt("请输入用户名:");
var miMa=prompt("请输入密码:");
if(user=="admin" && miMa=="123456"){
alert("用户登陆成功");
break;
}
}*/
/*while(true){
var user=prompt("请输入用户名:");
var miMa=prompt("请输入密码:");
if(user=="admin" && miMa=="123456"){
alert("用户登陆成功");
break;
}
}*/
/*var user=prompt("请输入用户名:");
var miMa=prompt("请输入密码:");
while(user!=="admin" && miMa!=="123456"){
user=prompt("请输入用户名:");
miMa=prompt("请输入密码:");
}
alert("用户登陆成功");*/
//9.求1-100的累加值,但要求跳过所有个位数为3的数【用continue实现】
var sum=0;
for(var i=1;i<=100;i++){
/*if(i % 10 == 3){
console.log(i);
continue;
}*/
if(parseInt(i/10)==3 || i % 10 == 3){
console.log(i);
continue;
}
sum=sum+i;
}
console.log("除了所有个数为3的1-100的和为:"+sum);
</script>
</head>
<body>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nfNsI79o-1575368198397)(image/jm/47.png)]
<script>
//要求可看文件img里面的循环小组作业
while(true){
var user=prompt("请输入用户名:");
var miMa=prompt("请输入密码:");
if(user=="admin" && miMa=="123456"){
alert("用户登陆成功");
var money=100;
var str = "";
while(true){
var num=+prompt("请输入您要的操作:\n 1.存钱\n 2.取钱 \n 3.显示余额\n 4.退 出");
if(num==1){
var cm=+prompt("请输入您要存的钱数:");
str += " " + money + "+"+cm
money=money+cm;
alert("您目前的余额为"+money);
}else if(num==2){
var qm=+prompt("请输入您要取的钱数:");
if(qm>money){
alert("钱不够");
}else{
str += " " + money + "-"+qm;
money=money-qm;
alert("你目前的余额为:"+money);
}
}else if(num==3){
alert("您的余额为:"+money+"取款记录:"+str);
}else{
break;
}
}
break;
}
}
</script>
11、命名规范和语法操作
1.标识符命名规范
变量、函数的命名必须要有意义
变量的名称一般用名词
函数的名称一般用动词
2.操作符规范
//操作符的左右两侧各保留一个空格
for(var i = 1;i <= 5;i++){
if(i == 3){
break;
}
console.log("我正在吃第" + i + "个包子");
}
3.单行注释规范
for(var i = 1;i <= 5;i++){
if(i == 3){
break;// 单行注释前面有个空格
}
console.log("我正在吃第" + i + "个包子");
4.其他规范
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fthtTZBz-1575368198398)(image/jm/46.png)]
12、数组
目标:
- 能够知道为什么要有数组
- 能够创建数组
- 能够获取数组中的元素
- 能够对数组进行遍历
- 能够给数组新增一个元素
- 能够独立完成冒泡排序的案例
1.数组的概念
数组是指一组数据的集合,其中每个数据被称为元素,在数据中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
//普通变量一次只能存储一个值
var num=10;
//数组一次可以存储多个值
var arr=[1,2,3,4,5];
2.创建数组
-
数组的创建方式有两种:
利用new关键字创建数组
利用数组字面量创建数组
-
利用new关键字创建数组
var 数组名=new Array();//注意:Array(),A要大写。 var arr=new Array();//创建一个新数组 var arr1=new Array(2);//这个2表示数组的长度为2,是两个空的数组元素 var arr2=new Array(2,3);//等价于[2,3],这样写表示里面有两个元素为2和3; //添加元素 var arr=new Array(); arr[0]=2; arr[1]=3; //获取元素 console.log(arr[0]);
-
利用数组字面量创建数组
//1.使用数组字面量创建空的数组 var 数组名=[]; //2.使用数组字面量方式创建带初始值的数组 //数组中的数据我们称为数组元素。 var 数组名=["小红",“小明”,“小华”];//每个元素要用逗号隔开
注意:数组的字面量是方括号[],声明数组并赋值成为数组的初始化,这种字面量方式也是我们以后最多使用的方式。
-
数组元素的类型可以存放任意类型的数据,例如:字符串、数字、布尔值等。
var arr=[1,“小哦”,true];
3.获取数组中的元素
-
数组的索引
索引(下标):用来访问数组元素的序号(数组下标从0开始);
var arr=["小白",”小红“,”小黄“,‘小明’]; //索引号:0 1 2 3
数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过”数组名[索引]“的形式来获取数组中的元素。
这里的访问就是获取得到的意思
//定义数组 var arr=[1,2,3]; //获取数组中为2的元素 console。log(arr[1])
var arr=["小明","小花","小强"]; //获取元素 console.log(arr[0]);//返回结果小明 console.log(arr[1]);//返回结果小花 console.log(arr[2]);//返回结果小强 console.log(arr[3]);//返回结果undefined,因为没有这个数组元素,所以是undefined
4.遍历数组
遍历:就是把数组中的每个元素从头到尾访问一次(类似我们每天早上的点名)
var arr=["red","blue","green"];
for(var i=0;i<3;i++){
console.log(arr[i]);
}
//案例2
var arr=["关羽","张飞","刘备","诸葛亮","周瑜","大乔","小乔"];
for(var i=0;i<7;i++){
console.log(arr[i]);
}
-
数组的长度
使用”数组名.length“可以访问数组元素的数量(数组长度)。
var arr=["关羽","张飞","刘备","诸葛亮","周瑜","大乔","小乔"]; for(var i=0;i<arr.length;i++){ console.log(arr[i]); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4y5NsUIQ-1575368198399)(image/jm/48.png)]
var arr=[2,6,1,7,4];
var sum=0;
var average=0;
for(var i=0;i<arr.length;i++){
sum=sum+arr[i];
}
average=sum/(arr.length);
console.log(sum);
console.log(average);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Clfs1TZd-1575368198400)(image/jm/49.png)]
var arr=[2,6,1,77,52,25,7];
var max=arr[0];
for(var i=0;i<arr.length;i++){
if(arr[i]>max){
max=arr[i]
}
}
console.log(max);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ekkG7OrF-1575368198401)(image/jm/50.png)]
var str="";
var step="|";
var arr=["red","green","blue","pink"]
for(var i=0;i<arr.length;i++){
str=str+arr[i]+step;
}
console.log(str)
5.数组中新增元素
可以通过修改length长度以及索引号增加数组元素
-
通过修改length长度新增数组元素
可以通过修改length长度来实现数组扩容的目的,length属性是可读性的。
var arr=["red","blue","green","pink"]; arr.length=7; console.log(arr); console.log(arr[4]);//undefined console.log(arr[5]);//undefined console.log(arr[6]);//undefined 其中索引号是4、5、6的空间没有给值,就是声明变量没有给值,默认值就是undefined
-
通过改变索引号新增数组元素
var arr=["red","blue","green","pink"]; arr[4]="yellow"; console.log(arr); //返回结果red,blue,green,pink,yellow
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dg00ZXXv-1575368198402)(image/jm/51.png)]
var arr=[]; for(var i=0;i<10;i++){ arr[i]=i+1; } console.log(arr);
6.数组案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fv5HtPZI-1575368198403)(image/jm/52.png)]
//方法一
var arr=[2,0,6,1,77,0,52,0,25,7];
var arr1=[];
var j=0;
for(var i=0;i<arr.length;i++){
if(arr[i]>10){
arr1[j]=arr[i];
j++;
}
}
console.log(arr1);
//方法二
var arr=[2,0,6,1,77,0,52,0,25,7];
var arr1=[];
for(var i=0;i<arr.length;i++){
if(arr[i]>10){
arr1[arr1.length]=arr[i];
}
}
console.log(arr1);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-knwnSZZM-1575368198404)(image/jm/54.png)]
var newArr=[];
var arr=["red","green","blue","pink","purple"];
for(var i=arr.length-1;i>=0;i--){
newArr[newArr.length]=arr[i];
}
console.log(newArr);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ksSMELWi-1575368198404)(image/jm/55.png)]
var arr=[5,4,3,2,1];
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr.length-i-1;j++){
if(arr[j]<arr[j+1]){
var temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
console.log(arr);
13、函数
目标:
- 能够说出为什么需要函数
- 能够根据语法书写函数
- 能够根据需求封装函数
- 能够说出形参和实参的传递过程
- 能够使用函数的返回值
- 能够使用arguments获取函数的参数
1.函数的概念
在js里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。
虽然for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用js中的函数。
函数就是封装了一段可以被重复执行调用的代码块,目的:就是让大量代码重复使用。
2.函数的使用
函数在使用时可以分为两部分:声明函数和调用函数
-
声明函数
function 函数名(){ //函数体代码 }
注意:function是声明函数的关键字,必须小写;由于函数一般是为了实现某个功能才定义的,所以通常我们将函数名命名为动词,比如getSum
-
调用函数
函数名();//通过调用函数名来执行函数体代码
注意:调用的时候千万要记得添加小括号
口诀:函数不调用,自己不执行。
<script>
function sayHi(){
console.log("你好--");
}
sayHi();
</script>
-
函数的封装
函数的封装就是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
简单理解:封装类似于将电脑配件整合组装到机箱中(类似快递打包)
//计算1-100的累加和 function getSum(){ var sum=0; for(var i=1;i<=100;i++){ sum=sum+i; } console.log(sum); } getSum();
小结:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pbgooFrD-1575368198405)(image/jm/56.png)]
3.函数的参数
-
形参和实参
在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该参数时,同样也需要传递相应的参数,这些参数被称为实参。
注意:函数的参数可以有,也可以没有,个数不限
/*function 函数名(形参1,形参2...){ } 函数名(实参1,实参2...)*/ 例子: function cook(aru){// 形参是接受实参的 aru=“酸辣土豆丝”,形参相当于一个变量 console.log(aru) } cook("土豆丝");
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mMrZvMrN-1575368198406)(image/jm/57.png)]
参数的作用:在函数内部某些值不能固定,我们可以根据通过参数在调用函数时传递不同的值进去。
//案例1.利用函数求两个数的和
function getSum(num1,num2){
console.log(num1+num2);
}
getSum(1,2);//3
getSum(23,2);//25
//利用函数求任意两个数的和
function getSum(start,end){
var sum=0;
for(var i=start;i<=end;i++){
sum=sum+i;
}
console.log(sum);
}
getSum(1,10);//55
getSum(1,100);//5050
-
函数形参和实参个数不匹配问题
参数个数 说明 实参个数等于形参个数 输出正常结果 实参个数多于形参个数 只取到形参的个数 实参个数小于形参个数 多的形参定义为undefined,结果为NaN. function sum(num1,num2) console.log(num1+num2); } sum(100,200);//输出正常结果 sum(100,200,300);//只取到形参的个数 sum(200);//多的形参定义为undefined,结果为NaN.
4.函数的返回值
-
return语句
有的时候,我们会希望函数将值返回给调用者,此时通过使用return语句就可以实现
(1)函数是做某件事或者实现某种功能
function cook(aru){ console.log(aru); } cook("米饭");
(2)函数的返回值语法格式
function 函数名(){
return 需要返回的结果;
}
函数名();
注意:
- 我们函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名(),通过return实现
- 只要函数遇到return就把后面的结果返回给函数的调用者,函数名()=return后面的结果。
//例1
function getResult(){
return 666;
}
getResult();//getResult()=666
console.log(getResult());
//例2
function cook(aru){
return aru;
}
console.log(cook("大肘子"));
//求任意两个数的和
function getSum(num1,num2){
return num1+num2;
}
console.log(getSum(2,3));
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-onmzgjQb-1575368198407)(image/jm/58.png)]
function getMax(num1,num2){
/*if(num1>num2){
return num1
}else{
return num2;
}*/
return num1>num2 ? num1:num2
}
console.log(getMax(2,3));
console.log(getMax(38,3));
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJ44Whkh-1575368198408)(image/jm/59.png)]
function getMax(arr){
var max=arr[0];
for(var i=0;i<arr.length;i++){
if(arr[i]>max){
max=arr[i];
}
}
return max;
}
var result=getMax([5,2,99,101,67,77]);
console.log(result);
-
return 终止函数
function add(num1,num2){ //函数体 return num1+num2;//注意:return后的代码不执行 alert("我不会被执行,因为前面有return") } var re=add(1,2);//调用函数,传入两个实参,并通过re接收函数返回值 alert(re)
-
return 的返回值
return只能返回一个值,如果用逗号隔开多个值,以最后一个为准。
function fn(num1,num2){
return num1,num2;//返回的结果是最后一个值
}
console.log(fn(1,2));
如果可以想返回多个数,可以return一个数组
function getResult(num1,num2){
return [num1+num2,num1-num2,num1/num2,num1*num2]
}
var re = getResult(2,3);
console.log(re)
-
函数没有return 返回的是undefined
function fn(){ } console.log(fn());//undefined
函数都是有返回值的,如果有return则返回return后面的值,如果没有return则返回undefined。
-
break、continue、return的区别
break:结束当前的循环(如for,while)
continue:跳出本次循环,继续执行下次循环(如for,while)
return:不仅可以退出循环,还能返回return语句中的值,同时还可以结束当前的函数体内的代码。
5.arguments的使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取,在js中,arguments实际上它是当前的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。
arguments展示形式是一个伪数组,因此可以进行遍历,伪数组具有以下特点:
- 具有length属性
- 按索引方式存储数据
- 不具有数组的一些方法,比如push()、pop()
function fn(){
//console.log(arguments);//arguments存储了所有的实参
//console.log(arguments.length);//3
//console.log(arguments[0]);//1
//可以遍历对象
for(var i=0;i<arguments.length;i++){
console.log(arguments[i]);
}
}
fn(1,2,3);
fn(0,1,2,3,4,56);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JD3Ofc7t-1575368198409)(image/jm/60.png)]
function getMax(){
var max=arguments[0];
for(var i=0;i<arguments.length;i++){
if(arguments[i]>max){
max=arguments[i];
}
}
return max;
}
console.log(getMax(1,2,3));
console.log(getMax(1,2,3,55,88,23,56));
6.函数案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NoZ656dN-1575368198410)(image/jm/61.png)]
function reverse(arr){
var newArr=[];
for(var i=arr.length-1;i>=0;i--){
newArr[newArr.length]=arr[i];
}
return newArr;
}
var arr1=reverse([5,4,3,2,1]);
console.log(arr1);
var arr2=reverse(["pink","red","green","yello"]);
console.log(arr2);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c3hMixVr-1575368198410)(image/jm/62.png)]
function sort(arr){
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
var temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
return arr;
}
var arr1=sort([1,4,2,9]);
conse.log(arr1);(image/jm/63.png)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PF2uNkMH-1575368198411)(image/jm/64.png)]
function isRn(year){
//如果是闰年就返回true,否则返回false
var flag=false;
if(year%4==0&&year%100!=0 || year%400==0){
flag=true;
}
return flag;
}
console.log(isRn(2000));//true
console.log(isRn(1999));//false
-
函数可以调用另一个函数
因为每个函数都是独立的代码块,用于完成特殊任务,因此经常会用到函数相互调用的情况。
function fn1(){ console.log(111); fn2(); console.log("fn1); } function fn2(){ console.log(222); console.log("fn2"); } fn1();//111,222,fn2,fn1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7LvCa3kt-1575368198412)(image/jm/65.png)]
function backDay(){
var year=prompt("请输入年份:");
if(isRn(year)){
alert("当前年份的2月份是29天");
}else{
alert("当前年份的2月份是28天");
}
}
backDay();
//判断是不是闰年
function isRn(year){
//如果是闰年就返回true,否则返回false
var flag=false;
if(year%4==0&&year%100!=0 || year%400==0){
flag=true;
}
return flag;
}
7.函数的两种声明方式
-
利用函数关键字自定义函数(命名函数)
function fn(){ } fn();
-
函数表达式(匿名函数)
var 变量名=function(){};
var fun=function(aru){ console.log("我是函数表达式"); console.log(aru); } fun("pink老师");
注意:
- fun是变量名,不是函数名
- 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数
- 函数表达式也可以进行传递参数
14、作用域
目标:
- 能够说出js的两种作用域
- 能够区分全部变量和局部变量
- 能够说出如何在作用域链中查找变量的值
1.作用域
-
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定了这个名字的可用性的代码范围就是这个名字的作用域。**简单来说,作用域就是代码名字(变量)在某个范围内起作用和效果。**作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
-
js的作用域分为两种:全局作用域和局部作用域
全局作用域:整个script标签,或者是一个单独的js文件
局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字只在函数内部起效果和作用。
<script> //全局作用域 var num=10; console.log(num);//10 function fn(){ //局部作用域 var num=20; console.log(num); } fn();//20 </script>
2.变量的作用域
-
变量作用域的分类
在js中,根据作用域的不同,变量可以分为两种:全局变量和局部变量
-
全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
- 全局变量在代码的任何位置都可以使用
- 在全局作用域下var 声明的变量是全局变量
- 特殊情况下,函数内不使用var声明的变量也是全局变量(不建议使用)。
<script> var num=10;//num就是一个全局变量 console.log(num); function fn(){ console.log(num);//10 } fn(); </script>
-
局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
- 局部变量只能在该函数内部使用
- 在函数内部var声明的变量是局部变量
- 函数的形参实际上就是局部变量
<script> function fun(){ var num1=10;//num1就是局部变量,只能在函数内部使用 num2=20; } fun(); console.log(num1);//报错 </script>
-
全局变量和局部变量的区别
全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存。
局部变量:只有函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间。
3.作用域链
- 只要有代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又诞生一个作用域
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链。
<script>
var num=10;
function fn(){//外部函数
var num=20;
function fun(){//内部函数
console.log(num);
}
}
</script>
//案例1:
function f1(){
var num=123;
function f2(){
console.log(num);//遇见这种问题,应该站在目标出发,一层一层的从内往外找。
}
f2();
}
var num=456;
f1();//结果为123
//案例2:
var a=1;
function fn1(){
var a=2;
var b="22";
fn2();
function fn2(){
var a=3;
fn3();
function fn3(){
var a=4;
console.log(a);//a的值为4
console.log(b);//b的值为"22"
}
}
}
fn1();
15、预解析
目标:
- 能够知道解析器运行js分为哪两步
- 能够说出变量提升的步骤和运行过程
- 能够说出函数提升的步骤和运行过程
1.预解析
js代码是由浏览器中js解析器来执行的。js解析器在运行js代码的时候分为两步:预解析和代码执行
- 预解析:js引擎会把js里面所有的var还有function提升到当前作用域的最前面。
- 代码执行: 按照代码书写的顺序从上倒下往下执行
2.变量预解析和函数预解析
预解析分为变量预解析(变量提升)和函数预解析(函数提升)
-
变量提升:就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作。
console.log(num);//最后结果为undefined var num=10; //相当于做了以下代码 //var num=10; //console.log(num); //num=10;
-
函数提升:就是把所有的函数声明提升到当前作用域的最前面,不调用函数。
fun();//报错 var fun=function(){ console.log(22); } //函数表达式调用必须卸载函数表达式的下面 //相当于做了以下代码 //var fun; //fun(); //fun=function(){ // console.log(22); //}
3.预解析案例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script>
//案例1:
var num=10;
function fun(){
console.log(num);
var num=20;
}
fun();//结果为undefined
/*思路解析:
* 在js中执行顺序如下:
* var num;
* function fun(){
* var num;
* console.log(num);//num会找最近的值,最近的num=10因为声明提升没有赋值,因此最 * 后结果为undefined
* num=20;
* }
* num=10;
* fun();
*/
//案例2:
/*var num=10;
function fn(){
console.log(num);
var num=20;
console.log(num);
}
fn();*/
/*思路解析
* 实际上js的代码顺序如下:
* var num;
* function fn(){
* var num;
* console.log(num);//找最近的值,num只是声明没有赋值,因此是undefined
* num=10;
* console.log(num);//最近的num是20,因此结果为20
* }
* num=10;
* fn();
* 因此最后的结果为undefined和20;
*/
//案例3:
/*var a=18;
f1();
function f1(){
var b=9;
console.log(a);
console.log(b);
var a="123";
}*/
/*思路解析:
实际代码执行顺序如下:
var a;
function f1(){
var b;
var a;
b=9;
console.log(a);
console.log(b);
a="123";
}
a=18;
f1();
最后的结果为:a为undefined,b为9
*/
//案例4:
f1();
console.log(c);
console.log(b);
console.log(a);
function f1(){
var a=b=c=9;//相当于var a=9;b=9;c=9;
console.log(a);
console.log(b);
console.log(c);
}
/*思路解析:
实际上的js执行顺序
function f1(){
var a;
a=9;//a有声明有赋值
b=9;//没有声明,直接赋值,属于全局变量
c=9;//没有声明,直接赋值,属于全局变量
console.log(a);//a为9
console.log(b);//函数内部没有b,往全局变量中找,全局变量中的b为9,因此这里的值也是 9
console.log(c);//函数内部没有c,往全局变量中找,全局变量中的b为9,因此这里的值也是 9
}
f1();
console.log(a);//全局变量中没有a,局部变量中的不能在全局变量中使用,因此会报错
console.log(b);//全局变量b等于9,这里的结果也是9.
console.log(c);//全局变量c等于9,这里的结果也是9.
*/
</script>
</head>
<body>
</body>
</html>
16、对象
目标:
- 能够说出为什么需要对象
- 能够使用字面量创建对象
- 能够使用构造函数创建对象
- 能够说出new的执行过程
- 能够遍历对象
1.对象
-
在生活中,对象是一个具体的事物,在js中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如:字符串、数值、数组、函数等。
对象都是由属性和方法组成的。
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H46HTxgL-1575368198413)(image/jm/66.png)]
-
为什么需要对象
保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。如果要保存一个人的完整信息呢就需要用到对象。
js中的对象表达结构更清晰,更强大。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NNJkastq-1575368198414)(image/jm/67.png)]
2.创建对象的三种方式
在js中,现阶段我们可以采用三种方式创建对象(object);
-
利用字面量创建对象
1、对象字面量:就是花括号{}里面包含了表达这个事物(对象)的属性和方法。{里面采取键值对的形式表示
}
(1)键:相当于属性名
(2)值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔值类型、函数类型等)
var obj={};//这样就创建了一个空的对象 var obj={ name:“小明”, age:18, sex:“男”; sayHi:function(){ console.log("hi"); } } //注意:里面的属性或者方法我们采取键值对的形式;多个属性或者方法中间用逗号隔开的;方法冒号后面跟的是一个匿名函数。
2、对象的调用
- 对象里面的属性调用:对象.属性名,这个小点就相当于‘的’,例如:console.log(obj.uname)
- 对象里面属性的另一种调用方式:对象[‘属性名’],注意方括号里面的属性名必须加引号,例如:console.log(obj[‘name’])
- 对象里面的方法调用:对象.方法名(),注意这个方法名字后面一定加括号。例如:obj.sayHi();
<script> var obj={ uname: "小花", age: 15, sex: "女", sayHi: function(){ console.log("hello") } } console.log(obj.uname); console.log(obj["age"]); console.log(obj.sex); obj.sayHi(); </script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6V3QnjDR-1575368198416)(image/jm/68.png)]
var obj1={ name:"可可", type:"阿拉斯加犬", age:5, color:"red", getSkill:function(){ console.log("back"); console.log("showFilm"); } } console.log(obj1.age); console.log(obj1["name"]); obj1.getSkill();
-
利用new Object创建对象
<script> var obj=new Object();//创建了一个新的对象 //添加属性 obj.uname="张三"; obj.age=18; obj.sayHi=function(){ console.log("你好"); } console.log(obj.uname); console.log(obj["age"]); obj.sayHi(); //我们是利用等号=赋值的方法,添加对象的属性和方法 //每个属性和方法之间使用分号结束的 </script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5OMwNJgI-1575368198416)(image/jm/69.png)]
var obj=new Object(); obj.uname="鸣人"; obj.sex="男"; obj.age=19; obj.getSkill=function(){ console.log("影分身术"); } console.log(obj.uname); console.log(obj.sex); console.log(obj["age"]); obj.getSkill();
-
利用构造函数创建对象
构造对象:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋值初始值,它总与new运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装带这个函数里面。
构造函数的语法格式:
function 构造函数名(){ this.属性=值; this.方法=function(){} } new 构造函数名();
注意:
- 构造函数名字首字母要大写
- 我们构造函数不需要return就可以返回结果
- 我们调用构造函数,必须使用new
- 我们只要new 构造函数名(),调用函数就创建一个对象
- 我们的属性和方法前面必须添加this
//创建四大天王的对象,相同的属性:名字、年龄、性别,相同的方法:唱歌 function Star(uname,age,sex){ this.uname=uname; this.age=age; this.sex=sex; this.sing=function(sang){ console.log(sang) } } var ldh=new Star("刘德华",18,"男"); console.log(ldh.uname); console.log(ldh.age); ldh.sing("冰雨"); var zxy=new Star("张学友",30,"男"); console.log(ldh.uname); console.log(ldh.age); ldh.sing("李兰香");
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4wqhuqWJ-1575368198417)(image/jm/70.png)]
function Hero(uname,type,blood){ this.uname=uname; this.type=type; this.blood=blood; this.attack=function(aru){ console.log(aru); } } var lp=new Hero("廉颇","力量型",500); console.log(lp.uname); console.log(lp.type); console.log(lp.blood); lp.attack("近战"); var hy=new Hero("后羿","射手型",100); console.log(hy.uname); console.log(hy.type); console.log(hy.blood); hy.attack("远程");
-
构造函数和对象
构造函数,如Star(),抽象了对象的公共部分,封装到了函数里面,他泛指某一个大类
对象,如new Star(),特指某一个,通过new关键字创建对象的过程我们也称为对象的实例化。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0HftVvoY-1575368198417)(image/jm/71.png)]
//构造函数 明星 泛指的某一大类
function Star(uname,age,sex){
this.uname=uname;
this.age=age;
this.sex=sex;
this.sing=function(sang){
console.log(sang)
}
}
//对象 特指 是一个具体的事物,刘德华=={uname: "刘德华", age: 18, sex: "男", sing: ƒ}
var ldh=new Star("刘德华",18,"男");
console.log(ldh);
-
变量、属性、函数、方法的区别
变量:单独声明赋值,单独存在
属性:对象里面的变量叫做属性,不需要声明,用来描述该对象的特征
函数:单独存在的,通过“函数名()”就可以调用
方法:对象里面的函数称为方法,方法不需要声明,使用‘对象.方法名()’的方式就可以调用,方法用来描述该 对象的行为和功能。
3.new关键字执行过程
- 在内存中创建一个新的空对象
- 让this指向这个新的对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法。
- 返回这个新对象(所以构造函数里面不需要return)
4.遍历对象属性
for…in用于对数组或者对象的属性进行循环操作。
语法格式为:
for(var 变量名 in 对象){
console.log(k);//得到的是属性名
console.log(对象[k]);//例如:obj[k]得到的是属性值
}
var obj={
uname: "小花",
age: 15,
sex: "女",
sayHi: function(){
console.log("hello")
}
}
//遍历对象
for(var k in obj){
/*console.log(k);
console.log(obj[k]);*/
console.log(k+":"+obj[k]);
}
//返回的结果如下:
//uname:小花
//age:15
//sex:女
//sayHi:function(){
// console.log("hello")
// }
5、小结
- 对象可以让代码结构更加清晰
- 对象复杂数据类型object
- 本质:对象就是一组无序的相关属性和方法的集合
- 构造函数泛指某一大类,比如苹果,不管是红色苹果还是绿苹果,都统称为苹果
- 对象实例特指一个事物,比如这个苹果,正在给你们上课的语文老师
- for…in语句用于对对象的属性进行循环操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hc8YmEKw-1575368198418)(image/jm/72.png)]
<script>
//1.创建一个电脑对象,该对象要有颜色、重量、品牌、型号,可以看电影、听音乐、打游戏和敲代码
function Computer(color,weigth,brand,type){
this.color=color,
this.weigth=weigth,
this.brand=brand,
this.type=type,
this.impact=function(can){
console.log(can)
}
}
var c1=new Computer("red","20kg","华为","c21");
console.log(c1);
c1.impact("看电影、听音乐、打游戏和敲代码");
//2.创建一个按钮对象,该对象中需要包含宽、高,背景颜色和点击行为
function Button(weigth,height,bgColor){
this.weight=weigth,
this.height=height,
this.bgColor=bgColor,
this.action=function(click){
console.log(click);
}
}
var b1=new Button("20px","30px","red");
console.log(b1);
b1.action("onclick");
//3.创建一个车的对象,该对象要有重量、颜色、牌子,可以载人、拉货和耕田
function Car(weight,color,type){
this.weight=weight,
this.color=color,
this.type=type,
this.fn=function(can){
console.log(can)
}
}
var car1=new Car("200kg","red","奥迪");
console.log(car1);
car1.fn("载人、拉货和耕田");
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Om7fhjRu-1575368198419)(image/jm/73.png)]
//写一个函数,可以反转任意数组
function reverse(arr){
var newArr=[];
for(var i=arr.length-1;i>=0;i--){
newArr[newArr.length]=arr[i];
}
return newArr;
}
re=reverse([5,4,3,2,1]);
console.log(re);
re1=reverse(["pink","red","yellow","blue"]);
console.log(re1);
//写一个函数,实现对数字数组的排序
function sort(arr){
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
var temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
return arr;
}
var re2=sort([9,6,3,10]);
console.log(re2);//3,6,9,10
var re3=sort([55,8,49,10,100]);
console.log(re3);//8,10,49,55,100
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzC4Vc8I-1575368198420)(image/jm/74.png)]
17、内置对象
目标:
- 能够说出什么事内置对象
- 能够根据文档查询指定API的使用方法
- 能够使用Math对象的常用方法
- 能够使用Date对象的常用方法
- 能够使用Array对象的常用方法
- 能够使用String对象的常用方法
1.内置对象
- js中的对象分为3种:自定义对象、内置对象、浏览器对象。
- 前两个对象是js基础内容,属于ECMAScript,第三个是浏览器对象属于js独有的。
- 内置对象就是指js语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
- 内置对象最大的优点就是帮助我们快速开发
- js提供了多个内置对象:Math、Date、Array、String等
2.查文档
MDA网址:https://developer.mozilla.org/zh-CN/
查询文档的方法须知:
- 查询该方法的功能
- 查询里面参数的意义和类型
- 查看返回值的意义和类型
- 通过demo进行测试
3.Math对象
Math数学对象,不是一个构造函数,所以我们不需要new来调用,而是直接使用里面的属性和方法即可。
//Math.abs();绝对值
console.log(Math.abs(1));//1
console.log(Math.abs(-1);//1
//传入一个非数字形式的字符串或者 undefined/empty 变量,将返回 NaN。传入 null 将返回 0。
console.log(Math.abs("nihao"));//NaN
console.log(Math.abs(null));//0
console.log(Math.abs("1"));//1 会隐型转换
// Math.floor() 地板 向下取整 ,往最小的数取值
console.log(Math.floor(1.9));//1
console.log(Math.floor(1.03));//1
// Math.ceil() 天花板 向上取整
console.log(Math.ceil(1.9));//2
console.log(Math.ceil(1.03));//2
//Math.round() 四舍五入 其他的数字都是四舍五入,.5是特殊的,它是往大了取
console.log(Math.round(1.1));//1
console.log(Math.round(1.5));//2
console.log(Math.round(1.9));//2
console.log(Math.round(-1.1));//-1
console.log(Math.round(-1.5));//-1
console.log(Math.PI);//Math.PI圆周率
//Math.max() 函数返回一组数中的最大值。
console.log(Math.max(3,5,8));//8
//如果有任一参数不能被转换为数值,则结果为 NaN
console.log(Math.max(2,8,"ni"));//NaN
//如果没有参数,则结果为 - Infinity。
console.log(Math.max());//-Infinity
//Math.min() 返回零个或更多个数值的最小值。和最大值的使用方法一样,不过如果没有参数,结果为Infinity。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A30EmZby-1575368198421)(image/jm/75.png)]
var myMath={
PI:3.141592653589793,
max:function(){
var max=arguments[0];
for(var i=0;i<arguments.length;i++){
if(arguments[i]>max){
max=arguments[i];
}
}
return max;
},
min:function(){
var min=arguments[0];
for(var i=0;i<arguments.length;i++){
if(arguments[i]<min){
min=arguments[i];
}
}
return min;
}
}
console.log(myMath.PI);//3.141592653589793
console.log(myMath.max(5,9,6));//9
console.log(myMath.min(5,9,6));//5
Math.random() 随机数方法,返回一个随机的小数,0=<x<1,这个方法的括号里不跟参数
console.log(Math.random());
//得到一个两数之间的随机整数,包括两个数在内
function getRandom(min,max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandom(1,10));
//随机点名
var arr=["小明","小华","小刚","小画","阿美"];
//console.log(arr[0]);
console.log(arr[getRandom(0,arr.length-1)])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8tPzLMQE-1575368198422)(image/jm/76.png)]
function getRandom(min,max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var random=getRandom(1,10);
while(true){
var num=prompt("请输入数字:");
if(num>random){
alert("数字大了,继续猜")
}else if(num<random){
alert("数字小了,继续猜")
}else{
alert("恭喜你,猜对了");
break;
}
}
//拓展作业: 要求用户猜1-50之间的一个数字,但是只有10次机会
function getRandom(min,max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var random=getRandom(1,50);
for(var i=1;i<=10;i++){
var num=prompt("请输入一个数字:");
if(num>random){
alert("你猜大了");
}else if(num<random){
alert("你猜小了");
}else {
alert("你可真厉害,猜对了");
break;
}
}
4.日期对象
(1)Date概述
- Date对象和Math对象不一样,他是一个构造函数,所以我们需要实例化后再使用
- Date实例化用来处理日期和时间
(2)Date()方法的使用
-
获取当前时间必须实例化
var date=new Date(); console.log(date);
-
Date()构造函数的参数
如果括号里面有时间,就返回参数里面的时间,例如日期格式字符串为“2019-5-1”,可以写成new Date(“2019-5-1”);或者new Date(“2019/5/1”)
<script>
//里面不跟参数是返回的当前日期
var date=new Date();
console.log(date);
//括号里跟参数 数字型2019,10,1 字符串型"2019-10-1 17:30:00"
var date=new Date("2019-10-1 17:30:00");
var date1=new Date(2019,10,1);
console.log(date1);//数字型的时间参数会比参数里的月份大一个月,返回的是11月
console.log(date);//用的比较多的还是字符串型的
var date2=new Date("2019/10/11 17:30:00");
console.log(date2);
</script>
(3)日期格式化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ICeSNTfP-1575368198423)(image/jm/77.png)]
var date=new Date();
console.log(date.getFullYear());//返回的是年份2019
console.log(date.getMonth()+1);//月份是0-11,因此在获取月份的时候要加1
console.log(date.getDate());//返回的是几号
console.log(date.getDay());//返回的是星期几 星期1为1,星期天为0
//练习 写一个2019年10月11日 星期五 的案例
var date=new Date();
var year=date.getFullYear();
var month=date.getMonth()+1;
var dates=date.getDate();
var arr=["星期天","星期一","星期二","星期三","星期四","星期五","星期六"]
var day=date.getDay();
console.log("今天是"+year+"年"+month+"月"+dates+"日 "+arr[day]);
var date=new Date();
console.log(date.getHours());//时
console.log(date.getMinutes());//分
console.log(date.getSeconds());//秒
//要求封装一个时分秒的函数,格式为08:08:08
function getTimer(){
var date=new Date();
var h=date.getHours();
h=h<10 ? "0"+h : h;
var m=date.getMinutes();
m=m<10 ? "0"+m : m;
var s=date.getSeconds();
s=s<10 ? "0"+s : s;
return h+":"+m+":"+s
}
console.log(getTimer());
(4)时间戳
获取Date总的毫秒数(时间戳),不是当前时间的毫秒数,而是距离1970年1月1日号过了多少毫秒数
共有以下四种方法
//1.通过valueOf() 或者 getTime()
var date=new Date();
console.log(date.valueOf());
console.log(date.getTime());
//2.简单的写法 (最常用的写法)
var date1=+new Date();// +new Date()返回的是总的毫秒数
console.log(date1);
//3.H5新增的 获取总的毫秒数 要考虑兼容性
console.log(Date.now());
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2jetNq3k-1575368198423)(image/jm/78.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CzIS9DkZ-1575368198424)(image/jm/79.png)]
function countDown(time){
var nowTime=+new Date();//返回的是当前总的毫秒数
var inputTime= +new Date(time);//返回的是用户输入时间总的毫秒数
var times=(inputTime-nowTime)/1000;
//剩余时间总的秒数
var d=parseInt(times / 60 / 60/24);//天
d=checkTime(d)
var h=parseInt(times / 60 / 60%24);//时
h=checkTime(h)
var m=parseInt(times/60%60);//分
m=checkTime(m)
var s=parseInt(times%60);//秒
s=checkTime(s)
return d+"天 "+h+":"+m+":"+s;
}
function checkTime(num){
return num = num <10? 0+""+num : num;
}
console.log(countDown("2019-10-11 20:12:00"));
5.数组对象
-
检测是否为数组
1、instanceof 运算符 他可以用来检测是否为数组
2、Array.isArray(参数);H5新增的方法,ie9以上版本支持
var arr=[]; var obj={}; //1、instanceof 运算符 他可以用来检测是否为数组 console.log(arr instanceof Array);//true console.log(obj instanceof Array);//false //2、Array.isArray(参数);H5新增的方法,ie9以上版本支持 console.log(Array.isArray(arr));//true console.log(Array.isArray(obj));//false
-
添加删除数组元素的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MSvdZZDU-1575368198424)(image/jm/80.png)]
(1)往数组中添加元素
push(),往数组的末尾添加一个或者多个元素
-
push是可以给数组追加新的元素
-
push()参数直接写数组元素就可以了
-
push完毕之后,返回的结果是新数组的长度
-
原数组也会发生变化。
var arr=[1,2,3]; /*arr.push(4,5); console.log(arr);//1,2,3,4,5*/ console.log(arr.push(4,5,"red"));//6
unshift(),往数组的前面添加一个或者多个元素
-
unshift()是可以给数组追加新的元素
-
unshift()参数直接写数组元素就可以了
-
unshift()完毕之后,返回的结果是新数组的长度
-
原数组也会发生变化。
var arr1=[2,3]; /*arr1.unshift("你好",5); console.log(arr1);//"你好,5,2,3"*/ console.log(arr1.unshift("你好",5));//5 返回的是改变后的数组长度
(2)删除数组元素
pop(),删除数组最后一个元素
-
pop()是可以删除数组最后一个元素
-
pop()括号里面没有参数
-
pop()完毕之后,返回的结果是删除的那个元素
-
原数组也会发生变化
var arr=["red",1,3,4,"blue"]; console.log(arr);//red,1,3,4,blue //arr.pop(); console.log(arr.pop());//返回的是blue console.log(arr);//red,1,3,4"
shift(),删除数组第一个元素
- shift()是可以删除数组第一个元素
- pop()括号里面没有参数
- pop()完毕之后,返回的结果是删除的那个元素
- 原数组也会发生变化
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QQh0PdQW-1575368198425)(image/jm/81.png)]
var arr=[1500,1200,2000,2100,1800];
var newArr=[];
for(var i=0;i<arr.length;i++){
if(arr[i]<2000){
newArr.push(arr[i])
}
}
console.log(newArr);//"1500,1200,1800"
-
数组排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-033n0Btt-1575368198426)(image/jm/82.png)]
//reverse
var arr=["red","blue","green","pink"];
arr.reverse();
console.log(arr);//pink,green,blue,red
//sort()
var arr=[4,7,13,9,10,28];
arr.sort(function(a,b){
return a-b;//升序
//return b-a;//降序
});
console.log(arr);//4,7,9,10,13,28
-
数组索引方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I73120yv-1575368198427)(image/jm/84.png)]
//返回数组元素索引号方法 ,indexOf(数组元素)作用就是返回该数组元素的索引号
//他只返回第一个满足条件的索引号
//如果着不带元素,则返回-1
var arr=["red","green","blue","pink"];
console.log(arr.indexOf("blue"));//2
console.log(arr.indexOf("yellow"));//-1
//返回数组元素索引号方法,lastIndexOf(数组元素)作用就是返回该数组元素的索引号,从后往前找
var arr=["red","green","blue","pink","blue"];
console.log(arr.lastIndexOf("blue"));//4
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7H3NIKry-1575368198427)(image/jm/85.png)]
<script>
function unique(arr){
var newArr=[];
for(var i=0;i<arr.length;i++){
if(newArr.indexOf(arr[i]) === -1){
newArr.push(arr[i]);
}
}
return newArr;
}
var demo=unique(["c","a","z","a","x","a","x","c","b"]);
console.log(demo);//c,a,z,x,b
</script>
-
数组转换成字符串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-frcSY3zH-1575368198428)(image/jm/86.png)]
//1.toString()
var arr=[3,4,5];
console.log(arr.toString());//"3,4,5"
//2.join("分隔符"),如果没有分隔符则默认分隔符为逗号
var arr=["red","blue","pink"];
console.log(arr.join("|"));//"red|blue|pink"
console.log(arr.join("&"));//red&blue&pink
console.log(arr.join("@"));//red@blue@pink
-
数组其他的常用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eboyhp5R-1575368198429)(image/jm/87.png)]
concat():可以连接2个或者多个数组,并将新的数组返回
该方法不会对原数组产生影响
语法:
第一数组名.concat(第二个数组名,第三个数组名,"也可以是元素")
//创建一个数组
var arr=["孙悟空","猪八戒"];
var arr2=["白骨精","玉兔精"];
var arr3=["二郎神","太上老君"];
console.log(arr.concat(arr2,arr3,"牛魔王"));//"孙悟空,猪八戒,白骨精,玉兔精,二郎神,太上老 君,牛魔王"
splice()
可以删除数组中的指定元素
使用splice会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回。
参数:
第一个:表示开始位置的索引
第二个:表示删除的数量
第三个以及以后:可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边。
arr=["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
console.log(arr);//孙悟空,猪八戒,沙和尚,唐僧,白骨精
result=arr.splice(1,2,"牛魔王","铁扇公主","红孩儿");
console.log(arr);//孙悟空,牛魔王,铁扇公主,红孩儿,唐僧,白骨精
console.log(result);//猪八戒,沙和尚
slice()
可以用来从数组中提取选定元素
该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回
参数:
1.截取开始的位置的索引,包含开始索引
2.截取结束的位置的索引,不包括索引
第二个参数可以省略不写,此时就会截取从开始索引往后的所有元素
索引可以传递一个负值,如果传递一个负值,则从后往前计算,如
-1 就是相当于倒数第一个
-2就相当于倒数第二个
后面以此类推
var arr=["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
var result=arr.slice(0,2);
console.log(result);//猪八戒,沙和尚
result=arr.slice(2);
console.log(result);//沙和尚,唐僧,白骨精,如果只填一个参数,那么就是默认从这个位置往后截取
result=arr.slice(1,-2)
console.log(result);//猪八戒,沙和尚
6.字符串对象
-
基本包装类型
为了方便操作基本数据类型,js还提供了三个特殊的引用类型:string、number、boolean。
基本数据类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法
var str="andy"; console.log(str.length);//4
按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js会把基本数据类型包装成为复杂数据类型,其执行过程如下:
//1。生成临时变量,把简单类型包装为复杂数据类型 var temp=new string("andy"); //2.赋值给我们声明的字符变量 str=temp; //3.销毁临时变量 temp=null;
-
字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
var str="abc"; str="hello"; console.log(str); //当重新给str赋值的时候,常量abc不会被修改,依然在内存中 //重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变 //由于字符串的不可变,在大量的拼接字符串的时候会有效率问题,因为这个需要花费大量的时间来显示不断的开辟新的空间
-
根据字符串返回位置
字符串所有的方法,都不会修改字符串本身,操作完成会返回一个新的字符串。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MsGHUZQK-1575368198430)(image/jm/88.png)]
<script> var str="andy"; console.log(str.length);//4 var str="改革春风吹满地,春天来了"; console.log(str.length);//12 //str.indexOf("要查找的字符",起始的位置) console.log(str.indexOf("春"));//2 console.log(str.indexOf("春",4));//8 第2个参数4是代表从4的位置开始往后查找 console.log(str.lastIndexOf("春"));//8 console.log(str.lastIndexOf("春",6));//2 </script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aq03fe3i-1575368198431)(image/jm/89.png)]
//案例 求o出现的位置和次数 var str="abcoefoxyozzopp"; var index=str.indexOf("o");//3 var num=0; while(index !== -1){ console.log(index); num++; index=str.indexOf("o",index+1); } console.log("o出现的次数为:"+num);//4
-
根据位置返回字符(重点)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RMMzaVKQ-1575368198431)(image/jm/90.png)]
//charAt(),根据索引查找字符 var str="andy"; console.log(str.charAt(3));//y console.log(str.charAt(0));//a //charCodeAt() 根据索引号查找字符编码 console.log(str.charCodeAt(0));//97 //str[索引号] 根据索引查找字符 h5新增 和charAt()一样 console.log(str[2]);//d
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LuS1EIs4-1575368198432)(image/jm/91.png)]
<script> //求一下字符串中出现次数最多的字符 var str="abcoefoxyozzopp"; var o={}; for(var i=0;i<str.length;i++){ var chars=str.charAt(i);//chars字符串中的每一个字符 if(o[chars]){//o[chars]==o.a o[chars]++;//o.a=o.a+1 }else{ o[chars]=1; } } console.log(o); //遍历对象 var max=0; var ch=""; for(var k in o){ console.log(o[k]); if(o[k]>max){ max=o[k]; ch=k; } } console.log(max); console.log("出现次数最多的字符"+ch); </script>
-
字符串操作方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OrN8ZEAx-1575368198432)(image/jm/92.png)]
var str="andy"; var str1="red"; console.log(str.concat(str1));//andyred //substr("开始的位置","截取的个数") var str="abcdcef"; console.log(str.substr(0,2));//ab
-
替换字符串和转换为数组方法
<script> //replace("要替换的字符","替换成的字符"),替换原来的字符 var str="andy"; console.log(str.replace("a","b"));//"bndy" //案例:var str="abcoefoxyozzopp";把字符中的o都换成* var str1="abcoefoxyozzopp"; while(str1.indexOf("o") !== -1){ str1=str1.replace("o","*"); } console.log(str1); //split("分隔符")把字符串转换为数组;还有个前面学过的join("分隔符")数组转换为字符串 var str2="red,pink,bule"; //var arr=str2.split(",") console.log(str2.split(",")); //console.log(Array.isArray(arr)); var str3="red&pink&bule"; console.log(str3.split("&"));// ["red", "pink", "bule"] //toUpperCase();小写转换为大写; var str4="abcde"; console.log(str4.toUpperCase()); //str4.toLowerCase();大写转换为小写 var str5="ABCDEF"; console.log(str4.toLowerCase()); </script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QSiQqgdb-1575368198433)(image/jm/93.png)]
<script> var str="abaasdffggghhjjkkgfdsssss3444343"; //字符串的长度 console.log("字符串的长度为:"+str.length); //取出指定位置的字符,如:0,3,5,9等 console.log(str.charAt(0)); console.log(str.charAt(3)); console.log(str.charAt(5)); console.log(str.charAt(9)); //查找指定字符是否在以上字符串中存在,如:i,c,d console.log(str.indexOf("i")); console.log(str.indexOf("c")); console.log(str.indexOf("d")); //替换指定的字符,如:g替换成22,ss替换为b等操作方法 /*for(var i=0;i<str.length;i++){ if(str.indexOf("g")!==-1 || str.indexOf("ss")!==-1){ str=str.replace("g","22"); str=str.replace("ss","b"); } } console.log(str);*/ //截取指定开始位置到结束位置的字符串,如截取1-5,2-8的字符串 console.log(str.substr(1,5)); console.log(str.substr(2,8)); //找出以上字符串中出现次数最多的字符和出现的次数 </script>
-
18、简单类型和复杂类型
19、Web APIS
二、DOM文档对象模型
目标:
- 能够说出什么是DOM
- 能够获取页面元素
- 能够给元素注册事件
- 能够操作dom元素的属性
- 能够创建元素
- 能够操作dom节点
1、DOM简介
-
什么是DOM
文档对象模型(简称DOM),是w3c组织推荐的处理可扩展标记语言(html或者xhtml)的标准编程接口。
w3c已经定义了一系列的dom接口,通过这些dom接口可以改变网页的内容、结构和样式。
-
dom树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aaU8cVnX-1575368198433)(image/jm/94.png)]
文档:一个页面就是一个文档,dom中使用documents表示
元素:页面中的所有标签都是元素,dom中使用element表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),dom中使用node表示。
dom把以上内容都看做成是对象。
2、获取元素
-
如获取页面元素
dom在我们实际开发中主要用来操作元素的。
获取页面中的元素可以使用以下集中方式:
- 根据id获取
- 根据标签名获取
- 通过html5新增的方法获取
- 特殊元素获取
-
根据id获取
使用getElementById()的方法可以获取带有id的元素对象。
<body> <div id="time">2019-9-9</div> <script> //1.参数id是大小写敏感的字符串 //2.返回的是一个元素对象 var timer=document.getElementById("time"); console.log(timer); console.log(typeof timer);//object //console.dir打印我们返回的元素对象 更好的产看里面的属性和方法 console.dir(timer); </script> </body>
-
根据标签名获取
使用getElementsByTagName(’标签名‘)方法可以返回带有指定标签名的对象的集合。
注意:
1.因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历
2.得到的元素是动态的。
//通过标签名获取 //返回的是获取元素的对象集合,以伪数组的形式存储的 var lis=document.getElementsByTagName("li"); console.log(lis[0]); //我们想要打印里面的元素可以通过遍历的方式 for(var i=0;i<lis.length;i++){ console.log(lis[i]); }
还可以获取某个元素(父元素)内部所有指定标签名的子元素
element.getElementsByTagName(”标签名’)
注意:父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包括父元素。
var ol=document.getElementById("ol"); var olis=ol.getElementsByTagName("li"); console.log(olis);
-
通过HTML5新增的方法获取
document.getElementsByClassName(“类名”);//根据类名返回元素对象集合
document.querySelector(‘选择器’);//根据指定选择器返回第一个元素对象,切记,里面的选择器需要加符号,如: .box #nav等
document.querySelectorAll(’选择器‘);//根据指定选择器返回的所有元素的对象集合。
<div class="box">盒子1</div> <div class="box">盒子</div> <div id="nav"> <ul> <li>首页</li> <li>产品</li> </ul> </div> <script> //getElementsByClassName(字符串类名) var boxs=document.getElementsByClassName("box"); console.log(boxs); var firstBox=document.querySelector(".box"); console.log(firstBox) //querySelector(选择器) var nav=document.querySelector("#nav"); console.log(nav); var li=document.querySelector("li"); console.log(li); //querySelectorAll(选择器) var allBox=document.querySelectorAll(".box"); console.log(allBox); var lis=document.querySelectorAll("li"); console.log(lis); </script>
-
获取特殊元素(body,html)
获取body元素:document.body;//返回body元素对象
获取html元素:document.documentElement;//返回html元素对象
<script> //获取body元素 var bodyEle=document.body; console.log(bodyEle); //获取html元素 var htmlEle=document.documentElement; console.log(htmlEle) </script>
3、事件基础
-
事件概述
js是我们有能力创建动态页面,而事件可以被js侦测到的行为。
简单理解:触发–响应机制
网页中的每个元素都可以产生某些可以触发js的事件,例如:我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。
-
事件三要素
事件是有三部分组成:事件源、事件类型、事件处理程序,我们把这三个部分成为事件三要素。
事件源: 事件被触发的对象
事件类型:如何触发、什么事件,比如是鼠标点击还是鼠标经过
事件处理程序:通过一个函数赋值的方式完成
<button>唐伯虎</button> <script> var btn=document.querySelector("button"); btn.onclick=function(){ alert("点我干啥"); } </script>
-
执行事件的步骤
获取事件源
注册事件(绑定事件)
添加事件处理程序(采取函数赋值形式)
<div>123</div> <script> //获取事件源 var div=document.querySelector("div"); //绑定事件 //div.onclick //添加事件处理程序 div.onclick=function(){ console.log("你点我了"); } </script>
-
常见的鼠标事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxoKQy5e-1575368198434)(image/jm/99.png)]
-
4、操作元素
js的DOM操作可以改变网页内容、结构和样式,我=我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性
(1).改变元素内容
element.innerText
从起始位置到终止的内容,但它去掉html标签,同时空格和换行也会去掉
element.innerHTML
从起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行。
<button>显示当前系统时间</button>
<div>某个时间</div>
<p>123</p>
<script>
var btn=document.querySelector("button");
var div=document.querySelector("div");
btn.onclick=function(){
//div.innerHTML="2019-10-17";
div.innerText=getDate();
}
function getDate(){
var date=new Date();
var year=date.getFullYear();
var month=date.getMonth()+1;
var dates=date.getDate();
var arr=["星期天","星期一","星期二","星期三","星期四","星期五","星期六"]
var day=date.getDay();
return "今天是: "+year+"年"+month+"月"+dates+"日 "+arr[day];
}
//元素也可以不加事件
var p=document.querySelector("p");
p.innerText=getDate()
</script>
innerHTML和innerText区别的代码验证
<div></div>
<p>
我是文字
<span>123</span>
</p>
<script>
var div=document.querySelector("div");
//innerText不识别html标签 不保存空格和换行 非标准
//div.innerText="<strong>你好</strong>";//"<strong>你好</strong>"
//innerHTML识别标签 保存空格和换行 w3c标准
div.innerHTML="<strong>你好</strong>";//你好(加粗版的你好)
var p=document.querySelector("p");
//innerText和innerHTML可读写的,可以获取元素里面的内容
console.log(p.innerText);//我是文字 123
console.log(p.innerHTML);
/*我是文字
<span>123</span>*/
</script>
(2).常用元素的属性操作
1. innerText、innerHTML改变元素内容
2. src href
3. id alt title
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vob5j6q2-1575368198435)(image/jm/95.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
img{
width:500px;
height:300px;
}
</style>
</head>
<body>
<img src="img/sw.png" />
<div>哈喽,上午好呀,加油</div>
<script>
//获取元素
var img=document.querySelector("img");
var div=document.querySelector("div");
//使用内置对象date获取时间
var date=new Date();
var h=date.getHours();
//使用if 分支语句进行时间判断
if(h<12){
img.src="img/sw.png";
div.innerHTML="哈喽,上午好呀,加油";
}else if(h<18){
img.src="img/zw.png";
div.innerHTML="哈喽,中午好呀,好好干";
}else{
img.src="img/ws.png";
div.innerHTML="哈喽,晚上好呀,早睡明天见";
}
</script>
</body>
</html>
(3).表单元素的属性操作
利用dom可以操作如下表单元素的属性
type、value、checked、selected、disabled
<button>按钮</button>
<input type="text" value="请输入内容">
<script>
var btn=document.querySelector("button");
var input=document.querySelector("input");
btn.onclick=function(){
//表单里面的值是通过value来改变的
input.value="被点击了";
//如果想把哪个表单禁用,不能点击 disabled=true就可以
//btn.disabled=true
this.disabled=true
// this指的是事件函数的调用者,此时的this就是btn
}
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7D9uK7ky-1575368198435)(image/jm/96.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
.box{
width:400px;
border-bottom: 1px solid red;
margin:100px auto;
position:relative;
height:40px;
}
.box input{
width:350px;
height:38px;
outline: none;
border: 0;
}
.box img{
width:40px;
height: 40px;
position: absolute;
right:0;
top:2px;
}
</style>
</head>
<body>
<div class="box">
<label for="">
<img src="img/close.png"/>
</label>
<input type="password"/>
</div>
<script>
var img=document.querySelector("img");
var input=document.querySelector("input");
var flag=0;
img.onclick=function(){
if(flag==0){
img.src="img/up.png";
input.type="text";
flag=1;
}else{
img.src="img/close.png";
input.type="password";
flag=0;
}
}
</script>
</body>
</html>
(4).样式属性操作
women可以通过js修改元素的大小、颜色、位置等样式
-
1. element.style 行内样式操作 2. element.className 类名样式操作 这两种方法的区别: element.style用于样式比较少后者功能简单的情况下使用 element.className 用于样式比较多或者功能复杂的情况,而且class因为是个保留字,因此使用className来操作元素类名属性;此属性会直接更改元素的类名,会覆盖原先的类名,如果想要保留之前的类名可以使用多类名的形式写。
注意:
1.js里面的样式采取驼峰命名法,比如:backgroundColor fontSize
2.js修改style样式操作,产生的是行内样式,css权重比较高
- element.style 行内样式操作示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:200px;
height:200px;
background-color: pink;
margin:100px auto;
}
</style>
</head>
<body>
<div></div>
<script>
var div=document.querySelector("div");
div.onclick=function(){
div.style.width="500px";
div.style.backgroundColor="purple";
}
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QlZeNWss-1575368198436)(image/jm/97.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:150px;
height:150px;
margin:100px auto;
/*background-color: pink;*/
position: relative;
display: block;
}
.close{
width:30px;
height:30px;
position: absolute;
top:36px;
right:82px;
}
</style>
</head>
<body>
<div>
<img src="img/er.png" />
<img src="img/an.png" class="close"/>
</div>
<script>
var btn=document.querySelector(".close");
var div=document.querySelector("div");
btn.onclick=function(){
div.style.display="none";
}
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5C2x28KQ-1575368198437)(image/jm/98.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
div{
width:250px;
margin:100px auto;
}
li{
list-style: none;
width:24px;
height:24px;
background-color: red;
float: left;
margin: 15px;
background: url(img/jing.png) no-repeat;
}
</style>
</head>
<body>
<div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
var lis=document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
var index=i*44
lis[i].style.backgroundPosition="0 -"+index+"px";
}
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iBinLBoG-1575368198438)(image/jm/100.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
div{
width:550px;
height:36px;
border: 1px solid red;
margin:100px auto;
position: relative;
}
div input{
width:490px;
height:32px;
border: none;
outline: none;
padding-left:5px;
color:#ccc;
font-size: 12px;
}
button{
width:56px;
height:36px;
background-color: red;
position:absolute;
right:0;
top:0;
border:0;
outline: none;
color: #fff;
}
</style>
</head>
<body>
<div>
<input type="text" value="手机">
<button>搜索</button>
</div>
<script>
var input=document.querySelector("input");
input.onfocus=function(){
if(this.value==="手机"){
this.value="";
}
this.style.fontSize="16px";
this.style.color="#000";
}
input.onblur=function(){
if(this.value===""){
this.value="手机";
}
this.style.fontSize="12px";
this.style.color="#ccc";
}
</script>
</body>
</html>
-
element.className 类名样式操作
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> div{ width:300px; height:300px; margin:100px auto; background-color: pink; } .change{ width:500px; height:500px; background-color: purple; font-size: 20px; font-weight: 700; } </style> </head> <body> <div>文字</div> <script> var div=document.getElementsByTagName("div")[0]; div.onclick=function(){ this.className="change"; //如果想要保留之前的类名,可以可以写成多类名的形式 //this.className="first change"; } </script> </body> </html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jBd9hqKR-1575368198439)(image/jm/101.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin: 0;
}
input{
margin-left:5px;
}
.message{
display: inline-block;
font-size: 12px;
color: #ccc;
background: url(img/true.png) no-repeat left center;
padding-left:20px;
}
.change{
color:red;
background-image: url(img/false.png);
}
.right{
color:green;
background-image: url(img/right.png);
}
</style>
</head>
<body>
<div>
<input type="password" value=""/>
<p class="message">请输入6-16位密码</p>
</div>
<script>
var input=document.querySelector("input");
var p=document.querySelector("p");
//失去焦点onblur 密码长度表示:input.value.length
input.onblur=function(){
if(this.value.length<6|| this.value.length>16){
p.className="message change";
p.innerHTML="您输入的位数不对"
}else{
p.className="message right";
p.innerHTML="您输入的密码正确";
}
}
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OXI6DWdk-1575368198439)(image/jm/102.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XumiPZgI-1575368198440)(image/jm/103.png)]
//第一个作业
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
input{
outline: none;
color:#999;
}
.change{
border:1px solid pink;
color:#000;
}
.first{
border:1px solid #ccc;
color:#999;
}
</style>
</head>
<body>
<input type="text" value="邮箱/ID手机号">
<script>
var input=document.querySelector("input");
input.onfocus=function(){
if(input.value==="邮箱/ID手机号"){
input.value="";
input.className="change";
}
}
input.onblur=function(){
if(input.value===""){
input.value="邮箱/ID手机号";
input.className="first";
}
}
</script>
</body>
</html>
//第二个作业
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
background-color: rgb(0,0,0,0.6);
text-align: center;
position: relative;
}
.btn{
position:absolute;
right:0;
top:0;
}
</style>
</head>
<body>
<div>
<img src="img/gg.png" class="gg"/>
<img src="img/an.png" class="btn"/>
</div>
<script>
var div=document.querySelector("div");
var btn=document.querySelector(".btn");
btn.onclick=function(){
div.style.display="none";
}
</script>
</body>
</html>
//第三个作业
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
.nav{
width: 80px;
height:40px;
margin: 100px auto;
text-align: center;
font-size:14px;
}
.list{
display: none;
}
li{
list-style: none;
width:78px;
height:35px;
border:1px solid orange;
border-top: none;
line-height: 35px;
}
a{
text-decoration: none;
display: block;
width:100%;
height:100%;
color:#000;
line-height: 40px;
background-color: pink;
}
li:hover{
background-color: orange;
color: #fff;
}
</style>
</head>
<body>
<div class="nav">
<a href="#">微博</a>
<div class="list">
<ul>
<li>私信</li>
<li>评论</li>
<li>@我</li>
</ul>
</div>
</div>
<script>
var a=document.querySelector("a");
var list=document.querySelector(".list");
a.onclick=function(){
this.style.backgroundColor="#ccc";
list.style.display="block";
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button>关灯</button>
<script>
var body=document.body;
var btn=document.getElementsByTagName("button")[0];
var flag=1;
btn.onclick=function(){
if(flag==0){
body.style.backgroundColor="#fff";
btn.innerHTML="关灯";
flag=1;
}else{
body.style.backgroundColor="#000";
btn.innerHTML="开灯";
flag=0;
}
}
</script>
</body>
</html>
(5).排他思想
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qSlzFn7Y-1575368198441)(image/jm/104.png)]
如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的拍他思想。
注意:
-
所有的元素全部清除样式(干掉其他人)
-
给当前元素设置样式(留下我自己)
-
注意顺序不能颠倒,首先干掉其他人,在设置自己
-
代码验证
<body > <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script> //获取元素 var btns=document.getElementsByTagName("button"); //console.log(btns); for(var i=0;i<btns.length;i++){ btns[i].onclick=function(){ //1.先把所有的元素清除样式 for(var i=0; i<btns.length; i++){ btns[i].style.backgroundColor=""; } //2.给当前的元素设置元素 this.style.backgroundColor="pink" } } </script> </body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5C7cRulm-1575368198442)(image/jm/105.png)]
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> *{ padding:0; margin:0; } div{ width:332px; margin:100px auto; } ul{ background-color: #fff; height:50px; padding:2px; } li{ list-style:none; float: left; } img{ width:80px; height:50px; padding-right:2px; } body{ background: url(img/tu1.png) no-repeat center top; } </style> </head> <body > <div> <ul> <li><img src="img/tu1.png"/></li> <li><img src="img/tu2.png"/></li> <li><img src="img/tu3.png"/></li> <li><img src="img/tu4.png"/></li> </ul> </div> <script> //获取元素 var body=document.body; var imgs=document.querySelectorAll("img"); //循环注册事件 for(var i=0;i<imgs.length;i++){ imgs[i].onclick=function(){ //把this.src就是点击图片的路径 console.log(this.src); //把this.src图片的路径给body就可以了 body.style.backgroundImage="url("+this.src+")"; } } </script> </body> </html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCwmY3op-1575368198443)(image/jm/107.png)]
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> table{ margin:100px auto; color:#000; text-align: center; border:1px solid #000; border-collapse:collapse; } th,td{ border-bottom:1px solid #000; } </style> </head> <body> <table cellpadding="10px" cellspacing="0"> <thead> <tr> <th>代码</th> <th>名称</th> <th>最新公布净值</th> <th>累计净值</th> <th>前单位净值</th> <th>净值增长率</th> <th>公布日期</th> </tr> </thead> <tbody> <tr> <td>02344</td> <td>中银证券安进债券A</td> <td>1.023</td> <td>1.035</td> <td>1.545</td> <td>+0.0234%</td> <td>2019-01-11</td> </tr> <tr> <td>02344</td> <td>中银证券安进债券A</td> <td>1.023</td> <td>1.035</td> <td>1.545</td> <td>+0.0234%</td> <td>2019-01-11</td> </tr> <tr> <td>02344</td> <td>中银证券安进债券A</td> <td>1.023</td> <td>1.035</td> <td>1.545</td> <td>+0.0234%</td> <td>2019-01-11</td> </tr> <tr> <td>02344</td> <td>中银证券安进债券A</td> <td>1.023</td> <td>1.035</td> <td>1.545</td> <td>+0.0234%</td> <td>2019-01-11</td> </tr> <tr> <td>02344</td> <td>中银证券安进债券A</td> <td>1.023</td> <td>1.035</td> <td>1.545</td> <td>+0.0234%</td> <td>2019-01-11</td> </tr> </tbody> </table> <script> //获取元素 var trs=document.querySelector("tbody").querySelectorAll("tr"); for(var i=0;i<trs.length;i++){ //绑定鼠标经过事件 trs[i].onmouseover=function(){ //鼠标经过行tr的时候要变颜色 this.style.backgroundColor="pink"; } //绑定鼠标移开事件 trs[i].onmouseout=function(){ //鼠标移开的时候tr要恢复原色 this.style.backgroundColor=""; } } </script> </body> </html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vhzx6M5C-1575368198443)(image/jm/110.png)]
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> table{ margin:100px auto; border-collapse:collapse; } th{ background-color: cadetblue; color:#fff; } </style> </head> <body> <table border="1px" cellpadding="15px" cellspacing="0"> <thead> <tr> <th> <input type="checkbox" id="j_cbAll"/> </th> <th width="100px">商品</th> <th>价钱</th> </tr> </thead> <tbody id="j_tb"> <tr> <td> <input type="checkbox"/> </td> <td>iphone8</td> <td>8000</td> </tr> <tr> <td> <input type="checkbox"/> </td> <td>ipad</td> <td>5000</td> </tr> <tr> <td> <input type="checkbox"/> </td> <td>air</td> <td>2000</td> </tr> <tr> <td> <input type="checkbox"/> </td> <td>watch</td> <td>8000</td> </tr> </tbody> </table> <script> //获取元素 var j_cbAll=document.getElementById("j_cbAll"); var j_tbs=document.getElementById("j_tb").getElementsByTagName("input"); j_cbAll.onclick=function(){ //this.checked代表j_cbAll的选中状态 console.log(this.checked); 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].onclick=function(){ var flag=true; for(var i=0;i<j_tbs.length;i++){ if(!j_tbs[i].checked){ flag=false; break; } } j_cbAll.checked=flag; } } </script> </body> </html>
(6).自定义属性的操作
1.获取属性值
-
element.属性 获取属性值
-
element.getAttribute(“属性”)
-
这两者的区别:
element.属性 获取内置属性值(元素本身自带的属性),比如:id、class、name等
element.getAttribute(“属性”) 只要是获得自定义的属性(标准),是程序员自定义的属性。
<body>
<div id="demo" index="1"></div>
<script>
var demo=document.getElementById("demo");
console.log(demo.id);//demo
console.log(demo.index);//undefined
console.log(demo.getAttribute("id"));//demo
console.log(demo.getAttribute("index"))//1
</script>
</body>
2.设置属性值
- element.属性=“值” 重新赋值 主要设置内置属性值
- element.setAttribute(“属性”,“值”);主要针对于自定义属性
//(1)element.属性="值" 重新赋值
demo.id="nihao";
demo.className="navs";
//(2)element.setAttribute("属性","值");主要针对于自定义属性
demo.setAttribute("index","2");
console.log(demo.getAttribute("index"));//2
demo.setAttribute("class","footer");
3.移除属性
element.removeAttribute(‘属性名’)
demo.removeAttribute("index");
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cvfQa2jW-1575368198444)(image/jm/108.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
ul,li{
padding:0;
margin:0;
}
.tab{
width:988px;
margin:100px auto;
}
ul{
width:988px;
height:40px;
background-color: gainsboro;
border:1px solid #ccc;
}
li{
height:40px;
list-style: none;
float: left;
padding:0 10px;
line-height: 40px;
cursor: pointer;
}
.tab_list .current{
background-color: red;
color:#fff;
}
.tab_con{
padding-top:1px;
}
.item{
display: none;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(5000)</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_con">
<div class="item" style="display: block;">
商品介绍模块
</div>
<div class="item">
规格与包装模块
</div>
<div class="item">
售后保障模块
</div>
<div class="item">
商品评价(5000)模块
</div>
<div class="item">
手机社区模块
</div>
</div>
</div>
<script>
//1.上面的模块选项,点击某一个,当前这一个底色回事红色,其余不变,修改类名的方式
//获取元素
var tab_list=document.querySelector(".tab_list");
var lis=tab_list.getElementsByTagName("li");
var items=document.querySelectorAll(".item");
for(var i=0;i<lis.length;i++){
lis[i].setAttribute("index",i);
lis[i].onclick=function(){
//把其余的li的样式都消除掉class这个类
for(var i=0;i<lis.length;i++){
lis[i].className="";
}
//只留下此时的li的样式
this.className="current";
//2.下面的模块显示
var index=this.getAttribute("index");
//让所有的item的div都不显示
for(var i=0;i<items.length;i++){
items[i].style.display="none";
}
//让对应的item显示出来
items[index].style.display="block";
}
}
</script>
</body>
</html>
(7).h5自定义属性
自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性是为了通过getAttribute(‘属性’)获取。
但是有些自定义很容易引起歧义,不容易判断是元素内置属性还是自定义属性。
h5给我们新增了自定义属性:
-
设置自定义属性
h5规定自定义属性data开头做为属性名并且赋值。
比如
或者使用js设置
element.setAttribute(‘data-index’,‘2’);
-
获取H5自定义属性
兼容性获取 element.getAttribute(‘data-index’);
h5新增 element.dataset.index或者 element.dataset[‘index’] ie11才开始使用
<body>
<div getTime="2" data-index="3" data-list-name="hello"></div>
<script>
var div=document.getElementsByTagName("div")[0];
console.log(div);
console.log(div.getAttribute("getTime"));
console.log(div.getAttribute("data-index"));
div.setAttribute("data-time",20);
//h5新增的获取自定义属性的方法,只能获取到data开头的属性
//dataset是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset["index"]);
console.log(div.dataset.time);
console.log(div.getAttribute("data-time"));
console.log(div.dataset["time"]);
//如果自定义属性有多个链接的单词,我们获取的时候采取驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset["listName"])
</script>
</body>
5、节点操作
(1)为什么学节点操作
获取元素通常使用两种方式:
1.利用dom提供的方法获取元素
- document.getElementById()
- document.getElementsByTagName()
- document.querySelector等
- 逻辑性不强、繁琐
(2)利用节点层级关系获取元素
- 利用父子兄节点关系获取元素
- 逻辑性强,但是兼容性稍差
这两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单
(2)节点概述
网页中的所有的内容都是节点(标签、属性、文本、注释等),在dom中,节点使用node来表示。
HTML DOM树中的所有的节点均可以通过javascript进行访问,所有html元素(节点)均可以被修改,也可以创建或者删除。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
- 元素节点 nodeType为1
- 属性节点 nodeType为2
- 文本节点 nodeType为3(文本节点包括文字、空格、换行等)
我们在实际开发中,节点操作主要操作的是元素节点。
(3)节点层级
利用dom树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
1.父级节点
node.parentNode
- parentNode属性可返回某节点的父节点,注意是最近的一个父节点。
- 如果指定的节点没有父节点则返回null
<div class="demo">
<div class="box">
<span class="erweima">x</span>
</div>
</div>
<script>
//1.父节点 parentNode
var erweima=document.querySelector(".erweima");
//得到的是离他最近的父亲节点(亲爸爸),如果找不到父节点,就返回null
console.log(erweima.parentNode);//box
console.log(erweima.parentNode.parentNode);//demo
</script>
2.子节点
-
parentNode.childNodes(标准)
parentNode.childNodes则包含指定节点的子节点的集合,该集合为即使更新的结合。
注意:返回值包含了所有的子节点,包括元素节点,文本节点等。
如果只想要获得里面的元素节点,则需要专门处理,所以我们一般不提倡使用childNodes。
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]) } }
-
parentNode.children(非标准)
parentNode.children是一个只读属性,返回所有的子元素节点。他只返回子元素节点,其余节点不返回(这个是我们重点掌握的)。
虽然children是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用。
<body>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<ol>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ol>
<script>
//子节点
//(1)dom提供的api方法
var ul=document.getElementsByTagName("ul")[0];
var lis=ul.getElementsByTagName("li");
//或者是这种方法
/*var ul=document.querySelector("ul");
var lis=ul.querySelectorAll("li");*/
//(2)利用子节点的方法 childNodes 所有的子节点包括元素节点和元素节点
console.log(ul.childNodes);
//(3)children 获取多有的子元素 是我们开发中常用的方法
console.log(ul.children);
</script>
</body>
-
parentNode.firstChild 返回的是第一个子节点,找不到则返回null。同样,也是包含所有的节点,比如文本节点和元素节点等。
parentNode.lastChild 返回的是最后一个子节点,找不到则返回null。同样,也是包含所有的节点,比如文本节点和元素节点等。
parentNode.firstElementChild 返回的是第一个子元素节点,找不到则返回null。
parentNode.lastElementChild 返回最后一个子元素节点,找不到则返回null。
注意:firstElementChild 和lastElementChild 这两个方法有兼容性问题,ie9以上才支持。
在实际开发中,.firstChild 和 lastChild 包含其他节点,操作不方便,而firstElementChild和lastElementChild 又有兼容性问题,那么我们应该如何获取第一个元素或者最后一个元素呢,解决方案如下:
- 如果想要第一个元素节点,可以使用parentNode.chilren[0]
- 如果想要获取最后一个元素,可以使用parentNode.chilren[parentNode.chilren.length-1]
<body>
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
<li>我是li5</li>
</ol>
<script>
var ol=document.getElementsByTagName("ol")[0];
//1.firstChild 第一个子节点,不管是文本节点还是元素节点
//lastChild 是最后一个子节点,不管是文本节点还是元素节点
console.log(ol.firstChild);//#text
console.log(ol.lastChild);//#text
//2.firstElementChild 返回的是第一个子元素 lastElementChild是返回的是最后一个子元素
//这两个方法有兼容性问题
console.log(ol.firstElementChild);//<li>我是li1</li>
console.log(ol.lastElementChild);//<li>我是li5</li>
//3.在实际的开发中,运用children 是既没有兼容性问题也会返回一个子元素
console.log(ol.children[0]);//<li>我是li1</li>
console.log(ol.children[ol.children.length-1]);//<li>我是li5</li>
</script>
</body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mjhluAYb-1575368198445)(image/jm/109.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
ul,li,a{
padding:0;
margin:0;
}
li{
list-style: none;
}
a{
text-decoration: none;
}
.nav{
width:500px;
height:30px;
margin:100px auto;
}
.list{
float: left;
position: relative;
}
.list a{
display: block;
width:70px;
height:30px;
line-height: 30px;
text-align: center;
color:#4c4c4c;
font-weight: 400;
font-size:14px;
}
.list a:hover{
background-color: #ccc;
}
.itme{
position: absolute;
left:0;
top: 30px;
display: none;
}
.itme li{
border:1px solid orange;
border-top:none;
}
.itme li a{
background-color: #fff;
}
.itme li a:hover{
background-color: orange;
color:#fff;
}
</style>
</head>
<body>
<ul class="nav">
<li class="list">
<a href="#">微博</a>
<ul class="itme">
<li><a href="#">私信</a></li>
<li><a href="#">评论</a></li>
<li><a href="#">@我</a></li>
</ul>
</li>
<li class="list">
<a href="#">博客</a>
<ul class="itme">
<li><a href="#">博客评论</a></li>
<li><a href="#">未读提醒</a></li>
</ul>
</li>
<li class="list">
<a href="#">邮箱</a>
<ul class="itme">
<li><a href="#">免费邮箱</a></li>
<li><a href="#">企业邮箱</a></li>
<li><a href="#">vip邮箱</a></li>
<li><a href="#">新浪邮箱</a></li>
</ul>
</li>
<li class="list">
<a href="#">网站导航</a>
</li>
</ul>
<script>
var nav=document.getElementsByClassName("nav")[0];
var lis=nav.children;
for(var i=0;i<lis.length;i++){
lis[i].onmouseover=function(){
this.children[1].style.display="block";
}
lis[i].onmouseout=function(){
this.children[1].style.display="none";
}
}
</script>
</body>
</html>
3.兄弟节点
-
node.nextSibling 返回当前元素的下一兄弟节点,找不到则返回null。同样,也是包含所有的节点,比如:文本节点和元素节点。
-
node.previousSibling 返回当前元素的上一个兄弟节点,找不到则返回null。同样,也是包含所有的节点,比如:文本节点和元素节点。
-
node.nextElementSibling 返回的当前元素下一个兄弟节点,找不到则返回null。
-
node.previousElementSibling 返回的当前元素上一个兄弟节点,找不到则返回null。
注意:这3和4这两个方法有兼容性问题,ie9以上才支持。
<body> <p>我是p</p> <div>我是div</div> <span>我是span</span> <script> var div=document.getElementsByTagName("div")[0]; console.log(div); /*1.nextSibling 获取下一个兄弟节点,包括文本节点和元素节点等。 previousSibling 获取上一个兄弟节点,包括文本节点和元素节点等。*/ console.log(div.nextSibling);//#text console.log(div.previousSibling);//#text //nextElementSibling 得到下一个兄弟元素 //previousElementSibling 得到的是上一个兄弟元素。 console.log(div.nextElementSibling);//<span>我是span</span> console.log(div.previousElementSibling);//<p>我是p</p> </script> </body>
如何解决兼容性问题:封装一个兼容性的函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IiTJTVrx-1575368198447)(image/jm/111.png)]
4.创建添加节点
-
创建节点
document.createElement(“tagName”);
此方法创建是由tagName指定的html元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
-
添加节点
node.appendChild(child);
此方法将一个节点添加到指定父节点的子节点列表末尾。类似于css里面的after伪元素。
node.insertBefore(child,指定元素)
此方法将一个节点添加到父节点的指定子节点前面。类似于css里面的before伪元素。
<body> <ul> <li>123</li> </ul> <script> //1.创建元素节点createElement("元素名") var li=document.createElement("li"); //2.添加节点node.appendChild(child),其中node是父级,child是子级 后main追加元素,类 似于数组中的push() var ul=document.querySelector("ul"); ul.appendChild(li); //3。添加节点 node.nsertBefore(child,指定元素);在指定元素前面添加元素 var lili=document.createElement("li"); ul.insertBefore(lili,ul.children[0]); //我们要在页面中添加一个元素,1.创建元素 2.添加元素 </script> </body>
案例:简单版发布留言案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O5ZqsR9m-1575368198449)(image/jm/112.png)]
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> *{ padding:0; margin:0; } textarea{ width:300px; height:100px; outline:none; resize: none; border-color: pink; margin-top: 10px; margin-left: 500px; font-size: 18px; } ul{ margin-top: 20px; margin-left: 500px; } li{ list-style: none; background-color: pink; width: 300px; margin-bottom:10px; padding: 5px; } </style> </head> <body> <textarea></textarea> <button>发布</button> <ul></ul> <script> var text=document.querySelector("textarea"); var btn=document.querySelector("button"); var ul=document.querySelector("ul"); btn.onclick=function(){ if(text.value==""){ alert("请您输入内容"); return false; }else{ //1.创建元素 var li=document.createElement("li"); //现有li然后再赋值 li.innerHTML=text.value; //2,添加元素 //ul.appendChild(li);//在后面追加元素 ul.insertBefore(li,ul.children[0]);//在最前面添加留言 } } </script> </body> </html>
5.删除节点
node.removeChild(child) 此方法从dom中删除一个子节点,返回删除的节点。
<body>
<button>删除</button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光头强</li>
</ul>
<script>
var btn=document.querySelector("button");
var ul=document.querySelector("ul");
btn.onclick=function(){
if(ul.children.length==0){
this.disabled=true;
}else{
ul.removeChild(ul.children[0]);
}
}
</script>
</body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hDGestpR-1575368198450)(image/jm/113.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w4NhzkOd-1575368198451)(image/jm/114.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
textarea{
width:300px;
height:100px;
outline:none;
resize: none;
border-color: pink;
margin-top: 10px;
margin-left: 500px;
font-size: 18px;
}
ul{
margin-top: 20px;
margin-left: 500px;
}
li{
list-style: none;
background-color: pink;
width: 300px;
margin-bottom:10px;
padding: 5px;
}
a{
text-decoration: none;
float: right;
}
</style>
</head>
<body>
<textarea></textarea>
<button>发布</button>
<ul></ul>
<script>
var text=document.querySelector("textarea");
var btn=document.querySelector("button");
var ul=document.querySelector("ul");
btn.onclick=function(){
if(text.value==""){
alert("请您输入内容");
return false;
}else{
//1.创建元素
var li=document.createElement("li");
//现有li然后再赋值
li.innerHTML=text.value+"<a href='#'>删除</a>";
//2,添加元素
//ul.appendChild(li);//在后面追加元素
ul.insertBefore(li,ul.children[0]);//在最前面添加留言
//3.删除元素 ,当前a链接所在的li
var as=document.querySelectorAll("a");
for(var i=0;i<as.length;i++){
as[i].onclick=function(){
//删除的是li a所在的li li就等于this.parentNode
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
</html>
6.复制节点
node.cloneNode() 此方法返回调用该方法的节点的一个副本,也称克隆节点/拷贝节点。
注意:
- 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
- 如果括号里参数为true,则是深拷贝,会复制节点本身以及里面所有的子节点。
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul=document.querySelector("ul");
//1.克隆节点 node.cloneNode() 括号为空或者为false,则是浅拷贝,只复制标签不复制里面的内容。
//2.克隆节点 node.cloneNode() 括号为true,则是深拷贝,既复制标签也复制里面的内容。
var lili=ul.children[0].cloneNode();
var lili=ul.children[0].cloneNode(true);
//2.添加节点
ul.appendChild(lili);
</script>
</body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2xHYSHNu-1575368198452)(image/jm/115.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
table{
border-collapse: collapse;
width:500px;
margin:100px auto;
text-align: center;
}
tr,td{
height:30px;
background-color: #ccc;
}
</style>
</head>
<body>
<table border=1 cellpadding="10px" cellspacing="0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
//1.先准备好学生的数据
var dates=[{
name:"魏璎珞",
subject:"javascript",
score:100
},{
name:"弘历",
subject:"javascript",
score:98
},{
name:"傅恒",
subject:"javascript",
score:99
},{
name:"明玉",
subject:"javascript",
score:96
},{
name:"皇后",
subject:"javascript",
score:96
}];
//2.往tbody里面创建行:有几个人(通过数组的长度)我们就创建几行
var tbody=document.getElementsByTagName("tbody")[0];
for(var i=0;i<dates.length;i++){//外边的for循环的是行
//创建行tr
var tr=document.createElement("tr");
//往tbody里面添加tr
tbody.appendChild(tr);
//3.在行里面创建单元格td,单元格的数量取决于每个对象里面的属性个数,for循环遍历对象,dates[i]
for(var k in dates[i]){//里面的for循环管列
var td=document.createElement("td");
//把对象里面的属性值dates[i][k]赋值给td
td.innerHTML=dates[i][k];
tr.appendChild(td);
}
//4.创建最后的列,也就是有删除的列
var td=document.createElement("td");
td.innerHTML="<a href='javascript:;'>删除</a>";
tr.appendChild(td);
}
//5.给a链接做删除操作
var as=document.getElementsByTagName("a");
for(var i=0;i<as.length;i++){
as[i].onclick=function(){
//点击a链接删除的a所在的td的tr,也就是a的父亲的父亲
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>
</html>
7.三种动态创建元素的区别
- document.write()
- element.innerHtml
- document.createElement()
区别:
-
document.write是直接将内容写入页面的内容流,但是文档流执行完毕,会导致页面全部重绘。
-
innerHtml是将内容写入某个do节点,不会导致页面全部重绘
-
innerHtml创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
-
createElement()创建多个元素效率稍低一点点,但是结构更加清晰
总结:不同浏览器下,.innerHtml效率要比createElement高。
6、DOM重点核心(复习以上学习的dom内容)
文档对象模型(简称dom),是w3c组织推荐的处理可扩展标记语言(html或者是xml)的标准编程接口。
w3c已经定义了一系列的dom接口,通过这些dom接口可以改变网页的内容\结构和样式。
- 对于js,为了能够使js操作html,js就有了一套自己的dom编程接口。
- 对于html,dom使得html形成一颗dom树,包含文档、元素、节点。
- 我们获取过来的dom元素是一个对象(object),所以成为文档对象模型。
关于dom操作,我们主要针对于元素的操作。主要创建、增、删、改、查、属性操作、事件操作。
(1)创建
- document.write
- innerHtml
- createElement
(2)增
- appendChild 增加元素的后面
- insertBefore 增加到元素的前面node.insertBefore(增加的元素名,指定位置)
(3)删
- removeChild
(4)改
主要修改dom的元素属性,dom元素的内容、属性、表单的值等。
- 修改元素属性:src、href、title等
- 修改普通元素内容:innerHtml、innerText
- 修改表单元素:value、type、disabled等
- 修改元素样式:style、className
(5)查
主要获取dom的元素
- dom提供的API方法:getElementById、getElementByTagName
- 提供的新方法: querySelector、 queryAllSelector 有兼容性
- 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibing、NextElementSibing)
(6)属性操作
主要针对于自定义属性。
- setAttribute:设置dom的属性值)
- getAttribute:得到dom的属性值
- removeAttribute移除属性
(7)事件操作
给元素注册事件,采取事件源、时间类型、事件处理程序三要素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q4psVnmZ-1575368198453)(image/jm/99.png)]
7.事件高级
目标:
- 能够写出元素注册事件的两种方式
- 能够说出删除事件的两种方式
- 能够说出dom事件流的三个阶段
- 能够利用事件完成跟随鼠标的案例
- 能够封装阻止冒泡的兼容性函数
- 能够说出事件委托的原理
- 能够说出常用的鼠标和键盘事件
(1)注册事件(绑定事件)
1-1 注册事件概述
给元素添加事件,称为注册事件或者解绑事件。
注册事件有两种方式:传统方式和方法监听注册方式
传统注册方式的特点:
- 利用on开头的事件onclick
- btn.οnclick=function(){}
- 特点:注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面的处理函数
方法监听注册方式的特点:
- w3c标准推荐方式
- addEventListener()它是一个方法
- IE9之前的ie不支持此方法,可使用attachEvent()代替
- 特点:同一个元素同一个事件可以注册多个监听器
- 按注册顺序依次执行
1-2 addEventListener()事件监听方式
eventTarget.addEventListener(type,listener[useCapture])此方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
该方法接受三个参数:
- type:事件类型字符串,比如click、mouseover,注意这里不要带on
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认是false。学完dom事件流后,再进一学习。
1-3 attachEvent 事件监听方式(了解,用于ie9以前的浏览器)
eventTarget.attachEvent(eventNameWithOn,callback)方法将指定的监听器注册到eventTaget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。
该方法接收两个参数:
- eventNameWithOn:事件类型字符串,比如:onclick、onmouseover,这里主要要带on
- callback:事件处理函数,当目标触发事件时回调函数被调用
<body>
<button>传统事件注册方式</button>
<button>方法监听注册方式</button>
<button>ie9 监听方式</button>
<script>
var btns=document.querySelectorAll("button");
//1.传统事件注册方式 没有兼容性 有唯一性
//同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面的处理函数。
btns[0].onclick=function(){
alert("hello");
}
btns[0].onclick=function(){
alert("你好");
}//最后只会弹出你好,把前面的hello覆盖了
//2.事件监听注册方式 有兼容性
//同一个元素同一个事件可以注册多个监听器 ,并且是按顺序执行
btns[1].addEventListener("click",function(){
alert(33);
})
btns[1].addEventListener("click",function(){
alert(222);
})//最后结果是先弹出33.再弹出222
//3.attachEvent
btns[2].attachEvent("onclick",function(){
alert(111);
})
</script>
</body>
1-4 注册事件兼容性方案
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gODZ97fr-1575368198455)(image/jm/116.png)]
(2)删除事件(解绑事件)
删除事件的方式
-
传统注册方式
eventTaget.οnclick=null;
-
方法监听注册方式
eventTaget.removeEventListener(type,,listener[useCapture]);
eventTaget.detachEvent(eventNameWithOn,callback);
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var div=document.querySelectorAll("div");
div[0].onclick=function(){
alert(11);
//传统方式删除事件
div[0].onclick=null;
}
div[1].addEventListener("click",fn);//注意此处的fn不加括号
function fn(){
alert(22);
//2. removeEventListener 删除事件
div[1].removeEventListener("click",fn)
}
div[2].attachEvent("onclick",fn1);
function fn1(){
alert(33);
//3. detachEvent
div[2].detachEvent("onclick",fn1);
}
</script>
</body>
删除事件兼容性解决方案
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mBlkNehn-1575368198456)(image/jm/117.png)]
(3)dom事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程就是dom事件流。
dom事件流分为3个阶段:
1.捕获阶段 2.当前目标阶段 3.冒泡阶段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gkBHLmwM-1575368198457)(image/jm/118.png)]
- 事件冒泡: IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到dom最顶层节点的过程。
- 事件捕获:网景最早提出,由dom最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程。
备注:理解性的记忆如下:
我们向水里仍一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点(最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MafJ3U6t-1575368198457)(image/jm/119.png)]
注意:
- js代码中只能执行捕获或者冒泡其中的一个阶段
- onclick和attachEvent只能得到冒泡阶段
- addEventListener()括号里面第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(不写默认就是false)或者省略,表示事件阶段调用事件处理程序。
- 实际开发中我们很少使用事件捕获,我们更关注事件冒泡
- 有些事件是不会冒泡的,如:onblur、onfocus、onmouseenter、onmouseleave
- 事件冒泡有时候也会带来麻烦,有时候又会帮助很巧妙的做某些事件。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.father{
width:500px;
height:500px;
background-color: pink;
margin:100px auto;
position: relative;
}
.son{
width:200px;
height:200px;
background-color: purple;
position: absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
}
</style>
</head>
<body>
<div class="father">
father
<div class="son">son</div>
</div>
<script>
/*dom 事件流 三个阶段
1.js代码中只能执行捕获或者冒泡其中的一个阶段
2.onclick和attachEvent只能得到冒泡阶段
3.捕获阶段 如果addEventListener第三个参数是true,那么则处于捕获阶段 document-html-body-father-son*/
//1.捕获阶段
/*var son=document.querySelector(".son");
son.addEventListener("click",function(){
alert("son")
},true);
var father=document.querySelector(".father");
father.addEventListener("click",function(){
alert("father")
},true);*/
//冒泡阶段
//如果addEventListener第三个参数是false或者省略,那么则处于son-father-body-html-document
var son=document.querySelector(".son");
son.addEventListener("click",function(){
alert("son")
},false);
var father=document.querySelector(".father");
father.addEventListener("click",function(){
alert("father")
},false);
document.addEventListener("click",function(){
alert("document")
});
</script>
</body>
</html>
(4)事件对象
4-1 什么是事件对象
eventTarget.οnclick=function(event){}
eventTarget.addEventListener('click',function(event){})
//这个event就是事件对象,我们还喜欢写成e或者evt
官方解释:event对象代表时间的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
简单解释:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,他有很多属性和方法。比如:谁绑定了这个事件;鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置;键盘触发事件的话,会得到键盘的相关信息,比如按了哪个键。
4-2 事件对象的使用语法
括号里面event是个形参,系统帮我们设定为事件对象,不需要传递实参进去。
当我们注册事件时,event对象就会被系统自动创建,并一次传递给事件监听器(事件处理函数)。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:100px;
height:100px;
background-color: pink;
}
</style>
</head>
<body>
<div>123</div>
<script>
var div=document.querySelector("div");
/*div.οnclick=function(event){
console.log(event);
}*/
div.addEventListener("click",function(e){
/*e=e||window.event;*/
console.log(event);
})
//1.event 就是一个事件对象,写到我们侦听函数的小括号里面,当形参来看
//2.事件对象只要有了事件才会存在,他是系统给我们自动创建的,不需要我们传递参数
//3.事件对象是我们事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击里面就包含了鼠标的相关信息,
//鼠标坐标等等,如果是键盘事件里面就有包含的键盘事件的信息,比如:判断用户按下了那个键。
//4.这个事件对象我们可以自己命名,比如:event、evt、e
//5.事件对象也有兼容性问题,ie678通过window.event 兼容性的写法e=e||window.event;
</script>
</body>
</html>
4-3 事件对象的兼容性方案
事件对象本身的获取存在兼容问题:
-
标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到
-
在ie6-8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找。
解决方案:
e=e||window.event;
4-4 事件对象的常见属性和方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-db1WoQap-1575368198458)(image/jm/120.png)]
-
this和target的区别:
e.target返回的是触发事件的对象(元素),this返回的是绑定事件的对象,简单记忆:e.target是点击了哪个元素就返回那个元素,this那个元素绑定了这个点击事件,那么就返回谁
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> div{ width:100px; height:100px; background-color: pink; } </style> </head> <body> <div>123</div> <ul> <li>abc</li> <li>abc</li> <li>abc</li> </ul> <script> //常见事件对象的属性和方法 //1. e.target返回的是触发事件的对象(元素),this返回的是绑定事件的对象 //区别:e.target是点击了哪个元素就返回那个元素,this那个元素绑定了这个点击事件,那么就返 回谁 var div=document.querySelector("div"); div.addEventListener("click",function(e){ console.log(e.target); console.log(this); }) var ul=document.querySelector("ul"); ul.addEventListener("click",function(e){ //e.target指向我们点击的那个对象,谁触发了这个事件,我们点击的是li,所以返回的是li console.log(e.target);//点击的li返回的li,target是被点击也就是触发的对象 //我们给ul绑定了事件,那么this就指向ul console.log(this);//点击的是li返回的是ul,是因为this指向的是绑定对象 console.log(e.currentTarget); }) //兼容性的处理方法,可了解 /*div.οnclick=function(e){ e=e||window.event; var target=e.target||e.srcElement; console.log(target); }*/ //了解即可:还有个和this非常相似的属性currentTarget,ie678不认识 </script> </body> </html>
-
e.type和阻止默认行为
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div>123</div> <a href="http://www.baidu.com">百度</a> <form> <input type="submit" value="提交" name="sub"> </form> <script> //返回事件类型 e.type 返回的事件类型不带on var div=document.querySelector("div"); div.addEventListener("click",fn); div.addEventListener("mouseover",fn); div.addEventListener("mouseout",fn); function fn(e){ console.log(e.type); } /*div.οnclick=function(e){ console.log(e.type); }*/ //阻止默认行为 var a=document.querySelector("a"); a.addEventListener("click",function(e){ e.preventDefault(); //dom标准写法 }) //传统的注册方式 /*a.οnclick=function(e){ //普通的浏览器 e.preventDefault()属于方法加括号 e.preventDefault(); //低版本浏览器ie678 e.returnValue是属性,不加括号 e.returnValue; //可兼容性的,只能传统的注册方式可用,不能用于addEventListener,不过有个问题需要注意 就是return后面的代码不执行 return false; alert(11) }*/ </script> </body> </html>
(5)阻止事件冒泡
5-1 阻止事件冒泡的两种方式
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到dom最顶层节点。
事件冒泡本身的特性,会带来好处,也会带来坏处,需要我们灵活掌握。
阻止事件冒泡:
- 标准写法:利用事件对象里面的e.stopPropagation()方法
- 非标准写法:IE6-8利用事件对象cancelBubble属性
//阻止冒泡 stopPropagation() 标准 stop停止 Propagation传播
//非标准 ie678支持的,cancelBubble属性 cancel取消 Bubble泡泡
son.addEventListener("click",function(e){
alert("son");
e.stopPropagation();
//e.cancelBubble=true;//适用于低版本ie
},false);
var father=document.querySelector(".father");
father.addEventListener("click",function(e){
alert("father");
e.stopPropagation();
},false);
5-2 阻止事件冒泡的兼容性解决方案
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TjrHl0Tm-1575368198459)(image/jm/121.png)]
(6)事件委托(代理、委派)
事件冒泡本身的特性,会带来好处,也会带来坏处,需要我们灵活掌握。程序中也有如此场景:
<ul>
<li>知否知否应是绿肥红瘦1</li>
<li>知否知否应是绿肥红瘦2</li>
<li>知否知否应是绿肥红瘦3</li>
<li>知否知否应是绿肥红瘦4</li>
<li>知否知否应是绿肥红瘦5</li>
</ul>
点击每个li都会弹出对话框,以前需要给每个li注册事件。是非常麻烦而且辛苦的,而且访问dom的次数越多,这就会延长整个页面的交互就绪时间。
事件委托:也称为事件代理,在jQuery里面称为事件委派。
事件委托的原理(面试会考):
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理设置影响每个子节点。
在以上案例中,给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器。
事件委托的作用:我们只操作了一次dom,提高了程序的性能。
<body>
<ul>
<li>知否知否应是绿肥红瘦1</li>
<li>知否知否应是绿肥红瘦2</li>
<li>知否知否应是绿肥红瘦3</li>
<li>知否知否应是绿肥红瘦4</li>
<li>知否知否应是绿肥红瘦5</li>
</ul>
<script>
var ul=document.querySelector("ul");
/*ul.addEventListener("click",function(e){
console.log(e.target);
alert(11);
})*/
ul.onclick=function(e){
//console.log(e.target);
//利用排他思想 先把所有的li的颜色都去掉
for(var i=0;i<ul.children.length;i++){
ul.children[i].style.backgroundColor="";
}
e.target.style.backgroundColor="pink";
}
</script>
</body>
(7)常用的鼠标事件
7-1 除了常用的鼠标事件,还有这两个需要了解contextmenu selectstart
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oSATsZMS-1575368198460)(image/jm/99.png)]
-
禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认上下文菜单。
document.addEventListener("contextmenu",function(e){ e.preventDefault(); })
-
禁止鼠标选中(selectstart 开始选中)
document.addEventListener("selectstart",function(e){ e.preventDefault(); })
7-2 鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合,现阶段我们主要用鼠标事件MouseEvent和键盘事件对象keyboardEvent。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pn4YsIOv-1575368198460)(image/jm/122.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
body{
height:3000px;
}
</style>
</head>
<body>
<script>
document.addEventListener("click",function(e){
//1.client 鼠标在可视区的x坐标和y坐标
console.log(e.clientX);
console.log(e.clientY);
//2.page 鼠标在文档页面中的x坐标和y坐标,重点记住这一个
console.log(e.pageX);
console.log(e.pageY);
//3.screen 鼠标在电脑屏幕中的x坐标和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NX4gtyAf-1575368198462)(image/jm/123.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
img{
position:absolute;
top:100px;
left:200px;
}
</style>
</head>
<body>
<img src="img/angle.png"/>
<script>
var img=document.querySelector("img");
//1.mousemove 只要我们鼠标移动1px,就会触发这个事件
//2.核心原理:每次鼠标移动,我们都会获得最新的鼠标坐标,把这个x坐标和y坐标作为图片的top和left 值就可以移动图片
document.addEventListener("mousemove",function(e){
var x=e.pageX;
var y=e.pageY;
/*console.log("x的坐标"+x+"y的坐标"+y);*/
img.style.left=x-64+"px";
img.style.top=y-75+"px";
})
</script>
</body>
</html>
(8)常用的键盘事件
8-1 常用键盘事件
事件除了鼠标触发,还可以使用键盘触发。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4C2zh0hn-1575368198463)(image/jm/124.png)]
注意:
- 如果使用addEventListener不需要加on
- onkeypress和前面2个的区别是,它不识别功能键,比如左右箭头,ctrl 等
- 三个事件的执行顺序是:keydown、keypress、keyup
<script>
/*document.οnkeyup=function(){
console.log("我弹起来了");
}*/
//1.keyup 按键弹起的时候触发
document.addEventListener("keyup",function(){
console.log("我弹起来了");
})
//2.keydown 按键按下的时候触发,能识别功能键,比如ctrl。shfit键
document.addEventListener("keydown",function(){
console.log("我被按下了");
})
//3.keypress 按键按下的时候触发,不能识别功能键,比如ctrl。shfit键
document.addEventListener("keypress",function(){
console.log("我被按了press");
})
//4.三个事件的执行顺序是:keydown-keypress-keyup
</script>
8-2 键盘事件对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G9vPu5b1-1575368198463)(image/jm/125.png)]
注意:onkeyup和onkeydown不区分字母大小写,onkeypress区分字母大小写。在我们实际开发中,我们更多的是用keydown和keyup,它能识别所有的键(包括功能键),而keypress不识别功能键,但是keycode属性区分大小写,返回不同的ASCII值。
<body>
<script>
/*键盘事件对象中的keyCode属性可以得到相应键的ascii码值
1.我们的keyup和keydown事件不区分字母大小写,比如a和A
2.我们的keypress事件区分字母大小写a是97,A是65*/
document.addEventListener("keyup",function(e){
console.log("up:"+e.keyCode);
//console.log(e);
//我们可以利用keycode返回的ascii码值来判断用户按下了哪个键盘
if(e.keyCode===65){
alert("您按下的是a键")
}else{
alert("您按下的是其他键")
}
})
document.addEventListener("keypress",function(e){
console.log("press:"+e.keyCode);
})
</script>
</body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fX5e7woM-1575368198464)(image/jm/126.png)]
<body>
<input type="text">
<script>
//案例要求:当我们按下s键时,光标就定位到搜索框
//核心思想:1.检测用户是否按下了s键,如果按下s键,就把光标定位到搜索框里面
//2.使用键盘事件对象里面的keyCode判断用户按下的是否s键
//3.搜索框获得焦点,使用js里面的focus()方法
var input=document.querySelector("input");
document.addEventListener("keyup",function(e){
if(e.keyCode===83){
input.focus();
}
})
</script>
</body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kghnpR6c-1575368198465)(image/jm/127.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GwsEU6U2-1575368198467)(image/jm/128.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.con{
width:200px;
height:30px;
border: 1px solid #ccc;
margin-bottom:5px;
box-shadow: 1px 2px 1px rgba(0,0,0,0.1);
font-size:18px;
line-height: 30px;
display: none;
}
</style>
</head>
<body>
<div class="seach">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
var con=document.querySelector(".con");
var jd=document.querySelector(".jd");
jd.addEventListener("keyup",function(){
if(this.value==""){
con.style.display="none";
}else{
//当input内容不为空的时候con出现并把input内容赋值给con盒子的内容
con.style.display="block";
con.innerHTML=this.value;
}
})
//失去焦点的时候con盒子消失
jd.addEventListener("blur",function(){
con.style.display="none";
})
//获取焦点的时候con盒子出现
jd.addEventListener("focus",function(){
if(this.value!==""){
con.style.display="block";
}
})
</script>
</body>
</html>
三、BOM浏览器对象模型
目标:
- 能够说出什么是bom
- 能够知道浏览器的顶级对象window
- 能够写出页面加载事件以及注意事项
- 能够写出两种定时器函数并说出区别
- 能够说出js执行机制
- 能够使用location对象完成页面之间的跳转
- 能够知晓navigator对象涉及的属性
- 能够使用history提出的方法实现页面刷新
1.BOM概述
1-1 什么是BOM
BOM就是浏览器对象模型,他提供了独立于内容而与浏览器进行交互的对象,其核心对象是window。
BOM有一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
BOM缺乏标准,js语法的标准化组织是ECMA,DOM的标准化组织是w3c,BOM最初是Netscape浏览器标准的一部分。
DOM和BOM的区别如下:
-
DOM
- 文档对象模型
- DOM就是把文档当作一个对象来看待
- DOM的顶级对象是document
- DOM主要学习的是操作页面元素
- DOM是w3c标准规范
-
BOM
- 浏览器对象模型
- 把浏览器当作一个对象来看待
- BOM的顶级对象是window
- BOM学习的是浏览器窗口交互的一些对象
- BOM是浏览器厂商在各自浏览器上定义的,兼容性较差。
1-2 BOM的构成
BOM比DOM更大,它包含了DOM
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3jhxJOeB-1575368198467)(image/jm/129.png)]
window对象是浏览器的顶级对象,它具有双重角色。
-
它是js访问窗口的一个接口
-
他是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法。在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等。
注意:window下的一个特殊属性是window.name
2.window对象的常见事件
2-1窗口加载事件
window.οnlοad=function(){}
或者
window.addEventListener("load",function(){})
window.onload是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、css文件等),就调用的处理函数。
注意:
- 有了window.onload就可以把js代码写到页面元素的上方,因为onload是等页面内容全部加载完毕再去执行处理函数。
- window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准。
- 如果使用addEventListener 则没有限制
document.addEventListener("DOMContentLoaded",function(){})
DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片、falsh等等。ie9以上才支持
如果页面的图片很多的话,从用户访问到onload触发可能需要较长的时间,交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded事件比较合适。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script>
//window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准
/*window.οnlοad=function(){
var btn=document.querySelector("button");
btn.addEventListener("click",function(){
alert("点击我");
})
}
window.οnlοad=function(){
var btn=document.querySelector("button");
btn.addEventListener("click",function(){
alert("122");
})
}*/
window.addEventListener("load",function(){
var btn=document.querySelector("button");
btn.addEventListener("click",function(){
alert("122");
})
})
window.addEventListener("load",function(){
alert("点击我哦");
})
document.addEventListener("DOMContentLoaded",function(){
alert("333");
})
//load是等页面内容全部加载完毕,包含页面dom元素、图片、flash、css等等
//DOMContentLoaded是dom加载完毕,不包含图片、flash、css等就可以执行,加载速度比load更快一些
</script>
</head>
<body>
<button>点击</button>
</body>
</html>
2-2调整窗口大小事件
window.οnresize=function(){}
window.addEventListener('resize',function(){});
window.onresize是调整窗口大小加载事件,当出发时就调用的处理函数。
注意:
- 只要窗口大小发生像素变化,就会触发这个事件。
- 我们经常利用这个事件完成响应式布局。window.innerWinth当前屏幕的宽度。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:500px;
height:300px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
var div=document.querySelector("div");
window.addEventListener("resize",function(){
if(window.innerWidth<=800){
div.style.display="none";
}else{
div.style.display="block";
}
})
</script>
</body>
</html>
3.定时器
3-1 两种定时器
window对象给我们提供了2个非常好用的方法-定时器。
- setTimeout()
- setInterval()
3-2 setTimeout()定时器
window.setTimeout(回调函数,[延迟的毫秒数]);
setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
注意:
- window可以省略。
- 这个调用函数可以直接写函数,也可以写函数名或者采取字符串‘函数名()’三种形式。第三种不推荐。
- 延迟的毫秒数省略默认为0,如果写,必须是毫秒。
- 因为定时器可能会有很多,所以我们经常给定时器赋值一个标识符。
<script>
//setTimeout语法规范
//1.window.setTimeout(调用函数,延迟时间);
//2.window在调用的时候可以省略
//3.延迟时间单位是毫秒,1秒等于1000毫秒,延迟时间可以省略,不过省略之后就会默认为0毫秒,立即` 执行
//4.调用函数可以写直接写,也可以写函数名,还有一种写法"函数名()比如: setTimeout("fn()",3000);
//5.页面中可能会有很多的定时器,我们经常给定时器添加标识符()名字
/*setTimeout(function(){
console.log("时间到了");
},2000)*/
function cellBack(){
console.log("时间到了")
}
var time1=setTimeout(cellBack,3000);
var time2=setTimeout(cellBack,6000);//大多数用这种
//setTimeout("fn()",3000);//不提倡这种写法
</script>
setTimeout()这个调用函数我们也可以称为回调函数cellback。
普通函数是按照代码顺序直接调用。
而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。
简单理解:回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数。
像之前element.οnclick=function()或者element.addEventListener(“click”,fn)里面的函数都是回调函数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GjMaEonf-1575368198468)(image/jm/130.png)]
<img src="img/gg.png" />
<script>
var img=document.querySelector("img");
setTimeout(function(){
img.style.display="none";
},5000)
</script>
3-3 停止setTimeout()定时器
window.clearTimeout(TimeoutID)
clearTimeout()方法取消了先前通过setTimeout()建立的定时器。
注意:window可以省略;里面的参数就是定时器的标识符。
<button>点击停止定时器</button>
<script>
var btn=document.querySelector("button");
var timer=setTimeout(function(){
console.log("爆炸了")
},5000)
btn.addEventListener("click",function(){
clearTimeout(timer);
})
</script>
3-4 setInterval() 定时器
window.setInterval(回调函数,[间隔的毫秒数])
setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
注意:
- window可以省略。
- 这个调用函数可以直接写函数,也可以写函数名或者采取字符串‘函数名()’三种形式。第三种不推荐。
- 延迟的毫秒数省略默认为0,如果写,必须是毫秒。
- 因为定时器可能会有很多,所以我们经常给定时器赋值一个标识符。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VLXyW4Tj-1575368198469)(image/jm/131.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
span{
display:block;
width:50px;
height:50px;
background-color: #000;
color:#fff;
margin:10px;
line-height: 50px;
text-align: center;
float: left;
}
</style>
</head>
<body>
<div>
<span class="hours">1</span>
<span class="minte">2</span>
<span class="second">3</span>
</div>
<script>
//1.获取元素
var hours=document.querySelector(".hours");//小时的盒子
var minte=document.querySelector(".minte");//分钟的盒子
var second=document.querySelector(".second");//秒的盒子
var inputTime = +new Date("2019-11-03 10:00:00");//用户输入的时间总的毫秒数
countDown();//先调用一次函数,防止第一次刷新页面有空白
//2.开启定时器
setInterval(countDown,1000);
function countDown(){
var nowTime = +new Date();//返回的是当前时间总的毫秒数
//tims是剩余的总的毫秒数
var times=(inputTime-nowTime)/1000;
var h=parseInt(times / 60 / 60%24);//时
h=h<10? "0"+h:h;
hours.innerHTML=h;//剩余的小时给小时黑色盒子
var m=parseInt(times/60%60);//分
m=m<10? "0"+m:m;
minte.innerHTML=m;//剩余的分钟给分钟黑色盒子
var s=parseInt(times%60);//秒
s=s<10? "0"+s:s;
second.innerHTML=s;//剩余的秒数给秒的黑色盒子
}
</script>
</body>
</html>
3-5 停止setInterval()定时器
window.clearInterval(IntervalID)
clearInterval()方法取消了先前通过setInterval()建立的定时器。
注意:window可以省略;里面的参数就是定时器的标识符。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button class="begin">开始定时器</button>
<button class="stop">停止定时器</button>
<script>
var begin=document.querySelector(".begin");
var stop=document.querySelector(".stop");
var timer=null;//全局对象,null是一个空对象
begin.addEventListener("click",function(){
timer=setInterval(function(){
console.log("你好");
},1000)
})
stop.addEventListener("click",function(){
clearInterval(timer);
})
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fs3VIsnX-1575368198471)(image/jm/132.png)]
<body>
手机号码:<input type="number"> <button>发送</button>
<script>
var btn=document.querySelector("button");
btn.addEventListener("click",function(){
var time=60;//定义剩下的秒数
btn.disabled=true;
var timer=setInterval(function(){
if(time==0){
clearInterval(timer);
btn.disabled=false;
btn.innerHTML="发送";
}else{
btn.innerHTML="还剩下"+time+"秒";
time--;
}
},1000)
})
</script>
</body>
3-6 this的指向问题
this的指向在函数定义的时候是确定不了的,只能函数执行的时候才能确定指向谁,一般情况下this的最终指向是那个调用它的对象。
- 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this是指向的window)
- 方法调用中谁调用this就指向谁
- 构造函数中this指向构造函数的实例
<body>
<button>点击</button>
<script>
//this指向问题,一般情况下this的最终指向的是那个调用他的对象
//1.全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this是指向的window)
console.log(this);//window
function fn(){
console.log(this);
}
window.fn();//window
window.setTimeout(function(){
console.log(this);//window
},1000)
//2.方法调用中谁调用this就指向谁
var obj={
sayHi:function(){
console.log(this);
}//this指向的obj对象
}
obj.sayHi();
var btn=document.querySelector("button");
btn.onclick=function(){
console.log(this);//this指的是btn按钮
}
//3.构造函数中this指向构造函数的实例
function Fun(){
console.log(this);//this指向的是fun实例函数
}
var fun=new Fun();
</script>
</body>
4.js执行机制
4-1 JS是单线程
js语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为js这门脚本语言诞生的使命-js是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。而应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,这样导致的问题就是:如果js执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
4-2 同步和异步
为了解决这个问题,利用多核cpu的计算能力,html5提出web worker标准,允许js脚本创建多个线程,于是,js中出现了同步和异步。
同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步:你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们烧水的同时,利用这10分钟,去切菜,炒菜。
<script>
//同步:在执行完一个任务后在执行下一个任务
//异步:在执行这个任务的时候,因为这个任务花费的时间长,在执行这个任务的期间就可以先去执行其他 的任务
/*console.log(1);
setTimeout(function(){
console.log(22);
},1000)
console.log(33);*/
//打印顺序为1 33 22
</script>
4-3 同步和异步
同步任务:都是在主线程上执行,形成一个执行线。
异步任务:js的异步任务是通过回调函数实现的。
一般而言,异步任务有以下三种类型:
- 普通事件,如click、resize等
- 资源加载,如load、error等
- 定时器,包括setTimeout、setInterval等
同步任务相关的回调函数添加到任务队列中(任务队列也称为消息队列)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-11jlVA1Y-1575368198472)(image/jm/133.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GdRpD5mn-1575368198473)(image/jm/134.png)]
4-4 执行机制(核心)
1.先执行执行栈中的同步任务
2.异步任务(回调函数)放入任务队列中。
3.一旦执行栈中的所有的同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p81DMQen-1575368198474)(image/jm/135.png)]
<script>
console.log(1);
document.onclick=function(){
console.log("click");
}
console.log(2);
setInterval(function(){
console.log(3);
},3000)
</script>
//执行顺序:
如果没有点击事件,那么输出结果为:1、2、3
如果三秒之前点击事件,那么输出结果为:1、2、click、3
如果三秒之后点击事件,那么输出结果问哦:1、2、3、click。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UUvg0CJY-1575368198474)(image/jm/136.png)]
执行机制执行的过程如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2d0KTmI3-1575368198475)(image/jm/138.png)]
由于主线程不断的重复获得任务、执行任务、在获取任务、再执行,所以这种机制被称为事件循环。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WXZPExcW-1575368198476)(image/jm/139.png)]
5.location对象
5-1 什么是location对象
window对象给我们提供了一个location属性用于获取或设置窗体的url,并且可以用于解析url。因为这个属性返回的是一个对象,所以我们将这个属性称为location对象。
5-2 url
统一资源定位符是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的url,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
protocol://host[:port]/path/[?query]#fragment
例如:http://www.itcast.cn/index.html?name=andy&age=18#link
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fH485EIm-1575368198477)(image/jm/140.png)]
5-3 location对象的属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJsVuHHT-1575368198478)(image/jm/141.png)]
重点记住: href和search
案例: 5秒钟跳转页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:400px;
height:40px;
border:1px solid #ccc;
margin:30px auto;
line-height:40px;
text-align: center;
}
</style>
</head>
<body>
<button>点击</button>
<div></div>
<script>
var btn=document.querySelector("button");
var div=document.querySelector("div");
btn.addEventListener("click",function(){
//location.href 获取网址
//console.log(location.href);
location.href="http://www.itcast.cn";
})
setInterval(fn,1000);
var time=5;
fn();
function fn(){
if(time==0){
location.href="http://www.baidu.com";
}else{
div.innerHTML="还有"+time+"秒钟跳转页面";
time--;
}
}
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZYDx0Pqq-1575368198479)(image/jm/143.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="index.html">
用户名:<input type="text" name="uname">
<input type="submit" value="登录">
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div></div>
<script>
console.log(location.search);//?uname=andy
//1.使用substr去掉?substr(开始的位置,截取的数量)
var params=location.search.substr(1);
console.log(params);
//2.利用=把字符串分割为数组,split("分隔符")
var arr=params.split("=");
console.log(arr);
var div=document.querySelector("div");
//把数据写入到div中
div.innerHTML=arr[1]+"欢迎你";
</script>
</body>
</html>
5-4 location对象的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EyKSE9ns-1575368198480)(image/jm/144.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button>点击</button>
<script>
var btn=document.querySelector("button");
btn.addEventListener("click",function(){
console.log(location.assign)
//location.assign记录浏览历史,所以可以实现后退功能
location.assign("http://www.baidu.com");
//location.replace不记录浏览历史,所以不可以实现后退功能
//location.replace("http://www.baidu.com");
//location.reload() 如果括号里是空或者false相当于刷新或者加载
/*location.reload();*/
//location.reload(true),括号里面有参数true,相当于是强制刷新
/*location.reload(true);*/
})
</script>
</body>
</html>
6.navigator对象
navigator对象包含有关浏览器的信息,它有很多属性,我们常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j5ZPtaFq-1575368198480)(image/jm/145.png)]
7.history对象
window对象给我们提供了一个history对象,与浏览器历史纪录进行交互,该对象包含用户(在浏览器窗口中)访问过的url。
history对象的方法 | 作用 |
---|---|
back() | 可以后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能 参数如果是1就是前进,如果参数是-1那么就是后退1个页面 |
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="list.html">带我去列表页</a>
<button>后退</button>
<script>
var btn=document.querySelector("button");
btn.addEventListener("click",function(){
history.back();
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="lindex.html">带我首页</a>
<button>前进</button>
<script>
var btn=document.querySelector("button");
btn.addEventListener("click",function(){
//history.forward();
//history.go(1),1就是前进一步
history.go(1);
})
</script>
</body>
</html>
四、PC端网页特效
目标:
- 能够说出常见offset系列属性的作用
- 能够说出常见client系列属性的作用
- 能够说出常见scroll系列属性的作用
- 能够封装简单动画函数
- 能够写出网页轮播图案例
1.元素偏移量offset系列
1-1 offset概述
offset翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
- 注意:返回的数值都不带单位
offset系列常用属性
offset系列属性 | 作用 |
---|---|
element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级元素都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素左边的偏移 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
.father{
position: relative;
width:200px;
height:200px;
background-color:pink;
margin:100px;
}
.son{
width:100px;
height:100px;
background-color: purple;
margin:45px;
}
.w{
width:200px;
height:200px;
background-color: blue;
margin:0 auto 200px;
padding:10px;
border:15px solid red;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<div class="w"></div>
<script>
//offset系列
var fh=document.querySelector(".father");
var son=document.querySelector(".son");
var w=document.querySelector(".w");
//1.可以得到元素的偏移 位置 返回的是不带单位的数值
console.log(fh.offsetTop);//100
console.log(fh.offsetLeft);//100
//它是带有定位的父亲为准,若没有父亲或者父亲没有定位,那么则以body为准
console.log(son.offsetLeft);//如果父亲有定位则返回45,没有定位则返回145
//2.可以得到元素的大小 高度和宽度,包括padding+border+width
console.log(w.offsetWidth);//250
console.log(w.offsetHeight);//250
//返回带有定位的父亲,如果没有定位则返回body
console.log(son.offsetParent);
console.log(son.parentNode);//返回的是离自己最近的父亲,不管父亲有没有定位
</script>
</body>
</html>
1-2 offset和style的区别
offset
- offset可以得到任意样式表中的样式值
- offset系列获得的数值是没有单位的
- offsetWidth包含padding+border+width
- offsetWidth等属性是只读属性,只能获取不能赋值
- 所以,我们想要获取元素大小位置,用offset更合适
style
- style只能得到行内样式表中的样式值
- style.width获得的是带有单位的字符串
- style.width获得不包含padding和border的值
- style.width是可读写属性,可以获取也可以赋值
- 所以,我们想要给元素更改值,则需要用style改变。
1-3 案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4eE6qAh5-1575368198481)(image/jm/146.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.box{
width:300px;
height:300px;
background-color: pink;
margin:100px;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box=document.querySelector(".box");
box.addEventListener("mousemove",function(e){
/*console.log(e.pageX);
console.log(e.pageY);
console.log(box.offsetLeft);*/
var x=e.pageX-box.offsetLeft;
var y=e.pageY-box.offsetTop;
box.innerHTML="盒子内的鼠标"+"x坐标为"+x +" y的坐标为"+y;
})
</script>
</body>
</html>
模态框拖拽框案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ai0XHgDf-1575368198482)(image/jm/147.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
box-sizing: border-box;
}
a{
text-decoration: none;
color:#000;
}
.head{
font-size:28px;
text-align: center;
}
.bg{
display: none;
width:100%;
height:100%;
position: fixed;
top:0;
left:0;
background-color: rgba(0,0,0,0.3);
}
.login{
position: absolute;
z-index: 2;
width:400px;
height:250px;
background-color: #fff;
left:50%;
top:50%;
transform:translate(-50%,-50%);
display: none;
}
.lg-title{
text-align: center;
font-size: 24px;
}
.lg-input{
padding-left:10px;
margin:30px;
font-size: 18px;
}
.lg-input lable{
display: inline-block;
width: 80px;
height:30px;
}
.lg-input input{
height:30px;
width:200px;
outline-style: none;
}
#close{
font-size: 12px;
display: block;
width:30px;
height:30px;
background-color: #fff;
border:1px solid #ccc;
position: absolute;
top:-10px;
right:-10px;
border-radius: 50%;
line-height: 30px;
text-align: center;
}
.lg-title{
cursor: move;
padding-top:10px;
}
#submit{
width: 100px;
height:30px;
left:50%;
margin-left:150px;
}
</style>
</head>
<body>
<div class="head">
<a href="javascript:;" id="link">点击,弹出对话框</a>
</div>
<div class="login" >
<span><a href="javascript:;" id="close">关闭</a></a></span>
<div class="lg-title" id="title">登陆会员</div>
<div class="lg-content">
<div class="lg-input">
<lable>用户名</lable>
<input type="text" placeholder="请输入你的用户名" class="uname"/>
</div>
<div class="lg-input">
<lable>密码</lable>
<input type="password" placeholder="请输入你的密码" class="pass"/>
</div>
<div class="sub"><input type="submit" value="登录" id="submit"></div>
</div>
</div>
<div class="bg"></div>
<script>
//1.获取元素
var link=document.querySelector("#link");
var bg=document.querySelector(".bg");
var login=document.querySelector(".login");
var close=document.querySelector("#close");
var title=document.querySelector("#title");
/*console.log(title)*/
//1.点击点击弹出对话框按钮,然后bg遮盖层和login对话框显示出来
link.addEventListener("click",function(){
bg.style.display="block";
login.style.display="block";
})
//2.当点击关闭按钮close,则遮盖层和login都隐藏
close.addEventListener("click",function(){
bg.style.display="none";
login.style.display="none";
})
//3.当拖动title时,可以使login对话框随意拖动位置
//(1)当我们鼠标按下,就获得鼠标在盒子内的坐标
title.addEventListener("mousedown",function(e){
var x=e.pageX-login.offsetLeft;
var y=e.pageY-login.offsetTop;
//(2)当鼠标移动时,把鼠标在页面中的坐标减去鼠标在盒子内的坐标就是模态框的位置。
document.addEventListener("mousemove",move)
function move(e){
login.style.left=e.pageX-x+"px";
login.style.top=e.pageY-y+"px";
}
//(3)鼠标弹起,就让鼠标移动事件移除。
document.addEventListener("mouseup",function(){
document.removeEventListener("mousemove",move)
})
})
</script>
</body>
</html>
仿京东放大镜案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LeiTCvQC-1575368198483)(image/jm/148.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PgyTN0nX-1575368198484)(image/jm/149.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
.wrap{
width:400px;
height:400px;
border:1px solid #ccc;
margin:30px;
position: relative;
}
.wrap .pic{
width:100%;
height:100%;
}
.mask{
width:200px;
height:200px;
background-color: #fede4f;
position: absolute;
top:0;
left:0;
opacity: 0.5;
cursor: move;
display: none;
}
.big{
width:500px;
height:500px;
position: absolute;
top:0;
left:400px;
border:1px solid #ccc;
overflow: hidden;
display: none;
}
.bigImg{
position: absolute;
top:0;
left:0;
}
</style>
</head>
<body>
<div class="wrap">
<img src="img/sj.png" class="pic"/>
<div class="mask"></div>
<div class="big">
<img src="img/sj.png" class="bigImg"/>
</div>
</div>
<script>
//获取元素
var wrap=document.querySelector(".wrap");
var mask=document.querySelector(".mask");
var big=document.querySelector(".big");
var bigImg=document.querySelector(".bigImg");
console.log(bigImg);
//1.当经过小盒子时候,遮挡层和大盒子就出现
wrap.addEventListener("mouseover",function(){
mask.style.display="block";
big.style.display="block";
})
//2.当离开小盒子的时候,遮挡层和大盒子就隐藏
wrap.addEventListener("mouseout",function(){
mask.style.display="none";
big.style.display="none";
})
//3.当鼠标移动的时候,黄色的遮挡层会跟着走
wrap.addEventListener("mousemove",function(e){
var x=e.pageX-this.offsetLeft;
var y=e.pageY-this.offsetTop;
//masK的移动距离
var maskX=x-mask.offsetWidth/2;
var maskY=y-mask.offsetHeight/2;
//遮挡层移动的最大距离
var maskMax=wrap.offsetWidth-mask.offsetWidth;
if(maskX<=0){
maskX=0;
}else if(maskX>=maskMax){
maskX=maskMax;
}
if(maskY<=0){
maskY=0;
}else if(maskY>=maskMax){
maskY=maskMax
}
//盒子的高度200的一半是100,就是mask的top和left的值了
mask.style.left=maskX+"px";
mask.style.top=maskY+"px";
//4.让大图片跟着遮挡层一起移动
//公式为:大图片的移动距离=遮挡层移动距离*大图片的最大移动距离/遮挡层移动的最大距离
//大图片的最大移动距离bigMax
bigMax=bigImg.offsetWidth-big.offsetWidth;
//大图片的移动距离bigX bigY
var bigX=maskX*bigMax/maskMax;
var bigY=maskY*bigMax/maskMax;
bigImg.style.left=-bigX+"px";
bigImg.style.top=-bigY+"px";
})
</script>
</body>
</html>
2.元素可视区client系列
client翻译过来就是客户端,我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
client系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括padding、内容区的高度,不含边框,返回数值不带单位 |
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
div{
width:200px;
height:200px;
background-color: pink;
border:10px solid red;
}
</style>
</head>
<body>
<div></div>
<script>
//clientHeight和offsetHeight最大的区别是前者不包括边框,光包含他自身的高度和内边距值
var div=document.querySelector("div");
console.log(div.clientHeight);//200 不带单位
console.log(div.clientTop);//10 不带单位
</script>
</body>
</html>
立即执行函数
语法格式: (function(){})() 或者 (function(){}())
//立即执行函数的作用:独立创建一个作用域,里面所有的变量都是局部变量。
<body>
<script>
//1.立即执行函数:不需要调用,立马能够自己执行的函数
function fn(){
console.log(1);
}
fn();
//立即执行函数的写法:(function(){})() 或者(function(){}())
//实例1
(function(a,b){
console.log(a+b);
var num=10;
})(1,2);//最后的小括号可以看作是调用函数
//实例2
(function(a,b){
console.log(a+b);
var num=10;
}(2,3))
//3.立即执行函数最大的作用就是创建了一个作用域,里面的所有的变量都是局部变量,不会有命名冲突的 情况
</script>
</body>
3.元素滚动scorll事件
3-1 元素scroll系列属性
scroll就是滚动的意思,我们使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等。
scroll系列属性 | 作用 |
---|---|
element.scrollTop | 返回被卷去的上侧距离,返回数值不带单位 |
element.scrollLeft | 返回被卷去的左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身实际的高度,不含边框,返回数值不带单位 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LdhTE9rj-1575368198485)(image/jm/150.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width: 200px;
height: 200px;
background-color: pink;
border: 10px solid #ccc;
padding:10px;
overflow: auto;
}
</style>
</head>
<body>
<div>
我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是 文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我 是字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我是文字我 是文字
</div>
<script>
var div=document.querySelector("div");
console.log(div.scrollHeight);//403 实际的高度,包括超出范围的高度
console.log(div.clientHeight);//220 高度加padding的值
//scroll事件 当滚动条发生变化就会触发事件
div.addEventListener("scroll",function(){
console.log(div.scrollTop);
})
</script>
</body>
</html>
3-2 页面被卷去的头部
如果浏览器的高(或者宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发onscroll事件。
3-3 页面被卷去的头部兼容性解决方案
需要注意的是,页面被卷去的头部,有兼容性问题,因为被卷去的头部通常有如下几种写法:
如下图用红线圈出来的就是DTD
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iHAK74T0-1575368198486)(image/jm/151.png)]
- 声明了DTD,使用document.documentElement.scroTop
- 没有声明DTD,使用document.body.scrollTop
- 新方法window.pageYoffset和window.pageXoffset,IE9开始支持
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7KxdrhNC-1575368198487)(image/jm/152.png)]
仿淘宝侧边栏案例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
.w{
width:1200px;
margin:0 auto;
}
.header{
background-color: purple;
height:100px;
margin-bottom:20px;
}
.banner{
background-color: blue;
height:300px;
margin-bottom:20px;
}
.main{
background-color: green;
height:1000px;
margin-bottom:20px;
}
.slider-bar{
width:50px;
height:100px;
background-color:pink;
position:absolute;
right:15px;
top:300px;
}
span{
display: none;
position:absolute;
bottom:0;
font-size:14px;
}
</style>
</head>
<body>
<div class="slider-bar">
<span class="goBack">返回顶部</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">main区域</div>
<script>
//获取元素
var sliderbar=document.getElementsByClassName("slider-bar")[0];
var banner=document.getElementsByClassName("banner")[0];
//console.log(banner.offsetTop);
var bannerTop=banner.offsetTop;
//当我们侧边栏固定定位之后应该变化的数值
var sliderbartop=sliderbar.offsetTop-banner.offsetTop;
//获取主体main
var main=document.querySelector(".main");
var mainTop=main.offsetTop;
var goBack=sliderbar.children[0];
document.addEventListener("scroll",function(){
//window.pageYOffset页面被卷去的头部
//console.log(window.pageYOffset);
//当页面上侧距离大于等于120的时候,sliderbar盒子变成固体定位
if(window.pageYOffset>=bannerTop){
sliderbar.style.position="fixed";
sliderbar.style.top=sliderbartop+"px";
}else{
sliderbar.style.position="absolute";
sliderbar.style.top="300px";
}
if(window.pageYOffset>=mainTop){
goBack.style.display="block";
}else{
goBack.style.display="none";
}
goBack.addEventListener("click",function(){
document.body.scrollTop = document.documentElement.scrollTop = 0;
})
})
</script>
</body>
</html>
3-4三大系列总结
三大系列大小对比 | 作用 |
---|---|
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
element.scrollWidth | 返回自身实际宽度,不含边框,返回数值不带单位 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVJ2BfPx-1575368198488)(image/jm/153.png)]
他们主要写法:
- offset系列经常用于获得位置 offsetLeft offsetTop
- client经常用于获取元素大小 clientWidth clientHeight
- scroll经常用于获取滚动距离 scrollTop scrollLeft
- 注意页面滚动的距离通过window.pageXoffset 获得
3-5 mouseenter和mouseover的区别
mouseenter鼠标事件
- 当鼠标移动到元素上时就会触发mouseenter事件
- 类似mouseover,他两者之间的差别是:mouseover鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会经过自身盒子触发。之所以这样就是因为mouseenter不会冒泡
- 和mouseenter搭配鼠标离开mouseleave同样不会冒泡
4.动画函数封装
4-1动画实现原理
核心原理: 通过定时器setInterval()不断移动盒子位置
实现步骤:
- 获得盒子当前位置
- 让何子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要添加定位,才能使用element.style.left
<body>
<div></div>
<script>
//动画原理
//1.获得盒子当前位置
//2.让盒子在当前位置加上1个移动距离
//3.利用定时器不断重复这个操作
//4.加一个结束定时器的条件
//5.注意此元素需要添加定位,才能使用element.style.left
var div=document.querySelector("div");
var timer=setInterval(function(){
if(div.offsetLeft>=400){
clearInterval(timer);
}else{
div.style.left=div.offsetLeft+1+"px";
}
},30)
</script>
</body>
4-2 动画函数的简单封装
注意函数需要传递2个参数,动画对象和移动到的距离。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:100px;
height:100px;
background-color: pink;
position:absolute;
left:0;
}
p{
width:200px;
height:200px;
background-color: purple;
position:absolute;
left:0;
top:150px;
}
</style>
</head>
<body>
<div></div>
<p></p>
<script>
//obj移动对象 target移动的目标位置
function animate(obj,target){
var timer=setInterval(function(){
if(obj.offsetLeft>=target){
clearInterval(timer);
}else{
obj.style.left=obj.offsetLeft+1+"px";
}
},30)
}
var div=document.querySelector("div");
var p=document.querySelector("p");
animate(div,400);
animate(p,500);
</script>
</body>
</html>
4-3 动画函数给不同元素记录不同的定时器
如果多个元素都使用这个动画函数,每次都要var 声明定时器,我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
核心原理: 利用js是一门动态语言,可以很方便的给当前对象添加属性。
<body>
<button>点击我p才走</button>
<div></div>
<p></p>
<script>
//obj={};
//obj.name="andy"
//obj移动对象 target移动的目标位置
function animate(obj,target){
//当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
//解决方案就是让我们元素只有一个定时器执行
//先清除以前的定时器,只保留当前的一个定时器
clearInterval(obj.timer);
obj.timer=setInterval(function(){
if(obj.offsetLeft>=target){
clearInterval(obj.timer);
}else{
obj.style.left=obj.offsetLeft+1+"px";
}
},30)
}
var div=document.querySelector("div");
var p=document.querySelector("p");
var btn=document.querySelector("button");
animate(div,400);
btn.addEventListener("click",function(){
animate(p,500);
})
</script>
</body>
4-4 缓动效果原理
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
- 核心算法:(目标值-现在的位置)/10 做为每次移动的距离步长
- 停止的条件是:让当前的盒子位置等于目标位置就停止定时器
- 注意布长值需要取整
4-5 动画函数多个目标值之间移动
可以让动画函数从800移动到500.
当我们点击按钮的时候,判断布长是正数还是负值,如果是正值则步长往大了取整;如果是负值,则步长向小了取整
4-6动画函数添加回调函数
回调函数原理:函数可以作为一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。
回调函数写的位置:定时器结束的位置
4-4和4-5和4-6的代码验证
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
span{
display: block;
position: absolute;
left:0;
top:200px;
width:150px;
height:150px;
background-color: purple;
}
</style>
</head>
<body>
<button class="btn500">点击夏雨荷500</button>
<button class="btn800">点击夏雨荷800</button>
<span>夏雨荷</span>
<script>
function animate(obj,target,cellback){//obj是目标对象,target是目标距离
//缓懂动画思路
//1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
//2.核心算法:(目标值-现在的位置)/10,作为每次移动的距离 步长
//3.停止的条件是:让当前盒子位置等于目标位置就停止定时器
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(cellback){
cellback();
}
}else{
//把每次加1,这个步长值改为一个慢慢变小的值
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(){
span.style.backgroundColor="red";
});
})
</script>
</body>
</html>
4-
4-7 动画函数封装到单独的js文件里面
function animate(obj,target,cellback){//obj是目标对象,target是目标距离
//console.log(cellback);//cellback=function(){};
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(cellback){
cellback();
}
}
//把每次加1,这个步长值改为一个慢慢变小的值
obj.style.left=obj.offsetLeft+step+"px";
},15)
}
案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXXLj868-1575368198489)(image/jm/154.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
.con{
width:200px;
height:40px;
background-color: brown;
position: absolute;
left:0;
top:0;
z-index: 1;
}
.sliderbar{
width:40px;
height:40px;
/*background-color: pink;*/
position:absolute;
z-index: 9999;
right:0;
top:100px;
color:#000;
text-align: center;
line-height: 40px;
}
span{
color:#000;
position: absolute;
left:15px;
z-index: 999;
}
</style>
<script src="js/animate.js"></script>
</head>
<body>
<div class="sliderbar">
<span>←</span>
<div class="con">问题反馈</div>
</div>
<script>
var sliderbar=document.getElementsByClassName("sliderbar");
var con=document.querySelector(".con");
var span=document.querySelector("span");
console.log(con)
con.addEventListener("mouseover",function(){
animate(con,-160,function(){
span.innerHTML="→";
});
})
con.addEventListener("mouseout",function(){
animate(con,0,function(){
span.innerHTML="←";
})
})
</script>
</body>
</html>
5.常见网页特效案例
5-1节流阀
防止轮播图按钮连续点击造成播放过快
节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
开始设置一个变量var flag=true;
if(flag){
flag=false;
do something;
}//关闭水龙头
利用回调函数动画执行完毕,flag=true 打开水龙头
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-13eSy5uz-1575368198490)(image/jm/156.png)]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/animate.js" ></script>
<script src="js/lunbo.js"></script>
<style>
*{
padding:0;
margin:0;
}
.focus{
width:520px;
height:280px;
background-color: pink;
margin:100px auto;
position: relative;
overflow: hidden;
}
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?7kkyc2');
src: url('fonts/icomoon.eot?7kkyc2#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?7kkyc2') format('truetype'),
url('fonts/icomoon.woff?7kkyc2') format('woff'),
url('fonts/icomoon.svg?7kkyc2#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
a{
text-decoration: none;
}
li{
list-style: none;
}
.arrow-l,.arrow-r{
font-family: 'icomoon';
font-style: normal;
display: block;
width:30px;
height:30px;
background-color: rgba(0,0,0,0.4);
position: absolute;
top:50%;
margin-top:-15px;
color:#fff;
text-align: center;
line-height: 30px;
font-size:20px;
display: none;
z-index: 2;
}
.arrow-r{
position: absolute;
right:0;
}
.circle{
width:100px;
height:15px;
/*background-color: rgba(255,255,255,0.3);*/
position: absolute;
left:50%;
margin-left:-50px;
bottom: 10px;
}
.circle li{
width:10px;
height:10px;
background-color: #fff;
border-radius: 50%;
float: left;
margin:3px 3px 3px;
}
.circle .curret{
background-color: orange;
}
.focus ul{
width:500%;
position: absolute;
top:0;
left:0;
}
.focus ul li{
float: left;
}
</style>
</head>
<body>
<div class="focus">
<a href="javascript:;" class="arrow-l"> </a>
<a href="javascript:;" class="arrow-r"> </a>
<ul>
<li>
<a href="#"><img src="img/pic1.png" /></a>
</li>
<li>
<a href="#"><img src="img/pic2.png" /></a>
</li>
<li>
<a href="#"><img src="img/pic3.png" /></a>
</li>
<li>
<a href="#"><img src="img/pic4.png" /></a>
</li>
</ul>
<ol class="circle">
</ol>
</div>
</body>
</html>
附:luobo.js如下
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.动态生成小圆圈,ul中有几张图片,圆圈就有几个
var ul=focus.querySelector("ul");
var ol=focus.querySelector(".circle");
//console.log(ul.children.length);
for(var i=0;i<ul.children.length;i++){
//(1).创建小li
var li=document.createElement("li");
//给li添加自定义属性
li.setAttribute("index",i);
//(2).把小li添加到ol中
ol.appendChild(li);
//4.给所有的小li绑定事件,运用拍他思想
li.addEventListener("click",function(){
//干掉其他人,把所有的li的current类名清楚掉
for(var i=0;i<ol.children.length;i++){
ol.children[i].className="";
}
//留下我自己,只能当前的li设置current类名
this.className="curret";
//5.点击小圆圈,移动图片,当然移动的是ul
//ul的移动距离,小圆圈的索引号乘以图片的宽度,注意是负值
//当我们点击了某个小li时,就拿到当前li的索引号
var index=this.getAttribute("index");
//当我们点击了某个小li,就要把这个小li的索引号给num
num=index;
//当我们点击了某个小li,就要把这个小li的索引号给circle
circle=index;
/*console.log(focusWidth);
console.log(index);*/
animate(ul,-index*focusWidth)
})
}
//(3).把ol中的第一个小li设置成类名curret
ol.children[0].className="curret";
//6.克隆第一张图片
var first=ul.children[0].cloneNode(true);
ul.appendChild(first);
//7.点击右侧按钮,滚动图片
var num=0;
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++;
if(circle==ol.children.length){
circle=0;
}
//调用函数
circleChange();
}
})
//9.左侧按钮
arrow_l.addEventListener("click",function(){
if(flag){
flag=false;
//如果走到了最后复制的一张图片,此时我们的ul要快速复原left=0
if(num==0){
num=ul.children.length-1;
ul.style.left=-num*focusWidth+"px";
}
num--;
animate(ul,-num*focusWidth,function(){
flag=true;
});
//8.点击右侧按钮,小圆圈跟随一起变化,可以再声明一个控制小圆圈的变量
circle--;
//circle<0时,circle应该改为第四个小圆圈,索引号为3
if(circle<0){
circle=ol.children.length-1;
}
//调用函数
circleChange();
}
})
function circleChange(){
//先清除其余小圆圈的current类名
for(var i=0;i<ol.children.length;i++){
ol.children[i].className="";
}
//留下当前的小圆圈的current类名
ol.children[circle].className="curret";
}
//10.自动播放轮播图
var timer=setInterval(function(){
//手动调用事件
arrow_r.click();
},2000)
})
5-2 返回顶部案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rX6k73es-1575368198491)(image/jm/157.png)]
案例分析:
- 带有动画的返回顶部
- 此时可以继续使用我们封装的动画函数
- 只需要把所有的left相关的值改为跟页面垂直滚动距离相关就可以了
- 页面滚动了多少,可以通过window.pageYoffset得到
- 最后是页面滚动,使用window.scroll(x,y),注意:括号里面的x和y不需要加px单位
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
padding:0;
margin:0;
}
.w{
width:1200px;
margin:0 auto;
}
.header{
background-color: purple;
height:100px;
margin-bottom:20px;
}
.banner{
background-color: blue;
height:300px;
margin-bottom:20px;
}
.main{
background-color: green;
height:1000px;
margin-bottom:20px;
}
.slider-bar{
width:50px;
height:100px;
background-color:pink;
position:absolute;
right:15px;
top:300px;
}
span{
display: none;
position:absolute;
bottom:0;
font-size:14px;
}
</style>
</head>
<body>
<div class="slider-bar">
<span class="goBack">返回顶部</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">main区域</div>
<script>
//获取元素
var sliderbar=document.getElementsByClassName("slider-bar")[0];
var banner=document.getElementsByClassName("banner")[0];
//console.log(banner.offsetTop);
var bannerTop=banner.offsetTop;
//当我们侧边栏固定定位之后应该变化的数值
var sliderbartop=sliderbar.offsetTop-banner.offsetTop;
//获取主体main
var main=document.querySelector(".main");
var mainTop=main.offsetTop;
var goBack=sliderbar.children[0];
document.addEventListener("scroll",function(){
//window.pageYOffset页面被卷去的头部
//console.log(window.pageYOffset);
//当页面上侧距离大于等于120的时候,sliderbar盒子变成固体定位
if(window.pageYOffset>=bannerTop){
sliderbar.style.position="fixed";
sliderbar.style.top=sliderbartop+"px";
}else{
sliderbar.style.position="absolute";
sliderbar.style.top="300px";
}
if(window.pageYOffset>=mainTop){
goBack.style.display="block";
}else{
goBack.style.display="none";
}
})
goBack.addEventListener("click",function(){
//里面的x和y是不加单位px的
//因为是窗口做动画,所以对象改为window
animate(window,0);
})
function animate(obj,target,cellback){//obj是目标对象,target是目标距离
//console.log(cellback);//cellback=function(){};
clearInterval(obj.timer);
obj.timer=setInterval(function(){
//步长值写道定时器的里面
//把步长值取整
//var step=Math.ceil((target-obj.offsetLeft)/10);
var step=(target-window.pageYOffset)/10;
step=step>0?Math.ceil(step):Math.floor(step);
if(window.pageYOffset==target){
clearInterval(obj.timer);
//回调函数写在定时器结束里面
if(cellback){
cellback();
}
}
animate(obj,target,cellback)
//把每次加1,这个步长值改为一个慢慢变小的值
//obj.style.left=window.pageYOffset+step+"px";
window.scroll(0,window.pageYOffset+step);
},15)
}
</script>
</body>
</html>
5-3 筋斗云案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cRKSQWD8-1575368198492)(image/jm/158.png)]
五、移动端网页特效
目标:
- 能够写出移动端触屏事件
- 能够写出常见的移动端特效
- 能够使用移动端开发插件开发移动端特效
- 能够使用移动端开发框架开发移动端特效
1.触屏事件
1-1 触屏事件概述
移动端浏览器兼容性较好,我们不需要考虑以前js的兼容性问题,可以放心的使用原生js书写效果,但是移动端也有自己独特的地方。比如触屏事件touch(也称触摸事件),Android和IOS都有。
touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触摸事件可响应用户手指(或触控笔)对屏幕或者触控板操作。
常见的触屏事件如下:
触屏touch事件 | 说明 |
---|---|
touchstart | 手指触摸到一个dom元素时触发 |
touchmove | 手指在一个dom元素上滑动时触发 |
touchend | 手指从一个dom元素上移开时触发 |
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:200px;
height:200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
var div=document.querySelector("div");
//手指触摸dom元素事件
div.addEventListener("touchstart",function(){
console.log("我摸你了");
})
//手指在dom元素身上移动事件
div.addEventListener("touchmove",function(){
console.log("继续摸");
})
//手指离开dom元素事件
div.addEventListener("touchend",function(){
console.log("我走了");
})
</script>
</body>
</html>
1-2 触摸事件对象(TouchEvent)
TouchEvent是一类描述手指在触摸平面(触摸屏、触摸板)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少等等。
touchstart、touchmove、touchend三个事件都会各自有事件对象。
触摸事件对象重点我们看三个常见对象列表:
触摸列表 | 说明 |
---|---|
touches | 正在触摸屏幕的所有手指的一个列表 |
touchTouches | 正在触摸当前dom元素上的手指的一个列表,我们平常都是给元素注册触摸事件,所以重点记住这一个 |
changedTouches | 手指状态发生了改变的列表,从无到有,从有到无变化 |
<script>
var div=document.querySelector("div");
//手指触摸dom事件
div.addEventListener("touchstart",function(e){
//console.log(e);
//touches正在触摸屏幕的所有手指的列表
//targetTouches正在触摸当前dom元素的手指元素
//如果侦听的是一个dom元素,他们两个是一样的
//changedTouches手指状态发生了改变的列表,从有到无或者从无到有
//因为我们一般都是触摸元素,所以最经常使用的是targetTouches
console.log(e.targetTouches[0]);
//e.targetTouches[0]就可以得到正在触摸dom元素的第一个手指的相关信息比如,手指的坐标等等
})
手指移动dom事件
div.addEventListener("touchmove",function(){
console.log("我继续");
})
//手指离开dom事件
div.addEventListener("touchend",function(e){
//console.log(e);
//当我们手指离开屏幕的时候,就没有了touches和targetTouches列表
//但是会有changedTouches
})
</script>
1-3 移动端拖动元素
-
touchstart、touchmove、touchend可以实现拖动元素
-
但是拖动元素需要当前手指的坐标值,我们可以使用targetTouches[0]里面的pageX和pageY.
-
移动端拖动的原理:手指移动中,计算出手指移动的距离。然后用盒子原来的位置+手指移动的距离
-
手指移动的距离:手指滑动中的位置减去手指刚开始触摸的位置
拖动元素三部曲:
- 触摸元素touchstart:获取手指初始坐标,同时货的盒子原来的位置
- 移动手指touchmove:计算手指的滑动距离,并且移动盒子
- 离开手指touchend
注意:手指移动也会触发滚动屏幕所以这里组织默认的屏幕滚动 e.preventDefault();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width:100px;
height:100px;
background-color: pink;
position:absolute;
left:0;
}
</style>
</head>
<body>
<div></div>
<script>
//(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();//阻止屏幕滚动行为
})
</script>
</body>
</html>
2.移动端常见特效
2-1 classList属性
classList属性是html5新增的一个属性,返回元素的类名。但是ie10以上版本不支持。
该属性用于在元素中添加,移除以及切换css类。有以下方法:
-
添加类 element.classList.add(“类名”);
focus.classList.add(curret);
-
移除类: element.classList.remove(“类名”);
-
切换类: element.classList.toggle(“类名”)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.bg{
background-color: black;
}
</style>
</head>
<body>
<div class="one two"></div>
<button>开关灯</button>
<script>
//返回元素的类名classList
var div=document.querySelector("div");
console.log(div.classList);
console.log(div.classList[0]);
//1.添加类名classList.add 注意括号里面的类名不加.
div.classList.add("three");
//2.删除类名classList.remove 注意括号里面的类名不加.
div.classList.remove("one");
//3.切换类名classList.toggle() ,注意括号里面的类名不加.
var btn=document.querySelector("button");
var body=document.body;
btn.addEventListener("click",function(){
body.classList.toggle("bg");
})
</script>
</body>
</html>
2-2 移动端轮播图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SeUZxDby-1575368198494)(image/jm/159.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W9g7nBh0-1575368198495)(image/jm/160.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bZsDdhBM-1575368198496)(image/jm/161.png)]
备注:这两个案例在一起完成,如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?7kkyc2');
src: url('fonts/icomoon.eot?7kkyc2#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?7kkyc2') format('truetype'),
url('fonts/icomoon.woff?7kkyc2') format('woff'),
url('fonts/icomoon.svg?7kkyc2#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
*{
padding:0;
margin:0;
}
li{
list-style: none;
}
a{
color: #fff;
font-size:16px;
text-decoration: none;
}
body{
min-width: 320px;
max-width: 540px;
margin:0 auto;
}
.top{
width:100%;
height:50px;
box-shadow: 1px 1px 2px 1px rgba(0,0,0,0.3);
padding:6px 15px;
box-sizing: border-box;
position: relative;
}
.search{
width:90%;
height:35px;
border: 1px solid #ccc;
border-radius: 10px;
}
.search i{
font-family: 'icomoon';
font-style: normal;
color:#ccc;
margin-left:5px;
margin-top:6px;
font-size:14px;
}
.search span{
color:#ccc;
font-size: 14px;
line-height: 35px;
}
.user{
width:30px;
height:30px;
background-color: #3D98FF;
position: absolute;
right:10px;
bottom: 10px;
border-radius: 50%;
}
.user em{
font-family: 'icomoon';
font-style: normal;
line-height: 30px;
font-size:22px;
margin-left:4px;
}
header{
width:100%;
height:100px;
position: relative;
overflow: hidden;
}
header img{
width:100%;
height:100%;
}
.focus ul{
overflow: hidden;
width:500%;
margin-left:-100%;
}
.focus ul li{
float: left;
width:20%;
}
.focus ol{
position: absolute;
right:5px;
bottom:5px;
}
.focus ol li{
width:5px;
height:5px;
background-color: #fff;
display: inline-block;
border-radius: 2px;
transition: all .3s;
}
.focus .current{
width:15px;
}
nav{
padding:5px;
}
.row{
width:100%;
height:90px;
background-color: #ff6972;
border-radius: 8px;
display: flex;
margin-bottom: 5px;
}
nav .row:nth-child(2){
background-color:#3d98ff ;
}
nav .row:nth-child(3){
background-color:#44c522;
}
nav .row:nth-child(4){
background-color:#fc9720;
}
.row3{
flex: 1;
border-left:1px solid #fff;
}
.row div:first-child{
border:0;
}
.hotel {
display: flex;
flex-direction: column;
}
.hotel a{
flex: 1;
text-decoration: none;
font-size:16px;
color:#fff;
line-height: 45px;
text-align: center;
text-shadow: 0 2px 1px rgba(0,0,0,.3);
}
.hotel a:first-child{
border-bottom: 1px solid #fff;
}
.row em {
height:45px;
display: block;
font-style: normal;
text-align: center;
line-height: 45px;
}
.row i {
display: block;
width: 71px;
height: 57px;
margin: -6px auto 5px;
background: url(img/tu.png) no-repeat -1px -242px;
}
.row div {
height: 100%;
flex: 1;
border-right: 1px solid #fff;
}
/*返回顶部模块*/
.goBack{
position: fixed;
width:38px;
height:38px;
bottom: 50px;
right:360px;
border:1px solid #ccc;
border-radius: 50%;
line-height: 38px;
font-size:14px;
text-align: center;
display: none;
}
.goBack b{
font-family: 'icomoon';
font-style: normal;
color:#ccc;
font-size:18px;
}
.footer{
width:100%;
height:1000px;
background-color: pink;
}
</style>
<script src="js/animate.js" ></script>
<script src="js/index.js"></script>
</head>
<body>
<!--返回顶部模块-->
<div class="goBack"><b></b></div>
<!--搜索框-->
<div class="top">
<div class="search">
<i></i>
<span>请输入内容</span>
</div>
<div class="user">
<em></em>
</div>
</div>
<!--焦点图-->
<header class="focus">
<ul>
<li><img src="img/bg3.png" /></li>
<li><img src="img/bg1.png" /></li>
<li><img src="img/bg2.png" /></li>
<li><img src="img/bg3.png" /></li>
<li><img src="img/bg1.png" /></li>
</ul>
<ol>
<li class="current"></li>
<li></li>
<li></li>
</ol>
</header>
<nav>
<div class="row">
<div>
<a href="#">
<em>酒店</em>
<i></i>
</a>
</div>
<div class="row3 hotel">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="row3 hotel">
<a href="#">团购</a>
<a href="#">同福客栈</a>
</div>
</div>
<div class="row">
<div>
<a href="#">
<em>酒店</em>
<i></i>
</a>
</div>
<div class="row3 hotel">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="row3 hotel">
<a href="#">团购</a>
<a href="#">同福客栈</a>
</div>
</div>
<div class="row">
<div>
<a href="#">
<em>酒店</em>
<i></i>
</a>
</div>
<div class="row3 hotel">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="row3 hotel">
<a href="#">团购</a>
<a href="#">同福客栈</a>
</div>
</div>
<div class="row">
<div class="row3 hotel">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="row3 hotel">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="row3 hotel">
<a href="#">团购</a>
<a href="#">同福客栈</a>
</div>
</div>
</nav>
<div class="footer"></div>
</body>
</html>
附-index.js
<script>
window.addEventListener("load",function(){
//1.获取元素
var focus=document.querySelector(".focus");
var ul=focus.children[0];
var ol=focus.children[1];
//获取focus的宽度
var w=focus.offsetWidth;
//2.开启定时器,滚动图片
var index=0;
var timer=setInterval(function(){
index++;
var translatex=-index*w;
ul.style.transition="all 0.3s";
ul.style.transform="translateX("+translatex+"px)";
},2000)
ul.addEventListener("transitionend",function(){
if(index>=3){
index=0;
ul.style.transition="none";
var translatex=-index*w;
ul.style.transform="translateX("+translatex+"px)";
}else if(index<0){
index=2;
ul.style.transition="none";
var translatex=-index*w;
ul.style.transform="translateX("+translatex+"px)";
}
//3.小圆点跟随变化
ol.querySelector(".current").classList.remove("current");
ol.children[index].classList.add("current");
})
//4.手指滑动轮播图
var startX=0;
var moveX=0;
var flag=false;
ul.addEventListener("touchstart",function(e){
startX=e.targetTouches[0].pageX;
clearInterval(timer);
})
ul.addEventListener("touchmove",function(e){
moveX=e.targetTouches[0].pageX-startX;
var translatex=-index*w+moveX;
ul.style.transition="none";
ul.style.transform="translateX("+translatex+"px)";
flag=true;
})
ul.addEventListener("touchend",function(e){
if(flag=true){
if(Math.abs(moveX)>100){
if(moveX>0){
index--;
}else{
index++;
}
var translatex=-index*w;
ul.style.transition="all .3s";
ul.style.transform="translateX("+translatex+"px)";
}else{
var translatex=-index*w;
ul.style.transition="all .5s";
ul.style.transform="translateX("+translatex+"px)";
}
}
//手指离开清除定时器
clearInterval(timer);
timer=setInterval(function(){
index++;
var translatex=-index*w;
ul.style.transition="all 0.3s";
ul.style.transform="translateX("+translatex+"px)";
},2000)
})
//返回顶部模块制作
var goBack=document.querySelector(".goBack");
var nav=document.querySelector("nav");
window.addEventListener("scroll",function(){
if(window.pageYOffset>=nav.offsetTop){
goBack.style.display="block";
}else{
goBack.style.display="none";
}
})
goBack.addEventListener("click",function(){
window.scroll(0,0);
})
})
</script>
2-3 click延时解决方案
移动端click事件会有300ms的延时,原因是移动端屏幕双击会缩放(double tap to zoom)页面。
解决方案:
-
禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300ms的点击延迟。
-
利用touch事件自己封装这个事件解决300ms延迟。
原理就是:
- 当我们手指触摸屏幕,记录当前触摸事件
- 当我们手指离开屏幕,用离开的时间减去触摸的时间
- 如果时间小于150ms,并且没有滑动过屏幕,那么我们就定义为点击
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hcefnr1p-1575368198497)(image/jm/162.png)]
这两个方法都不常用,一般用fastclick插件,如下
- 使用插件。fastclick插件解决300ms延迟。
3.移动端常用开发插件
3-1 什么是插件
移动端要求的是快速开发,所以我们经常会借助于一些插件来帮我们完成操作,那么什么是插件呢?
js插件是js文件,他遵循一定规范编写,方便程序展示效果,拥有特定动能且方便调用。如轮播图和瀑布流插件。
特点:他一般是为了解决某个问题而专门存在,其功能单一,并且比较小。我们以前写的animate.js也算一个简单的插件
fastclick插件解决300ms延迟。使用延时,GitHub官网地址:https://github.com/ftlabs/fastclick
使用过程:打开网址-找到lib文件 -打开fastclick.js文件-把里面的内容复制到一个js文件中并引用,最后在下面的body的script写上:
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
代码验证:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width: 200px;
height: 200px;
background-color: pink;
}
</style>
<script src="js/fastclick.js" ></script>
</head>
<body>
<div></div>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
var div=document.querySelector("div");
div.addEventListener("click",function(){
alert(11);
})
</script>
</body>
</html>
3-2 其他移动端常见的插件
superslider:http://www.superslide2.com
iscroll: https://github/cubiq/iscoll
swiper中文网网址:https://www.swiper.com.cn
3-3 插件的使用总结
4.移动端常用开发框架
4-1框架概述
框架顾名思义就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照所规定的某种规范进行开发。
插件一般是为了解决某个问题而专门存在,其功能单一,并且比较小。
前端常用的框架有bootstrap、vue、angular、react等,技能开发pc端,也能开发移动端
前端常用的移动插件有swiper、superslide、iscroll等。
框架:大而全,一整套解决方案
插件:小而专一,某个功能的解决方案
4-2 bootstrap
bootstrap是一个简洁、直观、强悍的前端开发框架,它让web开发更迅速、简单。它能开发pc端,也能开发移动端
bootstrap js插件使用步骤:
- 引入相关js文件(一定先引用jQuery文件)
- 复制html结构
- 修改对应样式
- 修改相应js参数
六、本地存储
目标:
- 能够写出sessionStorage数据的存储以及获取
- 能够写出localStorage数据的存储以及获取
- 能够说出他们两者的区别
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,html5规范的提出了相关解决方案
本地存储特性:
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage约5m、localStorage约20m
- 只能存储字符串,可以将对象JSON.stringfy()编码后存储
1.window.sessionStorage
特点:
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
存储数据:sessionStorage.setItem(“key”,value);
获取数据:sessionStorage.getItem(”key“);
删除数据:sessionStorage.removeItem(“key”);
删除所有数据:sessionStorage.clear();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="del">清空所有数据</button>
<script>
//1.获取元素
var input=document.querySelector("input");
var set=document.querySelector(".set");
var get=document.querySelector(".get");
var re=document.querySelector(".remove");
var del=document.querySelector(".del");
set.addEventListener("click",function(){
var value=input.value;
sessionStorage.setItem("uname",value);
sessionStorage.setItem("password",value);
})
get.addEventListener("click",function(){
console.log(sessionStorage.getItem("uname"));
})
re.addEventListener("click",function(){
sessionStorage.removeItem("uname");
})
del.addEventListener("click",function(){
sessionStorage.clear();
})
</script>
</body>
</html>
2.window.localStorage
特点:
- 生命周期永久生效,除非手动删除否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
存储数据:locationStorage.setItem(“key”,value);
获取数据:locationStorage.getItem(”key“);
删除数据:locationStorage.removeItem(“key”);
删除所有数据:locationStorage.clear();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="del">清空所有数据</button>
<script>
//1.获取元素
var input=document.querySelector("input");
var set=document.querySelector(".set");
var get=document.querySelector(".get");
var re=document.querySelector(".remove");
var del=document.querySelector(".del");
set.addEventListener("click",function(){
var value=input.value;
localStorage.setItem("uname",value);
})
get.addEventListener("click",function(){
console.log(localStorage.getItem("uname"));
})
re.addEventListener("click",function(){
localStorage.removeItem("uname");
})
del.addEventListener("click",function(){
localStorage.clear();
})
</script>
</body>
</html>
记住用户名案例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text" id="uname"> <input type="checkbox" id="remeber">记住用户名
<script>
//获取元素
var uname=document.getElementById("uname");
var remeber=document.getElementById("remeber");
if(localStorage.getItem("uname")){
uname.value=localStorage.getItem("uname");
remeber.checked=true;
}
remeber.addEventListener("change",function(){
if(this.checked){
localStorage.getItem("username",username.value)
}else{
localStorage.removeItem("username");
}
})
</script>
</body>
</html>
iv>
附-index.js
})
#### 2-3 click延时解决方案
移动端click事件会有300ms的延时,原因是移动端屏幕双击会缩放(double tap to zoom)页面。
解决方案:
- 禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300ms的点击延迟。
<meta name="viewport" content="user-scalable=no">
- 利用touch事件自己封装这个事件解决300ms延迟。
原理就是:
- 当我们手指触摸屏幕,记录当前触摸事件
- 当我们手指离开屏幕,用离开的时间减去触摸的时间
- 如果时间小于150ms,并且没有滑动过屏幕,那么我们就定义为点击
[外链图片转存中...(img-Hcefnr1p-1575368198497)]
这两个方法都不常用,一般用fastclick插件,如下
- 使用插件。fastclick插件解决300ms延迟。
### 3.移动端常用开发插件
#### 3-1 什么是插件
移动端要求的是快速开发,所以我们经常会借助于一些插件来帮我们完成操作,那么什么是插件呢?
js插件是js文件,他遵循一定规范编写,方便程序展示效果,拥有特定动能且方便调用。如轮播图和瀑布流插件。
特点:他一般是为了解决某个问题而专门存在,其功能单一,并且比较小。我们以前写的animate.js也算一个简单的插件
fastclick插件解决300ms延迟。使用延时,GitHub官网地址:https://github.com/ftlabs/fastclick
使用过程:打开网址-找到lib文件 -打开fastclick.js文件-把里面的内容复制到一个js文件中并引用,最后在下面的body的script写上:
```html
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
代码验证:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{
width: 200px;
height: 200px;
background-color: pink;
}
</style>
<script src="js/fastclick.js" ></script>
</head>
<body>
<div></div>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
var div=document.querySelector("div");
div.addEventListener("click",function(){
alert(11);
})
</script>
</body>
</html>
3-2 其他移动端常见的插件
superslider:http://www.superslide2.com
iscroll: https://github/cubiq/iscoll
swiper中文网网址:https://www.swiper.com.cn
3-3 插件的使用总结
4.移动端常用开发框架
4-1框架概述
框架顾名思义就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照所规定的某种规范进行开发。
插件一般是为了解决某个问题而专门存在,其功能单一,并且比较小。
前端常用的框架有bootstrap、vue、angular、react等,技能开发pc端,也能开发移动端
前端常用的移动插件有swiper、superslide、iscroll等。
框架:大而全,一整套解决方案
插件:小而专一,某个功能的解决方案
4-2 bootstrap
bootstrap是一个简洁、直观、强悍的前端开发框架,它让web开发更迅速、简单。它能开发pc端,也能开发移动端
bootstrap js插件使用步骤:
- 引入相关js文件(一定先引用jQuery文件)
- 复制html结构
- 修改对应样式
- 修改相应js参数
六、本地存储
目标:
- 能够写出sessionStorage数据的存储以及获取
- 能够写出localStorage数据的存储以及获取
- 能够说出他们两者的区别
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,html5规范的提出了相关解决方案
本地存储特性:
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage约5m、localStorage约20m
- 只能存储字符串,可以将对象JSON.stringfy()编码后存储
1.window.sessionStorage
特点:
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
存储数据:sessionStorage.setItem(“key”,value);
获取数据:sessionStorage.getItem(”key“);
删除数据:sessionStorage.removeItem(“key”);
删除所有数据:sessionStorage.clear();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="del">清空所有数据</button>
<script>
//1.获取元素
var input=document.querySelector("input");
var set=document.querySelector(".set");
var get=document.querySelector(".get");
var re=document.querySelector(".remove");
var del=document.querySelector(".del");
set.addEventListener("click",function(){
var value=input.value;
sessionStorage.setItem("uname",value);
sessionStorage.setItem("password",value);
})
get.addEventListener("click",function(){
console.log(sessionStorage.getItem("uname"));
})
re.addEventListener("click",function(){
sessionStorage.removeItem("uname");
})
del.addEventListener("click",function(){
sessionStorage.clear();
})
</script>
</body>
</html>
2.window.localStorage
特点:
- 生命周期永久生效,除非手动删除否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
存储数据:locationStorage.setItem(“key”,value);
获取数据:locationStorage.getItem(”key“);
删除数据:locationStorage.removeItem(“key”);
删除所有数据:locationStorage.clear();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="del">清空所有数据</button>
<script>
//1.获取元素
var input=document.querySelector("input");
var set=document.querySelector(".set");
var get=document.querySelector(".get");
var re=document.querySelector(".remove");
var del=document.querySelector(".del");
set.addEventListener("click",function(){
var value=input.value;
localStorage.setItem("uname",value);
})
get.addEventListener("click",function(){
console.log(localStorage.getItem("uname"));
})
re.addEventListener("click",function(){
localStorage.removeItem("uname");
})
del.addEventListener("click",function(){
localStorage.clear();
})
</script>
</body>
</html>
记住用户名案例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text" id="uname"> <input type="checkbox" id="remeber">记住用户名
<script>
//获取元素
var uname=document.getElementById("uname");
var remeber=document.getElementById("remeber");
if(localStorage.getItem("uname")){
uname.value=localStorage.getItem("uname");
remeber.checked=true;
}
remeber.addEventListener("change",function(){
if(this.checked){
localStorage.getItem("username",username.value)
}else{
localStorage.removeItem("username");
}
})
</script>
</body>
</html>