<script type="null">
alert('我是编程语言,用来控制电脑网页弹出你好'); alert('我是编程语言,用来控制电脑网页弹出你好');
</script>
各个浏览器的js引擎也不相同,所以也会有兼容行问题。
<!-- 1.行内式的js 直接写到元素内部 -->
<input type="button" value="唐伯虎" onclick="alert('秋香姐')">
<script>
// alert('沙漠骆驼');
</script>
<!-- 3.外部js写法 双标签 -->
<script src="my.js"></script>
javascript标签中无需写代码,否则会被忽略!


let命令,用来声明局部变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,而且有暂时性死区的约束。题目1:
var a = 99; // 全局变量a
f(); // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。
console.log(a); // a=>99, 此时是全局变量的a
function f() {
console.log(a); // 当前的a变量是下面变量a声明提升后,默认值undefined
var a = 10;
console.log(a); // a => 10
}
// 输出结果:
undefined
10
99
在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围。
例如:
{
var i = 9;
}
console.log(i); // 9
ES6新增的let,可以声明块级作用域的变量。
{
let i = 9; // i变量只在 花括号内有效!!!
}
console.log(i); // Uncaught ReferenceError: i is not defined
let非常适合用于 for循环内部的块级作用域。JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域,用let声明的变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。看一个常见的面试题目:
for (var i = 0; i <10; i++) {
setTimeout(function() { // 同步注册回调函数到 异步的 宏任务队列。
console.log(i); // 执行此代码时,同步代码for循环已经执行完成
}, 0);
}
// 输出结果
10 共10个
// 这里面的知识点: JS的事件循环机制,setTimeout的机制等
如果把 var改成 let声明:
// i虽然在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // i 是循环体内局部作用域,不受外界影响。
}, 0);
}
// 输出结果:
0 1 2 3 4 5 6 7 8 9
用let声明的变量,不存在变量提升。而且要求必须 等let声明语句执行完之后,变量才能使用,不然会报Uncaught ReferenceError错误。
console.log(aicoder); // 错误:Uncaught ReferenceError ...
let aicoder = 'aicoder.com';
// 这里就可以安全使用aicoder
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
let不允许在相同作用域内,重复声明同一个变量。否则报错:
Uncaught SyntaxError: Identifier ‘XXX’ has already been declared
例如:
let a = 0;
let a = 'sss';
// Uncaught SyntaxError: Identifier 'a' has already been declared
ES6的let让js真正拥有了块级作用域,也是向这更安全更规范的路走,虽然加了很多约束,但是都是为了让我们更安全的使用和写代码。
在计算机科学中,字面量(Literal)是在计算机中描述 事/物
| 方法 | 说明 | 归属 |
|---|---|---|
| alert(msg) | 浏览器弹出警示框 | 浏览器 |
| console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
| prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
| doucument.write() | 页面输出内容,识别标签 | 浏览器 |
注意:
alert主要用来显示消息给用户,console.log()用来给程序员查看自己运行时的消息。
prompt取过来的值是字符类型的
var myfirstname = 99,
kjlj = 54;
| 情况 | 说明 | 结果 |
|---|---|---|
| var age;console.log(age); | 只声明不赋值 | undefined(未定义) |
| console.log(age); | 不声明,不赋值,直接使用 | 报错 |
| age = 10;console.log(age); | 不声明,只赋值 | 10 |
字母,数字,下划线,美元符号组成关键字,保留字命名:var,fo,while驼峰命名,首字母小写,后面单词的首字母大写:myFirstName有道注意:常量不允许重新赋值,声明的时候必须赋值(初始化)
小技巧:不需要重新赋值的数值用const
let - 现在实际开发的声明方式(2022)
var - 以前的声明变量的方式,会有很多问题(2019)
const -类似于let ,但是变量值无法被修改
简单数据类型(Number,String,Boolean,Underfined,Null)引用数据类型(object)| 简单数据类型 | 说明 | 默认值 | typeof结果 |
|---|---|---|---|
| Number | 数字型,包含整型值和浮点型值,如:21,0.21 | 0 | |
| Booolean | 布尔值类型,如true,false,等价于0,1 | false | |
| symbol | 定义的值具有唯一性 | ||
| string | 字符串类型 | “” | |
| Undefined | var a;声明了变量a,但没有给值,此时a=undefined | undefined | undefined |
| Null | var a= null;声明了变量a为空值 | null | object |
isNaN():这个方法用来判断非数字,并且返回一个值,如果是数字返回 false ,如果不是返回的是true。
Infinity,无穷大-Infinity, 无穷小Number.Max_Value,数字型最大值Number.Min_Value,数字型最小值NaN,缩写:not a number,代表一个非数值 //1.八进制 0~7
var num1 = 010;
console.log(num1);
//2.十六进制 0~9 a~f
var num2 = 0x9;
console.log(num2);
//数字型最大值
console.log(Number.MAX_VALUE);
//无穷大
console.log(Number.MAX_VALUE * 2); //Infinity
//数字型的最小值
console.log(Number.MIN_VALUE);
//无穷小
console.log(Number.MIN_VALUE * 2); //-Infinity
//非数字 NaN
NaN代表一个计算错误。它是一个不正确的或者未定义的数学操作所到的的结果
NaN是
粘性的。任何对NaN的操作都会返回NaN在Js中八进制前面加
0,十六进制前面加0X
未定义是比较特殊的类型,只有一个值 undefined.
html使用双引号,js推荐使用单引号| 转义符 | 解释说明 |
|---|---|
| \n | 换行符 |
| \ | 斜杠| |
| ’ | '单引号 |
| ‘’ | ''双引号 |
| \t | tab缩进 |
| \b | 空格,b是blank的意思 |
注意事项:
- 引号必须成对出现
- 单引号和双引号可以相互嵌套,口诀
外双内单,或者外单内双- 必要时可以使用转义符
\,输出单引号或双引号
1、对象(Object)类型,是一组由键、值组成的无序集合;数据类型 object
2、数组(Array)类型,是一组按顺序排列的数据的集合;数据类型 object
3、函数(Function)类型,是一段具有特定功能的代码块。数据类型 function
场景:+运算符可以实现字符串的拼接。
口诀:数字相加,字符相连
<script>
//1.检测获取字符串的长度 length
var str = 'my name is andy';
console.log(str.length); //15
//2.字符串拼接+,'数值相加,字符相连'
console.log('沙漠' + '骆驼');
console.log('小李' + 18 + '岁');
var age = 18;
console.log('小李' + age + '岁');
console.log(24 + 24); //48
</script>
反引号··${}包住变量 <script>
let age = 18
document.write(`我今年${age}岁了`)
var nan = 10 ,nv = 44;
console.log(`本班男生${nan}人,女生${nv}人,共计${nan + nv}人`);
</script>

某些运算符(除加法四则运算),if条件被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换。
+ 号两边只要有一个是字符串,就会把另外一个转成字符串(拼接)+号作为正号解析可以转换成字符串类型加法:操作数是number型;
操作数是undefined,null,boolean,隐式调用
Number()进行数据类型的转换
| 方式 | 说明 | 案例 |
|---|---|---|
| toString() | 转换成字符串 | var vm = 1;alert(num.toString()) |
| String()强制转换 | 转换成字符串 | var num =1;slert(String(num)); |
| 加号 拼接字符串 | 和字符串拼接的结果都是字符串 | var num =1;alert(num+“我是字符串”) |
<script>
// 1.把数字类型转换为字符串型 变量.toString()
var num = 10;
var str = num.toString();
console.log(str);
console.log(typeof str);
// 2.利用String(变量)
console.log(String(num));
//3.利用+拼接字符串的方法实现转换效果,隐式转换
console.log(num + '');
</script>
| 方式 | 说明 | 案例 |
|---|---|---|
| parselnt(string) | 将stirng类型转成整数数值型 | parselnt(‘78’) |
| parseFloat(string) | 将string类型转换成浮点数数值型 | parseFloat(‘78.21’) |
| Number()强制转换函数 | 将string类型转换成数值型 | Number(‘12’) |
| js隐式转换(. * / ) | 利用算数运算隐式转换为数值型 | ‘12’-0 |
空,否定的值会被转换成false,如''(空字符串),0,NAN,null,underfined""+1,结果是"1"0 NaN| 方式 | 说明 | 案例 |
|---|---|---|
| Boolean()函数 | 其他类型转换成布尔值 | Boolean(‘true’) |

var num = 0
++num
var num = 0
num++
| 运算符名称 | 说明 | 案例 | 结果 |
|---|---|---|---|
| == | 判断号(会转型) | 37 == 37 | true |
| === !== | 全等要求值和数据类型都一致 | 37 === ‘37’ | false |
| 逻辑运算符号 | 说明 | 案例 |
|---|---|---|
| && | 逻辑与,and | true&&false |
| || | 逻辑或,or | true||or |
| ! | 逻辑非,not | !true |
| 赋值运算符号 | 说明 | 案例 |
|---|---|---|
| = | 直接赋值 | var user=‘sss’ |
| +=,-= | 加,减一个数后再赋值 | var age=10;age+=5;//5 |
| * =,/=,%= | 乘,除,取模后赋值 | var age=2;age * =5//10 |
| 优先级 | 运算符 | 顺序 |
|---|---|---|
| 1 | 小括号 | () |
| 2 | 一元运算符 | ++,-,! |
| 3 | 算数运算符 | 先 * / %后+ - |
| 4 | 关系运算符 | > >= < <= |
| 5 | 相等运算符 | == != === !== |
| 6 | 逻辑运算符 | **先&& 后 |
| 7 | 赋值运算符 | = |
| 8 | 逗号运算符 | . |
注意:
&&的权重比||高
比较运算符 : > ,< >= , <= ,== ,!=, =, !,返回值是布尔类型
- 都是number型,大小进行比较
- 都是string型,按位按照
ASCII表1进行比较- number,string :隐式调用Number()把string 转为number进行计算
==:值相等===:值相等,数据类型相同
console.log(2 > "100"); //false "100"转为 100 与2进行比较
console.log("234" > "100"); //true 这种比较为ASCII码比较,依次取每个字符,字符转为ASCII码进行比 较
console.log("15" > "9"); //false
console.log(15 > 9); //ture
console.log(12 == "12"); //true
console.log(1 == true); //ture Number(true)转换成1
console.log(0 === false); //false
console.log(0 == undefined); //false Number(undefined)转换成NaN
console.log(0 == ""); //true
console.log(0 == " "); //true
算术运算符:+,-,*,/,%,++,–,**
console.log(1 + 133); //134
console.log(1 + "133"); //1133
console.log(1 - "133"); //-132
console.log(1 - "abc"); //NAN 直接是非数字类型
逻辑运算符:隐式调用Boolean()判断真假
0,false,null,undefined,NaN,""这些为假&&:返回第一个假值,运用(短路原则)会返回第一个假值||: 返回第一个真值(短路原则)
var num = 10, bool = true, str = "abc";
console.log(num && bool && 0); //0
console.log(num && str); //"abc"
console.log(bool && str); //"abc"
console.log(0 && str); //0
console.log(false && num); //false
console.log(undefined && num); //undefined
console.log(str && false); //false
console.log(0 && ""); //0
console.log("" && 0); // ""
console.log(num || bool || 0); //10
console.log(num || str); //10
console.log(bool || str); //true
console.log(0 || str); //"abc"
console.log(false || num); //10
console.log(undefined || num); //10
console.log(str || false); //10
console.log(0 || ""); //"" 没真值,只能返回第二个
console.log("" || 0); //0
取反:!
真变假,假变真
var num = 10, bool = true, str = "abc";
console.log(!true); //false
console.log(!0); //true
console.log(!str); //false
短路的代码不会执行
console.log(str && num++); //10 && 期望返回第一个假值,没有假值,就返回最后一个真值,两个都是真值,返回第二个num++
console.log(num); //11
console.log(false && ++num); //false
console.log(num); //11 被短路的代码不运行了,所以还是11
console.log(num++ || 0); //11 最后做自增运算 12
console.log(0 || ++num); //13
console.log(0 || str > num); //fales 返回 str>num 的结果NaN
console.log(num); //13
let x = 7
3+4
num++
区别:
表达式:表达式可以被求值,所以它可以写在赋值语句的右侧
语句:而语句不一定有值,比如alert()for 和break等语句就不能用于赋值。
<script>
//1. if 的语法结构
// if (条件表达式) {
// //执行语句
// }
if (3 > 5) {
alert('沙漠骆驼');
}
</script>
条件表达式?表达式1:表达式2
<script>
var time = prompt('输入数字')
var resule = time < 10 ? '0' + time : time;
alert(resule);
</script>
<script>
switch (表达式) {
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
default:
执行最后的语句
}
掌握 for 循环语句,让程序具备重复执行能力
for 是 JavaScript 提供的另一种循环控制的话句,它和 while 只是语法上存在差异。
<script>
// 1. 语法格式
// for(起始值; 终止条件; 变化量) {
// // 要重复执行的代码
// }
// 2. 示例:在网页中输入标题标签
// 起始值为 1
// 变化量 i++
// 终止条件 i <= 6
for(let i = 1; i <= 6; i++) {
document.write(`<h${i}>循环控制,即重复执行<h${i}>`)
}
</script>
变化量和死循环,for 循环和 while 一样,如果不合理设置增量和终止条件,便会产生死循环。
跳出和终止循环
<script>
// 1. continue
for (let i = 1; i <= 5; i++) {
if (i === 3) {
continue // 结束本次循环,继续下一次循环
}
console.log(i)
}
// 2. break
for (let i = 1; i <= 5; i++) {
if (i === 3) {
break // 退出结束整个循环
}
console.log(i)
}
</script>
结论:
JavaScript 提供了多种语句来实现循环控制,但无论使用哪种语句都离不开循环的3个特征,即起始值、变化量、终止条件,做为初学者应着重体会这3个特征,不必过多纠结三种语句的区别。for循环,当不明确循环的次数的时候推荐使用while循环注意:
for的语法结构更简洁,故for循环的使用频次会更多。
利用循环的知识来对比一个简单的天文知识,我们知道地球在自转的同时也在围绕太阳公转,如果把自转和公转都看成是循环的话,就相当于是循环中又嵌套了另一个循环。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zRS58H6S-1655862279964)(./assets/universe.gif)]
实际上 JavaScript 中任何一种循环语句都支持循环的嵌套,如下代码所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qoIQphAC-1655862279964)(assets/1647918261399.png)]
// 1. 外面的循环 记录第n天
for (let i = 1; i < 4; i++) {
document.write(`第${i}天 <br>`)
// 2. 里层的循环记录 几个单词
for (let j = 1; j < 6; j++) {
document.write(`记住第${j}个单词<br>`)
}
}
记住,外层循环循环一次,里层循环循环全部
// 外层打印几行
for (let i = 1; i <= 5; i++) {
// 里层打印几个星星
for (let j = 1; j <= i; j++) {
document.write('★')
}
document.write('<br>')
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z74pPmVT-1655862279965)(assets/1647918678956.png)]
样式css
span {
display: inline-block;
width: 100px;
padding: 5px 10px;
border: 1px solid pink;
margin: 2px;
border-radius: 5px;
box-shadow: 2px 2px 2px rgba(255, 192, 203, .4);
background-color: rgba(255, 192, 203, .1);
text-align: center;
color: hotpink;
}
javascript
// 外层打印几行
for (let i = 1; i <= 9; i++) {
// 里层打印几个星星
for (let j = 1; j <= i; j++) {
// 只需要吧 ★ 换成 1 x 1 = 1
document.write(`
<div> ${j} x ${i} = ${j * i} </div>
`)
}
document.write('<br>')
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IP5OTaAf-1655862279965)(assets/1647918734677.png)]
知道什么是数组及其应用的场景,掌握数组声明及访问的语法。
<script>
// 1. 语法,使用 [] 来定义一个空数组
// 定义一个空数组,然后赋值给变量 classes
// let classes = [];
// 2. 定义非空数组
let classes = ['小明', '小刚', '小红', '小丽', '小米']
</script>
通过 [] 定义数组,数据中可以存放真正的数据,如小明、小刚、小红等这些都是数组中的数据,我们这些数据称为数组单元,数组单元之间使用英文逗号分隔。
<script>
var arry = new Array(); //创建了个一空数组
</script>
<script>
var arr = []; //创建了一个空数组
var arr1 = [1, 2, 'pingk老师', true];
//数组里面的数据一定要逗号隔开
//数组里面的数据比如,1,2,我们称为数组元素。
</script>
<script>
var arr = new Array(2);//这个2表示数组长度为2,里面有两个空值
var arr1 = new Array(2,3);//等价于[2,3]
console.log(arr1);
</script>
1.数组的索引
console.log(arr1[2]);
<script>
var arr = [];
var obj ={};
console.log(arr instanceof Array);//true
console.log(ogj instanceof Array);//false
</script>
console.log(Array.isArray(arr));//true
<script>
var arr = ['red', 'green', 'blue'];
for (var i = 0; i <= 2; i++) {
console.log(arr[i]);
}
</script>
<script>
var max = 1;
var arr = [1, 2, 3, 66, 78, 234, 123, 12, 345, 435];
for (var i = 0; i <= arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
console.log(max);
<script>
var str = '';
var arr = ['red', 'blue', 'green'];
var step = '|'
for (var i = 0; i < arr.length; i++) {
str += arr[i] + step;
}
console.log(str);
</script>
<script>
var arr = ['red', 'green', 'blue'];
for (var i = 0; i <= arr.length; i++) {
console.log(arr[i]);
}
</script>
<script>
var arr = ['red', 'blue', 'green'];
console.log(arr.length);
arr.length = 5; //数组长度修改为5
console.log(arr);//修改后最后两个元素没有给值,所以是undefined
</script>
<script>
var arr1 = ['red', 'blue', 'green'];
arr1[3] = 'pink';
console.log(arr1);
arr1[0] = 'yellow'; //替换原来的数组元素
</script>
<script>
var arr = [2, 0, 1, 22, 121, 454, 3, 35, 435, 45];
var newArry = [];
var j = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= 10) {
newArry[j] = arr[i];
j++;
}
}
console.log(newArry);
</script>
<script>
var arr1 = [2, 0, 1, 22, 121, 454, 3, 35, 435, 45];
var newArry1 = [];
for (var i = 0; i < arr.length; i++) {
if (arr1[i] >= 10) {
newArry1[newArry1.length] = arr[i];
}
}
console.log(newArry1);
</script>
数组做为对象数据类型,不但有 length 属性可以使用,还提供了许多方法:
使用以上4个方法时,都是直接在原数组上进行操作,即成功调任何一个方法,原数组都跟着发生相应的改变。并且在添加或删除单元时 length 并不会发生错乱。
<script>
// 定义一个数组
let arr = ['html', 'css', 'javascript']
// 1. push 动态向数组的尾部添加一个单元
arr.push('Nodejs')
console.log(arr)
arr.push('Vue')
// 2. unshit 动态向数组头部添加一个单元
arr.unshift('VS Code')
console.log(arr)
// 3. splice 动态删除任意单元
arr.splice(2, 1) // 从索引值为2的位置开始删除1个单元
console.log(arr)
// 4. pop 删除最后一个单元
arr.pop()
console.log(arr)
// 5. shift 删除第一个单元
arr.shift()
console.log(arr)
</script>
<body>
<script>
let arr = [6, 23, 1, 56, 78, 86]
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
//开始交换
if (arr[j] > arr[j + 1]) {
//交换两个变量
let temp = arr[j + 1]
arr[j + 1] = arr[j]
arr[j] = temp
}
}
}
console.log(arr);
</script>
</body>
注意:一共需要的趟数是 arr. length-1,每一趟需要交换的次数是 arr.length -i - 1。i是外侧循环
<script>
var arr = [1, 2, 3, 4, 5]
console.log(arr);
// forEach 遍历
arr.forEach(function (v, i) {
// console.log(v);
// console.log(i);
})
//push向数组末尾添加一个或者多个元素,会改变原数组
arr.push("a", "b", "10")
console.log(arr);
//every() 当元素全部满足条件的时候返回true,有一个不满足就会返回false
var result = arr.every(function (v, i) {
return v > 5;
})
//some()只要有一个满足就返回true
console.log(result);
var result1 = arr.some(function (v, i) {
return v > 5;
})
console.log(result1);
//splice(位置(元素下标),删除的元素个数) 删除 会影响原数组
arr.splice(2, 2)
console.log(arr);
//findIndex返回满足条件的元素,首次出现的位置 ,如果没有就返回-1
var result2 = arr.findIndex(function (v, i) {
return v == 5;
})
console.log(result2);
//join() 把数组转换成字符串,不会影响原数组
console.log(arr.join("-"));
//filter() 过滤 返回满足条件的元素,构成新数组
var result3 = arr.filter(function (v, i) {
return v < 5;
})
console.log(result3);
//map() 映射
var result4 = arr.map(function (v, i) {
return v * 4
})
console.log(result4);
</script>

<script>
//函数
function getSum(num1, nmu2) {
var sun = 0;
for (var i = num1; i <= nmu2; i++) {
sun += i;
}
console.log(sun);
}
getSum(1, 100)//调用函数
</script>
funcation fn(){}
fn()
没有名字的函数,无法直接使用。
使用方式:
函数表达式。 let fn = function(){
//函数体
}
//方式一
(function () { console.log(11); }());
//方式二
(function () { console.log(11); })();
//不需要调用,立即执行
(function (x, y) { console.log(x + y); })(1, 2);
注意:多个立即执行函数需要用分号
;隔开
注意:
函数表达式和具名函数不同,如果是具名函数,那它的调用可以用在任何位置(函数体上下都可以)
函数表达式不行,因为let的关系,只能在声明后才可以调用。
<script>
function 函数名() {
函数体
}
</script>
函数名();
形参 function 函数名(形参1, 形参2...) {
}
实参 函数名(实参1, 实参2...);
<script>
function getSum(num1, nmu2) {
console.log(num1 + num2);
}
getSum(1, 2); //实参个数和形参个数一致,正常输出结果
getSum(1, 2, 3); //实参个数多于形参的个数,会取到形参的个数
getSum(1); //形参可以看作是不用声明的变量, num2是一个变量但是没有接收值 结果就是undefined
</script>
注意:
- 实参多于形参, 多的不参与运算,多的会保存到
arguments对象中(数组类型)- 实参少于形参,少的就时undefined
retuen 终止函数,retuen后面的代码不会被执行。 function 函数名() {
return 需要返回的结果;
}
function fn() {
return 20;
}
console.log(fn())
注意:当函数(fn)调用时,相当于调用者 fn( ) = 返回值
console.log( fu( ) )才能拿着到20
函数有返回值时,就返回该值,没有返回值就返回 undefined
全局作用域:整个script标签,或者是单独的js文件全局有效
局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字就只在函数内部起效果。局部有效
注意:
变量有一个坑
如果函数内部,变量没有声明,直接赋值,也会当全局变量来看,但是强烈不推荐。
用var声明的和不用var声明的(不推荐)形参属于局部变量全局变量只有浏览器关闭时才会销毁,比较占用内存资源局部变量当程序执行完毕就会销毁,节约内存资源就近原则)在能够访问到的情况下,先局部,局部没有在找全局预解析 代码执行var 还有funcation提升到当前作用域的最前面,进行提前声明和定义.函数声明提升到当前作用域提升前面,不调用函数。 <script>
console.log(num); //错误
var num = 10;
//相当于执行以下代码
var num;
console.log(num);
num = 10;
</script>
<script>
fun(); //错误
var fun = function() {
console.log(22);
}
//相当于执行以下代码
var fun;
fun();
fun = function() {
console.log(22);
}
</script>
<script>
//案例一
var num = 10;
fun();
function fun() {
console.log(num);//undefined
var num = 20;
}
//相当于执行以下操作
var num;
function fun() {
var num;
console.log(num);
num = 20;
}
num = 10;
fun();
</script>
<script>
//案例二
var num = 10;
function fn() {
console.log(num);
var num = 20;
console.log(num);
}
fun();
//相当于执行以下操作
var num;
function fn() {
var num;
console.log(num); //undefinde
num = 20;
console.log(num); //20
}
num = 10;
fun();
</script>
alert(a); //a函数
var a = 1;
alert(a); //1
function a() {
return false;
}
//相当于执行
var a;
function a(){
return false;
}
alert(a);
a = 1;
alert(a);
注意:
同级时,
函数的优先级高于变量
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a); //undefined
console.log(b); //9
var a = '123';
}
//相当于执行
var a ;
funcation f1(){
var b;
var a;
b = 9;
console.log(a);
console.log(b);
a = '123';
}
f1();
<script>
//案例四
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
//相当于执行以下操作
function f1() {
var a;
a = b = c = 9;
//相当于 var a=9 ; b = 9 ; c = 9 ;b和c没有 var声明,当全局变量来看
//集体声明 var a = 9 ,b =9, c = 9;
console.log(a); //9
console.log(b); //9
console.log(c); //9
}
f1();
console.log(c); //9
console.log(b); //9
console.log(a); //报错 undefined
</script>
花括号{}里面包含了表达这个具体事物的对象和方法。 <script>
var obj = {
uname: '李宇',
age: 18,
sex: '男',
sayHi: function drink() {
console.log('drink');
}
}
console.log(obj.age);
</script>
new object 创建对象 var obj1 = new Object();
obj1.uname = 'zzkj';
obj1.age = 18;
ocj1.sex = 'bna';
obj1.sayh = function() {
console.log(hi);
}
console.log(obj1.uname);
console.log(obj1['sex']);
obj1.sayh();
function Star(uname, sex) {
this.uname = uname;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
var ldh = new Star('刘德华', '男'); //调用函数返回对象。
ldh.sing('并与');
构造函数创建对象构造函数首字母要大写。 function 构造函数名() {
this.属性 = 值;
this.方法 = function() {}
}
new 构造函数名();
<script>
//1.构造函数在内存中创建了一个空的对象
//2.this 就会指向刚才创建的空对象
//2.执行构造函数里面的代码,给这个空对象添加属性和方法。
//4.返回这个对象。
function Star(uname, sex) {
this.uname = uname;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
var ldh = new Star('刘德华', '男'); //调用函数返回对象。
ldh.sing('并与');
</script>
<script>
var obj = {
name: 'pink老师',
age: 18,
sex: '男',
fn: function() {}
}
// for in 遍历我们的对象
for (var k in obj) {
console.log(k); //k代表的属性名,方法名
console.log(obj[k]); //得到的是里面的属性值
}
</script>
exec() 方法用于检索字符串中的正则表达式的匹配。
如果字符串中有匹配的值返回该匹配值,否则返回 null。
RegExpObject.exec(string)
| 参数 | 描述 |
|---|---|
| string | Require The string to be searched |
var str="Hello world!";
//查找"Hello"
var patt=/Hello/g;
var result=patt.exec(str);
document.write("返回值: " + result);
//查找 "RUNOOB"
patt=/RUNOOB/g;
result=patt.exec(str);
document.write("<br>返回值: " + result);
Returned value: Hello
Returned value: null
<script>
console.log(Math.PI); //圆周率
console.log(Math.max(1, 9, 3, 4)); //9
console.log(Math.max(-1, -10)); //-1
console.log(Math.max(-1, 'pingk')); //NAN
console.log(Math.max()); //-Inginity
</script>
<script>
var Mymath = {
PI: 3.141592653,
max: function() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
},
min: function() {
var min = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] < min) {
min = arguments[i];
}
}
return min;
}
}
console.log(Mymath.PI);
console.log(Mymath.max(1, 5, 9));
console.log(Mymath.min(1, 5, 9));
</script>
console.log(Math.abs(1)); //1
console.log(Math.abs(-1)); //1
console.log(Math.abs('-1')); //隐式转换,会把字符串型-1转换成1
console.log(Math.abs('pink')); //NAN
Math.floor() //向下取整 往小了的取值
Math.ceil() //向上取整,往最大了取值
console.log(Math.round(1.9)); //2
console.log(Math.round(-1.5)); //这个结果是-1
console.log(Math.round(-1.6)); //这个结果是-2
console.log(Math.random());
<script>
console.log(Math.random());
//得到两个数之间的随机整数,包括这两个数
//Math.floor(Math.random()*(max - min + 1)) + min;
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandom(1, 10));
//5.随机点名
var arr = ['这姑娘三', '里斯', '李书记', '时看见立刻'];
console.log(arr[getRandom(1, 3)]);
</script>
<script>
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;//跳出循环
}
}
var arr = new Array(); //创建了一个数组对象
var obj = new Object(); //创建了一个对象实例
//1. 使用Date,没有参数,返回当前系统的当前时间
var date = new Date();
console.log(date);
//2. 参数常用写法,数字型 2019 ,10 , 01或者是 字符串类型 '2019-10-1 8:8:8'
var date1 = new Date(2019, 10, 1);
console.log(date1); //返回11月,不是10月
var date2 = new Date('2019-10-1 8:8:8');
console.log(date2);
console.log(date.getMonth() + 1);
var datas = date.getDate();
var day = date.getDay();
var date = new Date();
//2022年3月9日星期三
var year = date.getFullYear();
var moth = date.getMonth() + 1;
var datas = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', ];
var day = date.getDay();
console.log('今天是:' + year + '年' + moth + '月' + datas + '日 ' + arr[day]);
今天是:2022年3月9日星期三
Date.getHours():时
Date.getMinutes():分
Date.getSeconds():秒
function getTime() {
var time = new Date();
var h = time.getHours();
var h = h < 10 ? '0' + h : h;
var m = time.getMinutes();
var m = m < 10 ? '0' + m : m;
var s = time.getSeconds();
return h + ':' + m + ':' + s;
var s = s < 10 ? '0' + s : s;
}
console.log(getTime());
| 计算公式 | 解释说明 |
|---|---|
| d = parselnt(总秒数/60/60/24) | 计算天数 |
| h = parselnt(总秒数/60/60%24) | 计算小时 |
| m = parselnt(总秒数/60%60) | 计算分数 |
| s = parselnt(总秒数%60) | 计算当前秒数 |
<script>
function conutDown(time){
var nowTime = +new Date();//返回当前时间总毫秒数
var inputTime = +new Date(time);//返回用户输入时间总的毫秒数
var times = (inputTime - nowTime)/1000;//剩余时间总的秒数
var d = parseInt(times/60/60/24);
d = d<10?'0'+d:d;
var h = parseInt(times/60/60%24);
h = h<10?'0'+h:h;
var m = parseInt(times/60%60);
m = m<10?'0'+m:m;
var s = parseInt(times%60);
s = s<10?'0'+s:s;
return d+'天'+h+'时'+m+'分'+s+'秒';
}
console.log(conutDown('2022-3-10 22:00:00'));
</script>
| 方法名 | 说明 | 返回值 |
|---|---|---|
| push(参数1…) | 末尾添加一个或者多个元素,注意修改原数组 | 并返回新的长度 |
| pop() | 删除数组最后一个元素,把数组长度减1无参数,修改原数组 | 返回它删除的元素的值 |
| unshift(参数1…) | 向数组的开头添加一个或者多个元素,注意修改原数组 | 并返回新的长度 |
| shift() | 删除数第一个元素,把数组长度减1无参数,修改原数组 | 并返回第一个元素的值 |
var arr = [1,2,3];
// 尾添加
// arr.push(4,'liyu');//push添加末尾
console.log(arr.push(4,'liyu'));//5
console.log(arr);//输出数组
//头添加
console.log(arr.unshift('red','purple'));
// arr.unshift('red','purple');
console.log(arr);
//尾删除,一次只能删除一个元素
//返回删除的那个元素
console.log(arr.pop());
console.log(arr);
//头删除,一次只能删除一个元素
console.log(arr.shift());
console.log(arr);
<script>
var arr= [1500,1200,2100,1800];
var newArry = [];
for (var i = 0;i<arr.length;i++){
if(arr[i]<2000){
newArry.push(arr[i]);
}
}
console.log(newArry);
</script>
(3) [1500, 1200, 1800]0: 15001: 12002: 1800length: 3[[Prototype]]: Array(0)
| 方法名 | 说明 | 是否修改原数组 |
|---|---|---|
| reverse() | 颠倒数组中元素的顺序,无参数 | 该方法会改变原来数组,返回新数组 |
| sort() | 对数组元素进行排序 | 该方法会改变原来数组,返回新数组 |
<script>
//翻转数组
var arr = ['pink','red','pink']
arr.reverse();
console.log(arr);
//数组排序(冒泡排序)
var arr1=[1,3,4,2,5,6];
arr1.sort(function(a,b){
// return a - b;//按照升序排序
return b - a;//按照降序排序
});
console.log(arr1);
</script>
注意:当使用 b-a 时,说明后面的大,是降序。使用a-b时,说明前面大,是升序(默认)
| 方法名 | 说明 | 返回值 |
|---|---|---|
| indexOf() | 数组中查找给指定元素的第一个索引 | 如果存在,返回索引号,如果不存在,则返回-1 |
| lastIndex() | 在数组中的最后一个索引 | 如果存在返回索引号 如果不存在,则返回-1 |
<script>
//它只返回第一个满足条件的索引号
var arr = ['red','blue','pink','blue']
console.log(arr.indexOf('blue'));//返回1
console.log(arr.indexOf('green'));//返回-1
console.log(arr.lastIndexOf('blue'));//返回3
console.log(arr.lastIndexOf('green'));//返回-1
</script>
<script>
// var arr = ['c','a','x','a','c','b','z','c','c'];
function unique(arr){
var newArry = [];
for (var i = 0;i< arr.length;i++){
if(newArry.indexOf(arr[i]) === -1){
newArry.push(arr[i]);
}
}
return newArry;
}
var demo = unique(['c','a','x','a','c','b','z','c','c'])
console.log(demo);
</script>
| 方法名 | 说明 | 返回值 |
|---|---|---|
| toString() | 把数组转换成字符串,逗号分隔没一项 | 返回一个字符串 |
| join(‘分隔符’) | 方法用于把数组中得到所有元素转换成一个字符串 | 返回一个字符串 |
<script>
//1.toString数组转换为字符串
var arr = [1,2,3];
console.log(arr.toString());//1,2,3
//2.join(分隔符)
console.log(arr.join('-'));
</script>
1,2,3
数组转换为字符串.html:13 1-2-3
//基本包装类型
var str = 'andy';
console.log(str.length);
//对象才有属性和方法,复杂数据类型里才有属性和方法
//简单数据类型里为何有length属性呢?
//(1)把简单数据类型包装为复杂数据类型
var temp = new String('andy');
//(2)把临时变量值给str
str = temp;
// (3) 销毁这个临时变量
temp = null;
| 方法名 | 说明 |
|---|---|
| indexOf(‘要查找的字符’,开始的位置) | 返回指定内容,在元字符串中的位置,如果找不到就返回-1,开始的位置是Index索引号 |
| LastIndexOf() | 从后往前找,只找第一个匹配的 |
<script>
//字符串对象 根据字符串返回位置 str.indexOf('要查找的字符串',[起始位置])
var str = '改革春风吹满地,春天来了';
console.log(str.indexOf('春'));//2
console.log(str.indexOf('春',3));//8
</script>
<body>
<script>
var str = "abscedsljposdfosdsof";
var index = str.indexOf('o');
console.log(index);
while(index != -1){
console.log(index);
str.indexOf('o',index+1);
}
</script>
</body>
| 方法名 | 说明 | 使用 |
|---|---|---|
| charAt(index) | 返回指定位置的字符(index 字符串的索引号) | str.charAt(0) |
| charCodeAt(index) | 获取指定位置处字符的ASCII码(index索引号) | str.charCodeAt(0) |
| str[index] | 获取指定位置处字符 | HTML5,IE8支持,和charat(等效) |
<script>
//1. charAt('index')
var str = 'andy';
console.log(str.charAt(3));
//遍历所有字符
for(var i=0;i<str.length;i++){
console.log(str.charAt(i));
}
//2.charCodeAt(index)返回相应索引号的字符ASCII值,目的:判断用户按下哪个键
console.log(str.charCodeAt(0)); //97
//3.str[index] H5新增
console.log(str[0]);//a
</script>
<script>
//用一个对象来判断是否
// var o = {
// age:18
// }
// if (o['age']) {
// console.log('里面有属性');
// }else{
// console.log('里面没有此属性');
// }
var str = 'asfHKjkajdkfjakjhfkjahdf';
var o = {};
for (var i= 0;i<str.length;i++){
var chars = str.charAt(i)//chars是字符串的每一个字符
if(o[chars]){
o[chars]++;
}else{
o[chars] = 1;
}
}
console.log(o);
var max = 0;
var ch = '';
//遍历对象
for(var k in o){
//k得到的数属性名
//o[k]得到的是属性值
if(o[k] >max){
max = o[k];
ch = k;
}
}
console.log(k+':'+max);
</script>
ObjectH: 1K: 1a: 4d: 2f: 4h: 2j: 5k: 4s: 1[[Prototype]]: Object
h:5
| 方法名 | 说明 |
|---|---|
| concat(st) | concat()方法用于连接两个或者多个字符串,拼接字符串,等效于+,+更常用 |
| substr(start,length) | 从start位置开始(索引号),length取的个数,重点记住这个 |
| slice(start,end) | 从start位置开始,截取到end位置,end取不到(他们两都是索引号) |
| substring(start,end) | 从start位置开始,截取到end位置,end取不到,基本和slice相同,但是不接受负值 |
| replace(‘被替换字符’,‘替换为的字符’) | 它只会替换第一个字符 |
| split(‘分割符’) | 字符转换为数组,前面我们学过join把数组转换成字符串 |
| replace(‘被替换字符’,‘替换为的字符’) | 它只会替换第一个字符 |
| toUpperCase() | 转换大写 |
| toLowerCase() | 转换小写 |
script写到标签下面<body>
<div id = "time">2019-09-09</div>
<script>
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer);
console.dir(timer);
</script>
</body>
2019-09-09
object
div#time
集合,以伪数组的形式存储<body>
<ul>
<li>支付方式覅哈哈1</li>
<li>支付方式覅哈哈2</li>
<li>支付方式覅哈哈3</li>
<li>支付方式覅哈哈4</li>
<li>支付方式覅哈哈5</li>
</ul>
<ol id="ol">
<li>支付方式1</li>
<li>支付方式2</li>
<li>支付方式3</li>
<li>支付方式4</li>
<li>支付方式5</li>
</ol>
<script>
//1. 返回的是 获取过来元素对象的集合,一伪数组的形式存储
var list = document.getElementsByTagName('li');
console.log(list);
console.log(list[0]);
//2. 依次打印里面的元素对象
for(var i=0;i<list.length;i++){
console.log(list[i]);
}
//3.如果页面中只有一个li返回都是伪数组
//4.页面中没有这个元素,返回的是空的伪数组
//5.element.getElementsByTagName('标签名')
// var ol = document.getElementsByTagName('ol')
var ol = document.getElementById('ol');
console.log(ol.getElementsByTagName('li'));
</script>
</body>
getElementsByClassName:根据类名获得某些元素的集合querySelector:返回指定选择器的`第一个元素对象.切记,里面的选择器要加符号: .box #navquerySelectorAll:返回指定选择器的所有对象的集合<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>产品</li>
<li>产品</li>
</ul>
</div>
<script>
var box = document.getElementsByClassName('box');//返回伪数组
console.log(box);
var firstBox = document.querySelector('.box');
console.log(firstBox);
var nav = document.querySelector('#nav')
console.log(nav);
var li = document.querySelector('li')
console.log(li);
var allBox = document.querySelectorAll('.box');
console.log(allBox);
</script>
</body>
获取body标签 var bodeEle = document.body;
console.log(bodeEle);
console.dir(bodeEle);
获取html元素 var htmlEle = document.documentElement;
console.log(htmlEle);
<body>
<button id="btn">离开家离开</button>
<script>
var btn = document.getElementById('btn')
btn.onclick = function(){
alert('点秋香');
}
</script>
</body>
| 属性 | 说明 |
|---|---|
| element.innerText | 从起始内容到终点内容,但它去除html标签,同时空格和换行也会去掉 |
| element.innerHTML | 起始位置到终点位置的全部内容,包含html标签,同时保留空格和换行(W3C推荐) |
<body>
<button>显示当前时间</button>
<div>某个时间</div>
<p>11243</p>
<script>
//点击按钮,div里面会变化
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.onclick = function () {
div.innerText = getDate();
}
function getDate() {
var date = new Date();
//2022年3月9日星期三
var year = date.getFullYear();
var moth = date.getMonth() + 1;
var datas = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六',];
var day = date.getDay();
return '今天是:' + year + '年' + moth + '月' + datas + '日 ' + arr[day];
}
//获取标签
var p = document.querySelector('p');
p.innerText = getDate();
</script>
</body>
<style>
img {
display: block;
}
</style>
<body>
<button id="p1">图片一</button>
<button id="p2">图片二</button>
<img src="./1.jpg" alt="老照片" title="柏林">
<script>
var p1 = document.getElementById('p1');
var p2 = document.getElementById('p2');
var img = document.querySelector('img');
p2.onclick = function () {
img.src = './2.jpg';
img.title = '莫斯科';
}
p1.onclick = function () {
img.src = './1.jpg';
img.title = '柏林';
}
</script>
</body>
<style>
img {
width: 300px;
}
div {
margin-top: 12px;
height: 13px;
font-size: 16px;
}
</style>
<body>
<img src="./1.jpg" alt="">
<div>上午好</div>
<script>
var img = document.querySelector('img');
var div = document.querySelector('div');
var date = new Date();
var h = date.getHours();
if (h < 12) {
img.src = './2.jpg';
// div.innerHTML('好好写代码')错误写法!!!
div.innerHTML = '好好写代码'
} else if (h < 18) {
img.src = './1.jpg';
div.innerHTML = '下午好好写代码';
} else if (h < 24) {
img.src = './2.jpg';
div.innerHTML = '晚上好好写代码';
}
</script>
</body>
<body>
<button>按钮</button>
<input type="text" value="输入内容">
<script>
//1.获取元素
var btn = document.querySelector('button');
var input = document.querySelector('input');
//2.注册事件
btn.onclick = function () {
// input.innerHTML = '点击了'; 不起作用
//表单里面的值是通过value修改的
input.value = '点击了';
//如果想让某个表单被禁用,不能点击用disabled我们想要这个按钮button按钮
// btn.disabled = true;
// this 是指向事件函数的调用者btn
this.disabled = true;
}
</script>
</body>
<style>
.box {
width: 400px;
border-bottom: 1px solid #ccc;
margin: 100px auto;
}
.box input {
width: 370px;
height: 30px;
border: 0;
outline: none;
}
</style>
<body>
<div class="box">
<button>显示</button>
<input type="password" name="" id="pwd">
</div>
<script>
var btn = document.querySelector('button');
var input = document.getElementById('pwd')
var flag = 0;
btn.onclick = function () {
if (flag == 0) {
input.type = 'text';
btn.innerHTML = '隐藏';
flag = 1;
} else {
input.type = 'password';
btn.innerHTML = '显示';
flag = 0;
}
}
</script>
</body>
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
<body>
<div></div>
<script>
var div = document.querySelector('div');
div.onclick = function () {
//里面的属性采取驼峰命名法
this.style.backgroundColor = 'red';
this.style.width = '300px';
}
</script>
</body>
注意 :1.JS里面的样式采取驼峰命名,比如:fontSize. 2.JS修改style样式操作,产生的是行内样式,css权重比较高。 <style>
.box {
position: relative;
height: 88px;
border: 1px solid #ccc;
margin: 100px auto;
font-size: 12px;
text-align: center;
color: #f40;
}
.box img {
width: 60px;
margin-top: 5px;
}
.close-btn {
position: absolute;
top: -1px;
left: 16px;
width: 14px;
height: 14px;
border: 1px solid #ccc;
line-height: 14px;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
cursor: pointer;
}
</style>
<body>
<div class="box">
<img src="./1.jpg" alt="">
<div class="close-btn">x</div>
</div>
<script>
var box = document.querySelector('.box');
var btn = document.querySelector('.close-btn');
btn.onclick = function () {
box.style.display = 'none';
}
</script>
</body>
| 属性 | 说明 |
|---|---|
| onfocus | 获得焦点 |
| onblur | 失去焦点 |
<body>
<input type="text" value="手机">
<script>
//1.获取元素
var text = document.querySelector('input');
text.onfocus = function () {
// console.log('得到了焦点');
if (this.value === '手机') {
this.value = '';
}
//获得焦点需要变黑(文字)
this.style.color = '#333';
}
text.onblur = function () {
// console.log('失去了焦点');
if (this.value === '') {
this.value = '手机';
}
his.style.color = '#999';
}
</script>
</body>
className会直接覆盖原来的类名,如果想要保存原来的类名 <style>
.first {
width: 300px;
height: 300px;
background-color: pink;
}
.change {
background-color: purple;
color: #fff;
font-size: 25px;
margin-top: 100px;
}
</style>
<body>
<div class="first">文本</div>
<script>
var text = document.querySelector('div');
text.onclick = function () {
// this.style.backgroundColor = 'skyblue';
//当前元素的类名改为change
this.className = 'change';//注意不加点
// 如果想要保存原来的类名
this.className = 'fisrt change';
}
</script>
</body>
<style>
div {
width: 600px;
margin: 100px auto;
}
.message {
display: inline-block;
font-size: 12px;
color: #999;
background: url() no-repeat left center;
padding-left: 20px;
}
.wrong {
color: red;
background-image: url();
}
</style>
<body>
<div class="register">
<input type="password" class="ipt">
<p class="message">请输入6~16位密码</p>
</div>
<script>
var ipt = document.querySelector('.ipt');
var message = document.querySelector('.message');
ipt.onblur = function () {
//根据表单里面
if (this.value.length < 6 || this.value.length > 16) {
message.className = 'wrong message';
message.innerHTML = '您输入的位数不对';
}
}
</script>
</body>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
var btn = document.getElementsByTagName('button');
//btn得到的是为数组,里面的每个一元素btn[i]
for (var i = 0; i < btn.length; i++) {
btn[i].onclick = function () {
//1.先把所有按钮的背景颜色去掉
for (var i = 0; i < btn.length; i++) {
btn[i].style.backgroundColor = '';
}
//2.让当前背景颜色为pink
this.style.backgroundColor = 'pink';
}
}
</script>
</body>
| 属性 | 说明 |
|---|---|
| onmouseover | 鼠标经过 |
| onmouseout | 鼠标离开 |
<script>
// 1. 全选和取消全选做法: 让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
// 获取元素
var j_cbAll = document.getElementById('j_cbAll'); // 全选按钮
var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); // 下面所有的复选框
// 注册事件
j_cbAll.onclick = function() {
// this.checked 它可以得到当前复选框的选中状态如果是true 就是选中,如果是false 就是未选中
console.log(this.checked);
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].checked = this.checked;
}
}
// 2. 下面复选框需要全部选中, 上面全选才能选中做法: 给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的, 上面全选就不选中。
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].onclick = function() {
// flag 控制全选按钮是否选中
var flag = true;
// 每次点击下面的复选框都要循环检查者4个小按钮是否全被选中
for (var i = 0; i < j_tbs.length; i++) {
if (!j_tbs[i].checked) {
flag = false;
break; // 退出for循环 这样可以提高执行效率 因为只要有一个没有选中,剩下的就无需循环判断了
}
}
j_cbAll.checked = flag;
}
}
</script>
<body>
<div id="demo" index="1" class="nav"></div>
<script>
var div = document.querySelector('div');
// 1. 获取元素的属性值
// (1) element.属性
console.log(div.id);
//(2) element.getAttribute('属性') get得到获取 attribute 属性的意思 我们程序员自己添加的属性我们称为自定义属性 index
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
// 2. 设置元素属性值
// (1) element.属性= '值'
div.id = 'test';
div.className = 'navs';//改的是div的class
// (2) element.setAttribute('属性', '值'); 主要针对于自定义属性
div.setAttribute('index', 2);
div.setAttribute('class', 'footer'); // class 特殊 这里面写的就是class 不是className
// 3 移除属性 removeAttribute(属性)
div.removeAttribute('index');
</script>
</body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(50000)</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">
商品评价(50000)模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
<script>
// 获取元素
var tab_list = document.querySelector('.tab_list');
var lis = document.querySelectorAll('li');
var item = document.querySelectorAll('.item');
//for循环绑定点击事件
for (var i = 0; i < lis.length; i++) {
//给某 个li设定索引号
lis[i].setAttribute('index', i);
lis[i].onclick = function () {
//干掉所有人,其余的li清楚class这个类
for (var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
//留下我自己
this.className = 'current ';
//下面模块显示内容
var index = this.getAttribute('index');
// console.log(index);
//排他思想,让其余item这些div隐藏
for (var i = 0; i < item.length; i++) {
item[i].style.display = 'none';
}
item[index].style.display = 'block';
}
}
</script>
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div = document.querySelector('div');
// console.log(div.getTime);//自定义属性不能取到
console.log(div.getAttribute('getTime'));
div.setAttribute('data-time', 20);
console.log(div.getAttribute('data-index'));
console.log(div.getAttribute('data-list-name'));
// h5新增的获取自定义属性的方法 它只能获取data-开头的
// dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset['index']);
// 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
逻辑性强,兼容性差HTML,DOM树中的所有节点都可以通过javaScript来进行访问,所有的html都可以被修改,也可以被创建和删除.一般的,节点至少拥有node Type(节点类型),nodename(节点名称)和nodeValue(节点值)这3个基本属性
<script>
// 1. 父节点 parentNode
var erweima = document.querySelector('.erweima');
// var box = document.querySelector('.box');
// 得到的是离元素最近的父级节点(亲爸爸) 如果找不到父节点就返回为 null
console.log(erweima.parentNode);
</script>
<script>
// DOM 提供的方法(API)获取
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
// 1. 子节点 childNodes 所有的子节点 包含 元素节点 文本节点等等
console.log(ul.childNodes);
console.log(ul.childNodes[0].nodeType);
console.log(ul.childNodes[1].nodeType);
// 2. children 获取所有的子元素节点 也是我们实际开发常用的
console.log(ul.children);
</script>
返回第一个子元素节点,ie9才支持,找不到就返回null返回最后一个子元素<body>
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
<li>我是li5</li>
</ol>
<script>
var ol = document.querySelector('ol');
// 1. firstChild 第一个子节点 不管是文本节点还是元素节点
console.log(ol.firstChild);
console.log(ol.lastChild);
// 2. firstElementChild 返回第一个子元素节点 ie9才支持
console.log(ol.firstElementChild);
console.log(ol.lastElementChild);
// 3. 实际开发的写法 既没有兼容性问题又返回第一个子元素
console.log(ol.children[0]);
//最后一个元素的索引号
console.log(ol.children[ol.children.length - 1]);
</script>
</body>
ie9以上才支持
| 属性 | 说明 | 兼容性 |
|---|---|---|
| node.nextSibling | 下个兄弟节点 | 都可以使用 |
| node.previousSibling | 上个兄弟节点 | 都可以使用 |
node.nextElementSibling | 下个兄弟(元素)节点 | IE9才支持 |
| node.previousElementSibling | 上个兄弟(元素)节点 | IE9才支持 |
var div = document.querySelector('div');
console.log(div.nextSibling);
console.log(div.previousSibling);
console.log(div.nextElementSibling);
console.log(div.previousElementSibling);//unll
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
解决方法:
如果想要第一个元素的子节点,可以使用parentNode.children[0]
如果想要最后一个子元素节点,可以使用parentNode.childern[parentNode.chilren.length - 1]
创建节点动态产生的,所以我们也称为动态创建元素节点。var li = document.createElement('li');
括号内的参数里面永远是标签名比如
li,div,p,span
后面追加元素 类似于数组中的pushul.appendChild(li);
指定节点的前面,类似于css里面的before伪元素。var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
<body>
<textarea name="" id=""></textarea>
<button>发布</button>
<ul>
</ul>
<script>
// 1. 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2. 注册事件
btn.onclick = function () {
if (text.value == '') {
alert('抱歉,没有输入内容')
} else {
// console.log(text.value);
var li = document.createElement('li');
li.innerHTML = text.value;
ul.insertBefore(li, ul.children[0]);
}
}
</script>
</body>
s光标定到输入框,按下enter留言发布。注意点:
获取ul节点,然后通过ul.innerHTML+(凭借好的字符串)实现元素的添加,innerHTML是识别标签的。
使用bootstrap框架
Date对象的使用
添加keyup,用来监听键盘按键
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"
integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
crossorigin="anonymous"></script>
<body>
<div class="container" style="padding-top: 100px;">
<textarea class="form-control" rows="5" placeholder="请留言"></textarea>
<button type="button" class="btn btn-success">发布</button>
<ul class="list-group" style="margin-top: 20px;">
</ul>
<div class="alert alert-warning alert-dismissible" role="alert" style="height: 49px; display: none;">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true" class="sp">×</span>
</button>
<strong>错误!</strong>你最好输入一些东西后再按按钮
</div>
</div>
</body>
</body>
<script>
var date = new Date();
var year = date.getFullYear();
var moth = date.getMonth() + 1;
var datas = date.getDate();
var btn = document.querySelector("button")
var text = document.querySelector("textarea")
var alerts = document.querySelector(".alert")
var ul = document.querySelector('ul');
var span = document.querySelector(".sp")
//对时间进行格式化
function getTime() {
var thme = new Date();
var h = thme.getHours();
var h = h < 10 ? '0' + h : h
var m = thme.getMinutes();
var m = m < 10 ? '0' + m : m
var s = thme.getSeconds()
var s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
//按钮点击
btn.addEventListener('click', function () {
if (text.value.length == 0) {
alerts.style.display = "block"
} else {
var li = document.createElement('li');
var str = `<li class="list-group-item">${text.value} <span class="date">${year}.${moth}.${datas}-${getTime()}</span><a href="javascript:;">×</a> </li>`
ul.innerHTML = str + ul.innerHTML
//1. 获取所有的a标签
//2. 添加点击事件
//3. 通过a找到父节点li,移除节点方法移除
// for (let i = 0; i < deletea.length; i++) {
// deletea[i].addEventListener('click', function () {
// console.log(this);
// console.log(deletea[i]);
// ul.removeChild(this.parentNode)
// })
// console.log(i);
// deletea[i].onclick = function () {
// console.log(deletea[i]);
// ul.removeChild(this.parentNode)
// }
// }
var deletea = document.querySelectorAll("a");
console.log(deletea);
deletea.forEach(function (item, index) {
item.onclick = function () {
console.log(item);
ul.removeChild(item.parentNode)
}
})
for (let i = 0; i < deletea.length; i++) {
deletea[i].onclick = function () {
console.log(this.parentNode);
ul.removeChild(this.parentNode);
}
}
text.value = ""
}
})
//点击后,隐藏报错框
span.addEventListener('click', function () {
alerts.style.display = "none"
})
//添加按键监听
document.addEventListener('keyup', function (e) {
if (e.keyCode == 83) {
text.focus();
} else if (e.keyCode == 13) {
btn.click();
}
})
//删除
/***
* 获取所有的a,循环添加点击事件,this代表当前点击的a
* 1. 全局this,指向window
* 2. 构造函数内部 this 指向实例化的对象
* 3. 事件处理函数中 this
* */
</script>
<style>
body {
background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
}
div {
/* display: flex; */
width: 100%;
height: 100vh;
/* padding: 200px; */
}
textarea {
margin-bottom: 20px;
resize: none;
}
.date {
float: right;
}
</style>

<body>
<button>删除</button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光头强</li>
</ul>
<script>
// 1.获取元素
var ul = document.querySelector('ul');
// 2. 删除元素 node.removeChild(child)
// ul.removeChild(ul.children[0]);
// 3. 点击按钮依次删除里面的孩子
var btn = document.querySelector('button');
btn.onclick = function () {
if (ul.children.length == 0) {
this.disabled = true;
} else {
ul.removeChild(ul.children[0]);
}
}
</script>
</body>
<script>
// 1. 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2. 注册事件
btn.onclick = function() {
if (text.value == '') {
alert('您没有输入内容');
return false;
} else {
// console.log(text.value);
// (1) 创建元素
var li = document.createElement('li');
// 先有li 才能赋值
li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
// (2) 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
// (3) 删除元素 删除的是当前链接的li 它的父亲
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
// node.removeChild(child); 删除的是 li 当前a所在的li this.parentNode;
ul.removeChild(this.parentNode);
}
}
}
}
</script>
| 属性值 | 解释说明 |
|---|---|
| node.cloneNode() | 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容 |
| node.cloneNode(true) | 括号为true 深拷贝 复制标签复制里面的内容 |
<body>
<ul>
<li>1111</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
// 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
</script>
</body>
| 属性 | 说明 |
|---|---|
| element.innerHtml | 当创建多的时候,效率不如createElement()(采用的拼接字符串),创建多个元素效率更高(采用数组形式拼接),结构稍微复杂 |
| document.write() | 直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘 |
| document.createElement() | 创建多个元素效率低一点点,但是结构清晰 |
1.removeChild
| 鼠标事件 | 触发条件 |
|---|---|
| onclick | 鼠标点击左键时触发 |
| onmouseover | 鼠标经过时触发 |
| onmouseout | 鼠标离开时触发 |
| onfocus | 获得鼠标焦点时触发 |
| oninput | 每次输入都会触发(配合表单更佳) |
| onblur | 失去鼠标焦点时触发 |
| onmousemove | 鼠标移动触发 |
| onmousedown | 鼠标按下时触发 |
btns[0].onclick = function()
eventTarget.addEventListener(type,listener[, useCapture])false是冒泡型事件流,也可以是true,这样就会给当前事件添加捕获型事件流。<body>
<button>传统注册事件</button>
<button>方法监听注册事件</button>
<button>ie9 attachEvent</button>
<div>点击我</div>
<script>
var btns = document.querySelectorAll('button');
var div = document.querySelector("div")
// 1. 传统方式注册事件,on+type 缺点:同一事件源,同一事件的唯一性。
btns[0].onclick = function () {
alert('hi');
}
btns[0].onclick = function () {
alert('hao a u');
}
// 2. 事件侦听注册事件 addEventListener ,通过一个事件源中绑定不同的事件处理函数
// (1) 里面的事件类型是字符串 必定加引号 而且不带on
// (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
//第一种注册方式
btns[1].addEventListener('click', function () {
alert('22');
})
btns[1].addEventListener('click', function () {
alert('33');
})
//第二种注册方式,函数外部声明,后引入
div.addEventListener('click', fn, false)
function fn() {
console.log(3);
}
</script>
</body>
btns[2].attachEvent('onclick', function () {
alert('11');
})
function addEventListener(element, evenName, fn) {
//判断当前浏览器是否支持addEventListener 方法
if (element.addEventListener) {
element.addEventListener(eventName, fn);//第三个参数默认时false
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
//相当于element.onclick = fn;
element['on' + eventName] = fn;
}
}
divs[0].onclick = null;
function removeEventListener(element, eventName, fn) {
//判断当前浏览器是否支持removeEventListener方法
if (element.removeEventListener) {
element.removeEventListener(eventName, fn)//第三个参数默认是false
} else if (element.detachEvent) {
element.detachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = null;
}
}
按照特定的顺序传播,这个传播过程即DOM事件流<body>
<div class="father">
<div class="son">
</div>
</div>
<script>
var father = document.querySelector(".father")
var son = document.querySelector(".son")
console.log(father);
console.log(son);
onclick只能是冒泡
on + type
son.onclick = function () {
console.log("son");
}
father.onclick = function () {
console.log("faher");
}
document.body.onclick = function () {
console.log("body");
}
document.documentElement.onclick = function () {
console.log("html");
}
</script>

<body>
<div class="father">
<div class="son">
</div>
</div>
<script>
var father = document.querySelector(".father")
var son = document.querySelector(".son")
console.log(father);
console.log(son);
//如果为true就是捕获,从根节点开始
son.addEventListener('click', function () {
console.log("son");
},true)
father.addEventListener('click', function () {
console.log("father");
},true)
father.parentNode.addEventListener('click', function () {
console.log("body");
},false)
document.documentElement.addEventListener('click', function () {
console.log("html");
},false)
</script>
</body>

注意:
- true在那个元素上,哪个元素的事件流就是捕获
- 上面案例中的dody元素和html元素的事件流是冒泡
- 当父子注册的事件一样时,才会有事件流
捕获阶段当前目标阶段冒泡阶段具体的元素吸收,然后逐级向上传播到DOM最顶层节点的过程。DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程。
onblur,onfocus,onmouseenter,onmouseleave。捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段 document -> html -> body -> father -> son
冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段 son -> father ->body -> html -> document
三个阶段
event 就是一个事件对象 写到我们侦听函数的 小括号里面 当形参来看鼠标的相关信息,鼠标坐标,如果是键盘事件里面就包含的键盘事件的信息 比如 判断用户按下了那个键event、 evt、 ewindow.event 兼容性的写法 e = e || window.event; var div = document.querySelector('div');
div.onclick = function(e) {
// console.log(e);
// console.log(window.event);
// e = e || window.event;
console.log(e);
}
e = e || window.event;
| 事件对象属性方法 | 说明 |
|---|---|
| e.target | 返回触发事件的对象 标准 |
| e.srcElement | 返回触发事件的对象 非标准 ie6-8使用 |
| e.type | 返回事件类型 比如click mouseover 不带on |
| e.cancelBubble | 该属性阻止冒泡 非标准 ie6-8使用 |
| e.returnValue | 该属性阻止默认事件(默认行为) 非标准 ie6 - 8不使用 比如不让链接跳转 |
| e.preventDefault() | 该方法阻止默认事件(默认行为) 标准 比如不让链接跳转 |
| e.stopPropagtion() | 阻止冒泡 标准 |
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
// 我们给ul 绑定了事件 那么this 就指向ul
console.log(this);
console.log(e.target);
// e.target 指向我们点击的那个对象 谁触发了这个事件 我们点击的是li e.target 指向的就是li
})
e.target 点击了哪个元素,就返回哪个元素, this: 哪个元素绑定了这个点击事件,那么就返回谁this是事件绑定的元素,是函数的调用者(绑定这个事件的元素)
e.target是事件触发的元素
让链接不跳转 或者让提交按钮不提交 var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 标准写法
})
// 3. 传统的注册方式
a.onclick = function(e) {
// 普通浏览器 e.preventDefault(); 方法
e.preventDefault();
// 低版本浏览器 ie678 returnValue 属性
e.returnValue;
// 我们可以利用return false 也能阻止默认行为 没有兼容性问题 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
return false;
alert(11);
}
<script>
// 常见事件对象的属性和方法
// 阻止冒泡 dom 推荐的标准 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation(); // stop 停止 Propagation 传播
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
})
</script>
if(e && e.stopPropagation){
e.stopPropagation();
}else {
window.event.cancleBubble = true;
}
e.target进行判断,然后利用冒泡原理影响设置每个子节点。大量元素添加事件,提高性能,减少dom操作
动态创建的元素
<body>
<ul>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
</ul>
<script>
// 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
// alert('知否知否,点我应有弹框在手!');
// e.target 这个可以得到我们点击的对象
e.target.style.backgroundColor = 'pink';
})
</script>
</body>
<body>
ul>li*10{&&} emm语法,快速生成
<ul>
<li>01</li>
<li>02</li>
<li>03</li>
<li>04</li>
<li>05</li>
<li>06</li>
<li>07</li>
<li>08</li>
<li>09</li>
<li>10</li>
</ul>
<script>
//操作dom10次
var lis = document.querySelectorAll("li")
lis.forEach(function (v, i) {
v.onclick = function () {
this.style.color = "red"
}
})
//事件委派,操作dom一次,给父元素添加事件
var ul = document.querySelector("ul")
ul.onclick = function (e) {
e = e || window.event;
e.target.style.color = "red"
console.log(e.target);
}
</script>
</body>
<!-- 事件三要素:
注册事件的方式:on+type,事件监听(兼容性问题)
事件流:捕获阶段,目标阶段,冒泡阶段
事件对象:鼠标事件对象,键盘事件对象
事件委派:冒泡型事件流
1. 大量元素添加事件,提高性能,减少dom操作
2. 动态创建的元素
-->
事件委派的好处
<body>
我是一段不愿意分享的文字
<script>
// 1. contextmenu 我们可以禁用右键菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
// 2. 禁止选中文字 selectstart
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
</script>
</body>
document.addEventListener('selectstart', function (e) {
e.preventDefault();
})
| 鼠标事件对象 | 说明 |
|---|---|
| e.clientX | 返回鼠标相对于浏览器可视区的X坐标 |
| e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
| e.apgeX | 返回鼠标相当于文档页面的X坐标 IE9+支持 |
| e.pageY | 返回鼠标相当于文档页面的Y坐标 IE9+支持 |
| e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
| e.screenY | 返回鼠标先对于电脑屏幕的Y坐标 |
console.log(e.clientX);
console.log(e.clientY);
console.log(e.pageX);
console.log(e.pageY);
console.log(e.screenX);
console.log(e.screenY);
<body>
<img src="./images/angel.gif" alt="">
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove', function (e) {
// 1. mousemove只要我们鼠标移动1px 就会触发这个事件
// console.log(1);
// 2.核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的top和left 值就可以移动图片
var x = e.pageX;
var y = e.pageY;
//3 . 千万不要忘记给left 和top 添加px 单位
pic.style.left = x - 50+ 'px';
pic.style.top = y - 40+ 'px';
});
</script>
</body>
| 键盘事件 | 触发条件 | 使用keycode的情况 |
|---|---|---|
| onkeyup | 某个键盘按键被松开时触发 | 不区分大小写 |
| onkeydown | 某个键盘按键被按下时触发 | 不区分大小写 |
| onkeypress | 某个键盘被按下时触发 但是它不识别功能键 比如: ctrl shift等 | 区分大小写 |
<body>
<script>
// 常用的键盘事件
//1. keyup 按键弹起的时候触发
// document.onkeyup = function() {
// console.log('我弹起了');
// }
document.addEventListener('keyup', function() {
console.log('我弹起了');
})
//3. keypress 按键按下的时候触发 不能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keypress', function() {
console.log('我按下了press');
})
//2. keydown 按键按下的时候触发 能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keydown', function() {
console.log('我按下了down');
})
// 4. 三个事件的执行顺序 keydown -- keypress -- keyup
</script>
</body>
| 键盘对象属性 | 属性 |
|---|---|
| keyCode | 返回该键的ASCII值 |
<body>
<input type="text">
<script>
// 核心思路: 检测用户是否按下了s 键,如果按下s 键,就把光标定位到搜索框里面
// 使用键盘事件对象里面的keyCode 判断用户按下的是否是s键
// 搜索框获得焦点: 使用 js 里面的 focus() 方法
var search = document.querySelector('input');
document.addEventListener('keyup', function (e) {
if (e.keyCode == 83) {
search.focus();
}
});
</script>
</body>
this的指向在函数定义时是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this的最终执向的是那个调用它的对象。
定时器里的this指向window)案例分析:
1. 快递单号输入内容时, 上面的大号字体盒子(con)显示(这里面的字号更大)
2. 表单检测用户输入: 给表单添加键盘事件
3. 同时把快递单号里面的值(value)获取过来赋值给 con盒子(innerText)做为内容
4. 如果快递单号里面内容为空,则隐藏大号字体盒子(con)盒子、
5. 当我们失去焦点,就隐藏这个con盒子
6. 当我们获得焦点,就显示这个con盒子
window对象是浏览器的顶级对象,它具有双重角色。
window.onload = function(){}
或者
window.addEventListener('load', function(){});
window.onload = function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
alert('点击我');
})
}
window.onload = function() {
alert(22);
}
window.addEventListener('load', function () {
var btn = document.querySelector('button');
btn.addEventListener('click', function () {
alert('点击我');
})
})
window.addEventListener('load', function () {
alert(22);
})
document.addEventListener('DOMContentLoaded', function () {}
document.addEventListener('DOMContentLoaded', function () {
alert(33);
})
window.onresise = funcation(){}
或者
window.addEventListener('resize', function() {})
<body>
<script>
window.addEventListener('load', function() {
var div = document.querySelector('div');
window.addEventListener('resize', function() {
console.log(window.innerWidth);
console.log('变化了');
if (window.innerWidth <= 800) {
div.style.display = 'none';
} else {
div.style.display = 'block';
}
})
})
</script>
<div></div>
</body>
window.onresize是调整窗口大小加载事件,当触发时就调用处理函数。
window.setTimeout(调用函数, [延时时间(毫秒)]);
setTimeout(function() {
console.log('爆炸了');
},2000)
function callback() {
console.log('爆炸了');
}
var timer1 = setTimeout(callback, 3000);
var timer2 = setTimeout(callback, 5000);
该方法用于设置一个定时器,该定时器再定时器到期后执行调用函数。
window.clearTimeout(timeout ID)
<body>
<button>点击停止定时器</button>
<script>
var btn = document.querySelector('button');
var timer = setTimeout(function() {
console.log('爆炸了');
}, 5000);
btn.addEventListener('click', function() {
clearTimeout(timer);
})
</script>
</body>
indow.setInterval(调用函数, 延时时间);
setInterval(function() {
console.log('继续输出');
}, 1000);
| 属性 | 区别 |
|---|---|
| setTimeout | 延时时间到了,就去调用这个回调函数,只调用一次 就结束了这个定时器 |
| setInterval | 每隔这个延时时间,就去调用这个回调函数,会调用很多次,重复调用这个函数 |
<body>
<div>
<span class="hour">1</span>
<span class="minute">2</span>
<span class="second">3</span>
</div>
<script>
// 1. 获取元素
var hour = document.querySelector('.hour');
var minute = document.querySelector('.minute');
var second = document.querySelector('.second');
var inputTime = +new Date('2022-3-18 21:00:00');
countDown();//先调用一次函数,防止刚刷新页面有空白。
// 2.开启定时器
setInterval(countDown, 1000);
function countDown() {
var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数
var h = parseInt(times / 60 / 60 % 24); //时
h = h < 10 ? '0' + h : h;
hour.innerHTML = h; // 把剩余的小时给 小时黑色盒子
var m = parseInt(times / 60 % 60); // 分
m = m < 10 ? '0' + m : m;
minute.innerHTML = m;
var s = parseInt(times % 60); // 当前的秒
s = s < 10 ? '0' + s : s;
second.innerHTML = s;
}
</script>
</body>
window.clearInerval(intervalID);
<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('ni hao ma');
}, 1000);
})
stop.addEventListener('click', function() {
clearInterval(timer);
})
</script>
</body>
<body>
手机号码: <input type="number"> <button>发送</button>
<script>
// 按钮点击之后,会禁用 disabled 为true
// 同时按钮里面的内容会变化, 注意 button 里面的内容通过 innerHTML修改
// 里面秒数是有变化的,因此需要用到定时器
// 定义一个变量,在定时器里面,不断递减
// 如果变量为0 说明到了时间,我们需要停止定时器,并且复原按钮初始状态
var btn = document.querySelector('button');
var time = 10;
btn.addEventListener('click', function () {
this.disabled = true;
var timer = setInterval(function () {
if (time == 0) {
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '发送';
time = 10;//这个10需要重新开始
} else {
btn.innerHTML = '还剩下' + time + '秒';
time--;
}
}, 1000)
})
</script>
</body>
同一个时间只能做一件事。这是因为JavaScript这门脚本语言诞生使命所致。同步和异步。执行栈click,resize等load,error等setInterval,setTimeout等(event loop)
执行过程:
- 先执行执行栈中的同步任务
- 异步任务(回调函数)放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行,开始执行。

什么是location对象:
window对象给我们提供了一个location属性用来获取或者设置窗体的url,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象。
protoccol://host[:port]/path/[?query]#fragment
组成
| 组成 | 说明 |
|---|---|
| protocol | 通信协议,常用的http,ftp,maito等 |
| host | 主机(域名)www.itheima.com |
| port | 端口号可选,省略时使用默认端口,如http的默认端口为80 |
| path | 路径由多个’/'符号隔开的字符串 ,一般用来表示主机上的目录或者文件地址 |
| query | 参数,以键值对的形式通过‘&’符合分隔开 |
| fragment | 片段 #后面内容 常见于链接,锚点 |
| location对象属性 | 返回值 |
|---|---|
| location.href | 获取或者设置整个URL |
| location.host | 返回主机(域名) |
| location.port | 返回端口号 如果未写返回空字符串 |
| location.pathname | 返回路径 |
| location.search | 返回参数 |
| location.hash | 返回片段 #后面内容常见于链接 锚点 |
| location.assign() | 跟href一样,可以跳转页面(也称为重定向) |
| location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
| location.reload() | 重新加载页面,相当于刷新页面按钮或者 f5 如果参数为true 强制刷新 ctrl+f5 |
<body>
<button>点击</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// 记录浏览历史,所以可以实现后退功能
// location.assign('http://www.itcast.cn');
// 不记录浏览历史,所以不可以实现后退功能
// location.replace('http://www.itcast.cn');
location.reload(true);
})
</script>
</body>
navigator对象包含有关浏览器的信息,他有很多属性,最常见的就是userAgent,该属性可以用来返回有客户机发送服务器的user-agent头部值。
user-Agent属性
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
| history对象方法 | 作用 |
|---|---|
| back() | 可以后退功能 |
| forward() | 前进功能 |
| go(参数) | 前进后退功能,参数如果是1 前进1个页面,如果是 -1 后退1个页面 |
offset翻译过来就是偏移量,我们使用offset系列相关属性得到元素的位置(偏移),大小等。
| offest系列属性 | 作用 |
|---|---|
| element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级都没有定位,则返回body |
| element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
| element.offsetLeft | 返回元素相对带有定位父元素左方的偏移 |
| element.offsetWidth | 返回自身包括padding,边框,内容区的宽度,返回数值不带单位 |
| element.offsetHeight | 返回自身包括padding,边框,内容区的高度,返回数值不带单位 |
= 核心JS代码
window.addEventListener('load', function () {
var preview_img = document.querySelector('.preview_img');
var mask = document.querySelector('.mask');
var big = document.querySelector('.big');
// 1. 当我们鼠标经过 preview_img 就显示和隐藏 mask 遮挡层 和 big 大盒子
preview_img.addEventListener('mouseover', function () {
mask.style.display = 'block';
big.style.display = 'block';
})
preview_img.addEventListener('mouseout', function () {
mask.style.display = 'none';
big.style.display = 'none';
})
// 2. 鼠标移动的时候,让黄色的盒子跟着鼠标来走
preview_img.addEventListener('mousemove', function (e) {
// (1). 先计算出鼠标在盒子内的坐标
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
// console.log(x, y);
// (2) 减去盒子高度 300的一半 是 150 就是我们mask 的最终 left 和top值了
// (3) 我们mask 移动的距离
var maskX = x - mask.offsetWidth / 2;
var maskY = y - mask.offsetHeight / 2;
// (4) 如果x 坐标小于了0 就让他停在0 的位置
// 遮挡层的最大移动距离
var maskXMax = preview_img.offsetWidth - mask.offsetWidth;
var maskYMax = preview_img.offsetHeight - mask.offsetHeight;
if (maskX <= 0) {
maskX = 0;
} else if (maskX >= maskXMax) {
maskX = maskXMax;
}
if (maskY <= 0) {
maskY = 0;
} else if (maskY >= maskYMax) {
maskY = maskYMax;
}
mask.style.left = maskX + 'px';
mask.style.top = maskY + 'px';
// 3. 大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离
// 大图
var bigIMg = document.querySelector('.bigImg');
// 大图片最大移动距离
var bigMax = bigIMg.offsetWidth - big.offsetWidth;
// 大图片的移动距离 X Y
var bigX = maskX * bigMax / maskXMax;
var bigY = maskY * bigMax / maskYMax;
bigIMg.style.left = -bigX + 'px';
bigIMg.style.top = -bigY + 'px';
})
})
client翻译过来就是客户端,我们使用client系列相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小和元素大小等。
| client系列属性 | 作用 |
|---|---|
| element.clientTop | 返回元素上边框大小 |
| element.clientLeft | 返回元素左边框大小 |
| element.clientWidth | 返回自身包括padding,不含边框,内容区的宽度,返回数值不带单位 |
| element.clientHeight | 返回自身包括padding,不含边框,内容区的高度,返回数值不带单位 |
client 宽度 和我们offsetWidth 最大的区别就是 不包含边框(function(){})()或者
(function () { }())
主要作用:创建一个独立的作用域
<body>
<script>
// 1.立即执行函数: 不需要调用,立马能够自己执行的函数
function fn() {
console.log(1);
}
fn();
// 2. 写法 也可以传递参数进来
// 1.(function() {})() 或者 2. (function(){}());
(function(a, b) {
console.log(a + b);
var num = 10;
})(1, 2); // 第二个小括号可以看做是调用函数
(function sum(a, b) {
console.log(a + b);
var num = 10; // 局部变量
}(2, 3));
// 3. 立即执行函数最大的作用就是 独立创建了一个作用域, 里面所有的变量都是局部变量 不会有命名冲突的情况
</script>
</body>
(function flexible(window, document) {
// 获取的html 的根元素
var docEl = document.documentElement
// dpr 物理像素比
var dpr = window.devicePixelRatio || 1
// adjust body font size 设置我们body 的字体大小
function setBodyFontSize() {
// 如果页面中有body 这个元素 就设置body的字体大小
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
} else {
// 如果页面中没有body 这个元素,则等着 我们页面主要的DOM元素加载完毕再去设置body
// 的字体大小
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10 设置我们html 元素的文字大小
function setRemUnit() {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize 当我们页面尺寸大小发生变化的时候,要重新设置下rem 的大小
window.addEventListener('resize', setRemUnit)
// pageshow 是我们重新加载页面触发的事件
window.addEventListener('pageshow', function (e) {
// e.persisted 返回的是true 就是说如果这个页面是从缓存取过来的页面,也需要从新计算一下rem 的大小
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports 有些移动端的浏览器不支持0.5像素的写法
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
div.addEventListener('scroll', function () {
console.log(div.scrollTop);
})
| scroll系列属性 | 作用 |
|---|---|
| element.scrollTop | 返回被卷去的上侧距离,返回数值不带单位 |
| element.scrollLeft | 返回被卷去的左侧距离,返回数值不带单位 |
| element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
| element.scrollHeight | 返回自身实际的高度,不含边框,返回数值不带单位 |
<script>
// scroll 系列
var div = document.querySelector('div');
console.log(div.scrollHeight);
console.log(div.clientHeight);
div.addEventListener('scroll', function () {
console.log(div.scrollTop);
})
</script>
<script>
//1. 获取元素
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
//一定要写道滚动的外边
var banenrTop = banner.offsetTop;
//当侧边栏固定定位后应该变化的值
var sliderbarTop = sliderbar.offsetTop - banenrTop;
//获取Mian主体元素
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
document.addEventListener('scroll', function () {
//window.pageYOffset 页面被减去的头部
// console.log(window.pageYOffset);
// 3.当页面被卷去的头部大于等于 172 此时,侧边栏就要改为固定定位
if (window.pageYOffset >= 172) {
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';
}
})
</script>
| 三大系列大小对比 | 作用 |
|---|---|
| element.offsetWidth | 返回自身包括padding,边框,内容区的宽度,返回数值不带单位 |
| element.clientWidth | 返回自身包括padding,内容区的宽度,不含边框,返回数值不带单位 |
| element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
注意函数需要传递两个参数,动画对象和移动到的距离。
如果多个元素都是用这个动画效果,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
核心原理:利用JS是一门动态语言,可以很方便的给当前对象添加属性。
<button>运动按钮,点击才走</button>
<div>盒子</div>
<span>小蓝</span>
<script>
var obj = {};
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button')
//用简单动画函数封装 obj目标对象 target 目标位置
//给不同的元素指定不同的定时器
function animate(obj, target) {
//当我们不断的点击按钮,这个元素会越开越快,因为开启了太多的定时器。
//解决方案就是让我们元素只有一个定时器
//先清除之前的计数器,只让一个定时器在走。
clearInterval(obj.timer);
obj.timer = setInterval(function () {
if (obj.offsetLeft >= target) {
//停止动画
// 本质是停止计时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30)
}
//调用函数
animate(div, 500);
btn.addEventListener('click', function () {
animate(span, 400)
})
</script>
<body>
<button>点击夏雨荷才走</button>
<span>夏雨荷</span>
<script>
// 缓动动画函数封装obj目标对象 target 目标位置
// 思路:
// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
function animate(obj, target) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
var step = (target - obj.offsetLeft) / 10;
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
var span = document.querySelector('span');
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// 调用函数
animate(span, 500);
})
</script>
</body>
<body>
<button class="btn500">点击夏雨荷到500</button>
<button class="btn800">点击夏雨荷到800</button>
<span>夏雨荷</span>
<script>
function animate(obj, target, callback) {
// console.log(callback); callback = funcation(){} 调用的时候 callback()
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
//回调函数写在这里
if (callback) {
//调用函数
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function () {
// 调用函数
animate(span, 500);
})
btn800.addEventListener('click', function () {
// 调用函数
animate(span, 800, function () {
// alert('你好吗?')
span.style.backgroundColor = 'pink';
});
})
</script>
</body>
window.addEventListener('load', function () {
//获取元素
var prev = this.document.querySelector('.prev');
var next = this.document.querySelector('.next');
var banner = this.document.querySelector('.banner');
var ul = banner.querySelector('ul');
var img = ul.querySelector('a');
var imgWidth = img.offsetWidth;
//鼠标经过时显示小箭头
banner.addEventListener('mouseenter', function () {
prev.style.display = 'block';
next.style.display = 'block';
clearInterval(timer);
timer = null;//清除定时器变量
})
//鼠标离开小箭头消失
banner.addEventListener('mouseleave', function () {
prev.style.display = 'none';
next.style.display = 'none';
timer = setInterval(function () {
next.click();
}, 3000)
})
//动态生成小圆圈,有几张图片就生成几个
// var ul = banner.querySelector('ul');
var ol = banner.querySelector('ol');
// console.log(img);
// console.log(ul.children.length);
for (var i = 0; i < ul.children.length; i++) {
//创建一个li
var li = this.document.createElement('li');
//记录当前小圆圈的索引号,通过自定义属性来做
li.setAttribute('index', i);
//把li插入到ol里面
ol.appendChild(li);
//小圆圈的排他思想
li.addEventListener('click', function () {
//干掉所有人,把所有的li移除current类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
//留下我自己 当前的li设置 current
this.className = 'current';
//点击小圆圈,移动图片
//ul的移动距离 ,注意是负值,是往左走
var index = this.getAttribute('index');
//当我们点击某个li,就把这个li的索引号给num
num = index;
//当我们点击某个li,就把这个li的索引号给circle
circle = index;
console.log(imgWidth);
animate(ul, - index * imgWidth);
})
}
//把ol里面的第一个li设置类名为 current
ol.children[0].className = 'current';
//克隆第一张图片放到最后
var first = ul.children[0].cloneNode('true');
ul.appendChild(first);
//点击右侧按钮,图片滚动一张
var num = 0;
//circle控制小圆圈的缩放
var circle = 0;
next.addEventListener('click', function () {
//如果走到最后复制一张图片,快速切换回去。
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, - num * imgWidth)
circle++;
//如果circle变成3就需要重置了
// if (circle == ol.children.length) {
// circle = 0;
// }
circle = circle == ol.children.length ? 0 : circle;
//先清除其他小圆圈的current类名
//调用函数
circleChange();
})
//左侧按钮做法
prev.addEventListener('click', function () {
//如果走到最后复制一张图片,快速切换回去。
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * imgWidth + 'px';
// alert(ul.style.left)
}
num--;
animate(ul, -num * imgWidth)
circle--;
//如果circle小于0说明第一张的图片,则小圆圈要改为第四个。
// if (circle < 0) {
// circle = ol.children.length - 1;
// }
circle = circle < 0 ? ol.children.length - 1 : circle;
//先清除其他小圆圈的current类名
//调用函数
circleChange();
})
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[circle].className = 'current';
}
var timer = this.setInterval(function () {
//手动调用点击事件
next.click();
}, 3000)
})
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
if (flag) {
flag = false;
animate(ul, -num * imgWidth, function () {
flag = true;
})
}
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (window.pageYOffset == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
// obj.style.left = window.pageYOffset + step + 'px';
window.scroll(0, window.pageYOffset + step);
}, 15);
}
<script>
window.addEventListener('load', function() {
// 1. 获取元素
var cloud = document.querySelector('.cloud');
var c_nav = document.querySelector('.c-nav');
var lis = c_nav.querySelectorAll('li');
// 2. 给所有的小li绑定事件
// 这个current 做为筋斗云的起始位置
var current = 0;
for (var i = 0; i < lis.length; i++) {
// (1) 鼠标经过把当前小li 的位置做为目标值
lis[i].addEventListener('mouseenter', function() {
animate(cloud, this.offsetLeft);
});
// (2) 鼠标离开就回到起始的位置
lis[i].addEventListener('mouseleave', function() {
animate(cloud, current);
});
// (3) 当我们鼠标点击,就把当前位置做为目标值
lis[i].addEventListener('click', function() {
current = this.offsetLeft;
});
}
})
</script>
| 触屏touch事件 | 说明 |
|---|---|
| touchstart | 手指触摸到一个DOM元素时触发 |
| touchmove | 手指再一个DOM元素滑动时触发 |
| touchend | 手指从一个DOM元素上移开时触发 |
<body>
<div></div>
<script>
// 1. 获取元素
// 2. 手指触摸DOM元素事件
var div = document.querySelector('div');
div.addEventListener('touchstart', function() {
console.log('我摸了你');
});
// 3. 手指在DOM元素身上移动事件
div.addEventListener('touchmove', function() {
console.log('我继续摸');
});
// 4. 手指离开DOM元素事件
div.addEventListener('touchend', function() {
console.log('轻轻的我走了');
});
</script>
</body>
<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>
classList属性是HTML5新增的一个属性,返回元素类名。但是ie10以上版本才支持。
<body>
<div class="one two"></div>
<button> 开关灯</button>
<script>
// classList 返回元素的类名
var div = document.querySelector('div');
// console.log(div.classList[1]);
// 1. 添加类名 是在后面追加类名不会覆盖以前的类名 注意前面不需要加.
div.classList.add('three');
// 2. 删除类名
div.classList.remove('one');
// 3. 切换类
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
document.body.classList.toggle('bg');
})
</script>
</body>
轮播图功能基本和PC端一致
window.addEventListener('load', function() {
// alert(1);
// 1. 获取元素
var focus = document.querySelector('.focus');
var ul = focus.children[0];
// 获得focus 的宽度
var w = focus.offsetWidth;
var ol = focus.children[1];
// 2. 利用定时器自动轮播图图片
var index = 0;
var timer = setInterval(function() {
index++;
var translatex = -index * w;
ul.style.transition = 'all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}, 2000);
// 等着我们过渡完成之后,再去判断 监听过渡完成的事件 transitionend
ul.addEventListener('transitionend', function() {
// 无缝滚动
if (index >= 3) {
index = 0;
// console.log(index);
// 去掉过渡效果 这样让我们的ul 快速的跳到目标位置
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里面li带有current类名的选出来去掉类名 remove
ol.querySelector('.current').classList.remove('current');
// 让当前索引号 的小li 加上 current add
ol.children[index].classList.add('current');
});
// 4. 手指滑动轮播图
// 触摸元素 touchstart: 获取手指初始坐标
var startX = 0;
var moveX = 0; // 后面我们会使用这个移动距离所以要定义一个全局变量
var flag = false;
ul.addEventListener('touchstart', function(e) {
startX = e.targetTouches[0].pageX;
// 手指触摸的时候就停止定时器
clearInterval(timer);
});
// 移动手指 touchmove: 计算手指的滑动距离, 并且移动盒子
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; // 如果用户手指移动过我们再去判断否则不做判断效果
e.preventDefault(); // 阻止滚动屏幕的行为
});
// 手指离开 根据移动距离去判断是回弹还是播放上一张下一张
ul.addEventListener('touchend', function(e) {
if (flag) {
// (1) 如果移动距离大于50像素我们就播放上一张或者下一张
if (Math.abs(moveX) > 50) {
// 如果是右滑就是 播放上一张 moveX 是正值
if (moveX > 0) {
index--;
} else {
// 如果是左滑就是 播放下一张 moveX 是负值
index++;
}
var translatex = -index * w;
ul.style.transition = 'all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
} else {
// (2) 如果移动距离小于50像素我们就回弹
var translatex = -index * w;
ul.style.transition = 'all .1s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}
}
// 手指离开的时候就重新开启定时器
clearInterval(timer);
timer = setInterval(function() {
index++;
var translatex = -index * w;
ul.style.transition = 'all .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);
})
})
移动端click事件会有300ms的延迟,原因是移动端屏幕双击会缩放(double tap to zoom)页面。
解决方案:
<meta name="viewport" content="user-sclable=no">
//封装top解决 click300ms 延时
function tap(obj, callback) {
var isMove = false;
var starTime = 0;//记录触摸时的时间变量
obj.addEventListener('touchstart', function (e) {
starTime = Date.now();//记录触摸时间
});
obj.addEventListener('touchmove', function (e) {
isMove = true;//看看是否有滑动,有滑动拖拽,不算点击
});
obj.addEventListener('touchend', function (e) {
if (!isMove && (Date.now() - starTime) < 150) {//如果手指触摸和离开时间小于150ms算点击
callback && callback();//执行回调函数
}
isMove = false;//取反 重置
starTime = 0;
});
}
tap(div, function () {
//执行代码
});
H5提供了video标签,但是浏览器支持情况不同。
不同的视频格式文件,我们可以通过sourse解决
但是外观,样式,暂停,播放只能自己解决。
这时,我们可以使用插件来制作。
随着互联网的快速发展,基于网页的应用越来越普遍,同时越来越复杂,为了满足各种各样的需求,会经常性的存储大量数据,HTML规范提出了相关解决方案。
数据存储在用户浏览器生命周期为关闭浏览器窗口(数据在何时存在)键值对的形式存储使用 <script>
sessionStorage.setItem(key, value)
</script>
<script>
sessionStorage.getItem(key)
</script>
<script>
sessionStorage.removeItem(key)
</script>
<script>
sessionStorage.clear()
</script>
生命周期永久生效,除非手动删除,否则关闭页面也会存在。 <script>
localStorage.setItem(key, value)
</script>
<script>
localStorage.getItem(key)
</script>
<script>
localStorage.removeItem(key)
</script>
<script>
localStorage.clear()
</script>
总结:两者方法极其相似,找一个纪就可以
轻量级数据的转换
对象转字符串
//存储字符串:对象-》字符串 JSON.stringfy()
console.log(obj);
console.log(JSON.stringify(obj));
localStorage.obj = JSON.stringify(obj);
字符串转对象
//字符串转换成对象后,再输出
console.log(JSON.parse(localStorage.obj));
传址拷贝,直接拷贝对象的内存地址,修改拷贝的数据,原始数据也会改变。
新开辟一块内存,将对象中的所有属性全部复制,原地址中对象改变了,深拷贝出来的对象也不变。
两种方式function dedCopy(o) {
if (Array.isArray(o)) {
var result = [];
} else if (typeof o == 'object') {
var result = {};
} else {
var result = o;
}
for (var i in o) {
if (typeof o[i] == 'object') {
result[i] = dedCopy(o[i])
} else {
result[i] = o[i]
}
}
return result;
}
ES6文档2
ES6有了块级作用域的概念
{} , var 不识别块级作用域, let ,const 识别块级作用域。
let [a, b, c] = [1, 4, 5]
console.log(`${a},${b},${c}`);
1,4,5
变量必须与属性名相同才能赋值,解构失败为undefined
函数可以给形参
添加默认值
function fn(s, y = 1) {
console.log(y);
}
fn()
var fu = function () {
console.log(111);
}
fu()
var fn = () => {
return console.log(2);
}
var sum = (sum1, sum2) => sum1 + sum2
var sum = (num1, num2) => {
var sum = num1 + num2
return sum
}
即library,是一个封装好的特定的集合(方法和函数),从封装一大堆函数的角度理解库,就是在这个库中,封装了很多预先定义好的函数在里面,比如动画 animate,hide,show,比如获取元素等。
简单理解:就是一个JS文件,里面对我们原生的js代码进行了封装,存放到里面。这样我们可以快速高效的使用这些封装好的功能了。
比如jQuery,就是为了快速方便的操作DMO,里面基本是函数和方法
这些库都是对原生javaScript的封装,内容都是用javaScript实现的,我们主要学习的是jQuery.
jQuery是一个快速,简洁的JavaScript库,其设计宗旨就是"write Less ,Do More",即编写更少的代码,做更多的事情。
j就是JavaScript; Query查询:意思就是查询js,把js中的DOM操作做了封装,我们可以快速的查询使用里面的功能。
jQuery封装了JavaScript常见的功能和代码,优化了DOM操作,事件处理,动画设计和Ajax交互
学习JQuery的本质:就是学习调用这些函数(方法)。
$(function () {
...//此处填写页面DOM加载完成的入口
});
$(document).ready(function () {
...//此处是页面DOM加载完成的入口
});
<script>
$(document).ready(function () {
$('div').hide();
})
$(function () {
$('div').hide;
})
</script>
加载完毕后才执行内部代码。 $别称,在代码中可以使用jQuery代替
,
但
一
般
为
了
方
便
,
通
常
都
直
接
使
用
,但一般为了方便,通常都直接使用
,但一般为了方便,通常都直接使用.$ 是jQuery的顶级对象,相当于原生javascript中的window,把元素利用$包装成jQuery对象,就可以调用jQuery的方法。原生JS获取来的对象就是DOM对象伪数组形式存储) <script>
//1. DOM对象:用原生的js获取过来的对象就是DOM对象
var myDiv = document.querySelector('div');
var mySpan = document.querySelector('span');
console.log(myDiv);
//2. JQuery对象:用jquery方式获取过来的对象是jQuery对象。本质:通过$ 把DOM元素进行了包装
$('div');//JQuery对象
console.dir($('div'))
$('span')
//3. jQuery对象只能用jQuery方法,DOM对象则使用原生的JavaScript属性和方法
myDiv.style.display = 'none';
// $('span').style.display = 'none'; 这个$('span')是一个jQuery对象,不能使用原生的js的属性和方法。
</script>
jQuery对象只能用jQuery方法,DOM对象则使用原生的JavaScript属性和方法
因为原生的js比jQuery更大,原生的一些属性和方法jQuery没有给我们封装,要想使用这些属性和方法必须要把jQuery对象转换为DOM对象才可以使用。
$('video')
var myvideo = document.querySelector('video');
$(myvideo)
$('video')[0].play()
$('video').get(0).play()
注意:因为jQuery对象是伪数组,所以要用索引号。
$(‘div’)[index]
$(‘div’.get(index))
index是索引号
原生JS获取元素方法很多,很杂,而且兼容性情况不一致,因此jQuery给我们做了封装,使得获取元素统一标准。
$(“选择器”) //里面选择器直接写css选择器就可以,但是要加引号zz
| 名称 | 用法 | 描述 |
|---|---|---|
| ID选择器 | $(”#id“) | 获取指定ID元素 |
| 全选择器 | $(” * “) | 匹配所有元素 |
| 类选择器 | $(”.class“) | 获取同一类class元素 |
| 标签选择器 | $(”div“) | 获取同一类标签的所有元素 |
| 并集选择器 | $(”div,p,li“) | 获取多个元素 |
| 交集选择器 | $(”li.current“) | 交集元素 |
| 名称 | 用法 | 描述 |
|---|---|---|
| 子代选择器 | $(”ul>li“) | 使用> 号,获取亲儿子层级的元素;注意,并不会获取孙子层级的元素 |
| 后代选择器 | $(”ul li“) | 使用空格,代表后代选择器,获取ul下的所有li元素,包括孙子 |
$('div').css('color(属性)', 'pink(值)')
遍历内部DOM元素(伪数组形式存储)的过程就叫隐式迭代。
简单理解:给匹配到的所有元素循环进行遍历,执行相应的方法,而不用我们再进行循环,简化我们的操作,方便我们调用。
| 语法 | 用法 | 描述 |
|---|---|---|
| :first | $(”li:first“) | 获取第一个li |
| :last | $(”li:last“) | 获取最后一个li |
| :eq(index) | $(”li:eq(2“) | 获取到的li元素中,选择索引号为2的元素,索引号从0开始 |
| :odd | $(”li:odd“) | 获取到的li元素中,选择索引号为奇数的元素 |
| :even | $(”li:even“) | 获取到的li元素中,选择索引号为偶数的元素 |
| 语法 | 用法 | 描述 |
|---|---|---|
parent() | $(”li“).parent(); | 查找父级 |
children(selector) | $(”ul“).chilren(“li”) | 相当于$(“ul>li”),最近一级(亲儿子) |
find(selector) | $(”ul“).find(“li”) | 相当于$(“ul li”),后代选择器 |
siblings(selector) | $(”.first“).siblings(“li”) | 查找兄弟节点,不包括本身 |
| nextAll[expr] | $(”.first“).nextAll() | 查找当前元素之后的所有同辈元素 |
| prevtAll[expr] | $(”.last“).prevAll() | 查找当前元素之前的所有同辈元素 |
| hasClass(class) | $(”div“).hasClass(“protected”) | 检查当前的元素是否含有某个特定的类,如果有,则返回true |
eq(index) | $(”li“).eq(2) | 相当于$(“li:eq(2)”).index从0开始 |
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
font-size: 14px;
}
.nav {
margin: 100px;
}
.nav>li {
position: relative;
float: left;
width: 80px;
height: 41px;
text-align: center;
}
.nav li a {
display: block;
width: 100%;
height: 100%;
line-height: 41px;
color: #333;
}
.nav>li>a:hover {
background-color: #eee;
}
.nav ul {
display: none;
position: absolute;
top: 41px;
left: 0;
width: 100%;
border-left: 1px solid #FECC5B;
border-right: 1px solid #FECC5B;
}
.nav ul li {
border-bottom: 1px solid #FECC5B;
}
.nav ul li a:hover {
background-color: #FFF5DA;
}
</style>
<script src="jquery.min.js"></script>
</head>
<body>
<ul class="nav">
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
</ul>
<script>
$(function() {
// 鼠标经过
$(".nav>li").mouseover(function() {
// $(this) jQuery 当前元素 this不要加引号
// show() 显示元素 hide() 隐藏元素
$(this).children("ul").show();
});
// 鼠标离开
$(".nav>li").mouseout(function() {
$(this).children("ul").hide();
})
})
</script>
</body>
想要多选一的效果,排他思想;当前元素设置样式,其余的兄弟元素清除样式。
<button>快速</button>
<button>快速</button>
<button>快速</button>
<button>快速</button>
<button>快速</button>
<button>快速</button>
<button>快速</button>
$(function () {
// 1. 隐式迭代 给所有的按钮都绑定了点击事件
$("button").click(function () {
// 2. 当前的元素变化背景颜色
$(this).css("background", "pink");
// 3. 其余的兄弟去掉背景颜色 隐式迭代
$(this).siblings("button").css("background", "");
});
})
核心原理:鼠标经过左侧小盒子某个li,就让内容区盒子相对应的图片显示,其余图片隐藏。
$(this)..index() $(function () {
$("#left li").mouseover(function () {
//li背景颜色的排他思想
$(this).css("background", "pink");
$(this).siblings("li").css("background", "")
// 让其他图片隐藏
var index = $(this).index();
$("#content div").eq(index).show();
$("#content div").eq(index).siblings().hide();
})
})
链式编程是为了节约代码量,看起来更优雅。
$(this).css("color", "red").siblings().css("color", "");
jQuery可以使用css方法修改简单元素样式;也可以操作类,修改多个样式。
$(this).css('color');
$(this).css('color', "red");
冒号隔开,属性可以不用加引号。 $(this).css({
"color": "white",
"font-size": "20px"
});
<script>
$(function() {
// 1.点击上部的li,当前li 添加current类,其余兄弟移除类
$(".tab_list li").click(function() {
// 链式编程操作
$(this).addClass("current").siblings().removeClass("current");
// 2.点击的同时,得到当前li 的索引号
var index = $(this).index();
console.log(index);
// 3.让下部里面相应索引号的item显示,其余的item隐藏
$(".tab_con .item").eq(index).show().siblings().hide();
});
})
</script>
原生js中className会覆盖元素里面的类名。
jQuery里面类操作对象会指定元素进行操作,不影响原先的类名。
<body>
<div class="one two"></div>
<script>
// var one = document.querySelector(".one");
// one.className = "two";
// $(".one").addClass("two"); 这个addClass相当于追加类名 不影响以前的类名
$(".one").removeClass("two");
</script>
</body>
jQuery给我们封装了很多动画效果,最为常见的如下:
| 作用 | 相关函数 |
|---|---|
| 显示隐藏 | show();hide();toggle() |
| 滑动 | slideDown();slideUp();slideToggle() |
| 淡入淡出 | fadeln();fadeOut();fadeToggle();fadeTo() |
| 自定义动画 | animate() |
show([speed,[easing],[fn]])
| 函数名 | 作用 |
|---|---|
| 显示 | show() |
| 隐藏 | hide() |
| 切换(点击一下显示,点击一下隐藏) | toggle() |
<body>
<button>显示</button>
<button>隐藏</button>
<button>切换</button>
<div></div>
<script>
$(function() {
$("button").eq(0).click(function() {
$("div").show(1000, function() {
alert(1);
});
})
$("button").eq(1).click(function() {
$("div").hide(1000, function() {
alert(1);
});
})
$("button").eq(2).click(function() {
$("div").toggle(1000);
})
});
</script>
</body>
一般情况下,我们都不加参数直接显示隐藏就可以了,切换样式太丑了
| 函数名 | 作用 |
|---|---|
| 下拉滑动 | slideDown() |
| 上拉滑动 | slideUp() |
| 切换滑动 | slideToggle() |
<body>
<button>下拉滑动</button>
<button>上拉滑动</button>
<button>切换滑动</button>
<div></div>
<script>
$(function() {
$("button").eq(0).click(function() {
// 下滑动 slideDown()
$("div").slideDown();
})
$("button").eq(1).click(function() {
// 上滑动 slideUp()
$("div").slideUp(500);
})
$("button").eq(2).click(function() {
// 滑动切换 slideToggle()
$("div").slideToggle(500);
});
});
</script>
</body>
hover([over,]out)
<script>
$(function() {
// 鼠标经过
// $(".nav>li").mouseover(function() {
// // $(this) jQuery 当前元素 this不要加引号
// // show() 显示元素 hide() 隐藏元素
// $(this).children("ul").slideDown(200);
// });
// // 鼠标离开
// $(".nav>li").mouseout(function() {
// $(this).children("ul").slideUp(200);
// });
// 1. 事件切换 hover 就是鼠标经过和离开的复合写法
// $(".nav>li").hover(function() {
// $(this).children("ul").slideDown(200);
// }, function() {
// $(this).children("ul").slideUp(200);
// });
// 2. 事件切换 hover 如果只写一个函数,那么鼠标经过和鼠标离开都会触发这个函数
$(".nav>li").hover(function() {
$(this).children("ul").slideToggle();
});
})
</script>
事件切换 hover 如果只写一个函数,那么鼠标经过和鼠标离开都会触发这个函数。
stop()
stop()方法用于停止动画或效果。
注意:stop()写到动画或者效果的前面,相当于停止结束上一次的动画。
<script>
$(function() {
// 鼠标经过
// $(".nav>li").mouseover(function() {
// // $(this) jQuery 当前元素 this不要加引号
// // show() 显示元素 hide() 隐藏元素
// $(this).children("ul").slideDown(200);
// });
// // 鼠标离开
// $(".nav>li").mouseout(function() {
// $(this).children("ul").slideUp(200);
// });
// 1. 事件切换 hover 就是鼠标经过和离开的复合写法
// $(".nav>li").hover(function() {
// $(this).children("ul").slideDown(200);
// }, function() {
// $(this).children("ul").slideUp(200);
// });
// 2. 事件切换 hover 如果只写一个函数,那么鼠标经过和鼠标离开都会触发这个函数
$(".nav>li").hover(function() {
// stop 方法必须写到动画的前面
$(this).children("ul").stop().slideToggle();
});
})
</script>
注意:方法必须写到动画的前面.
| 函数名 | 作用 |
|---|---|
| 淡入 | fadeIn() |
| 淡出 | fadeOut() |
| 透明度 | fadeTo() |
| 切换(淡入淡出相互切换)) | fadeToggle() |
fadeTo([speed,opcity,[easing],[fn]])
opacity透明度必须写,取值0~1之间. $("button").eq(3).click(function() {
// 修改透明度 fadeTo() 这个速度和透明度要必须写
$("div").fadeTo(1000, 0.5);
});
主要思想 :透明度的排他思想,使用了hover,设置了鼠标移入和鼠标移除的效果,使用stop函数,停止了动画排队.
<script>
$(function() {
//鼠标进入的时候,其他的li标签透明度:0.5
$(".wrap li").hover(function() {
$(this).siblings().stop().fadeTo(400, 0.5);
}, function() {
// 鼠标离开,其他li 透明度改为 1
$(this).siblings().stop().fadeTo(400, 1);
})
});
</script>
animate(params,[speed],[easing],[fn])
params: 想要更改的样式属性,以对象的形式传递,必须写.属性名可以不用带引号,如果是复合函数属性,则需要采取驼峰命名法borderLeft.其余参数都可以省略.所谓元素固有属性就是元素自带的属性,比如 < a > 里面的href,比如< input >里的typpe
prop('属性')
prop('属性','属性值')
//1. element.prop("属性名") 获取元素固有的属性值
console.log($("a").prop("href"));
$("a").prop("title", "我们都挺好");
$("input").change(function() {
console.log($(this).prop("checked"));
});
用户自己给元素添加的属性,我们称为自定义属性,比如给 div 添加 Index =“1”.
attr('属性') //类似原生 getAttribute()
attr('属性','属性值') //类似原生 setAttribute()
// console.log($("div").prop("index"));
// 2. 元素的自定义属性 我们通过 attr()
console.log($("div").attr("index"));
$("div").attr("index", 4);
console.log($("div").attr("data-index"));
// 3. 数据缓存 data() 这个里面的数据是存放在元素的内存里面
data() 方法可以在指定的元素上获取元素,并不会修改DOM元素结构。一旦页面刷新,之前存放的元素就将被移除。
把元素当作变量来看,把数据存放到内存里。
data("name","value") //向被选元素附加数据
date("name") //向被选元素获取数据。
同时还可以读取html5自定义属性data-index ,得到的是数字型。
// 3. 数据缓存 data() 这个里面的数据是存放在元素的内存里面
$("span").data("uname", "andy");
console.log($("span").data("uname"));
console.log($("div").data("index"));
这个方法获取data-index h5自定义属性 第一个 不用写data- 而且返回的是数字型
主要是遍历,创建,添加,删除元素操作。
jQuery隐式迭代是对同一类元素做了同样的操作。如果想要给同一个元素做不同的操作,就需要用到遍历。
$("div").each(function (index, domEle) { xxx; })
each()方法遍历匹配每一个元素。主要用DOM处理,each每一个
里面的回调函数有两个参数:index是每个元素的索引号,demEle是每个元素的DOM元素对象,不是jQuery对象。
$each(object,function(index,element){ xxx;})
$.each()方法可以用于遍历任意对象,主要用于数据处理,比如数组,对象
里面的函数有两个参数:index是每个元素的索引号,element遍历内容
$.each({
name: "andy",
age: 18
}, function (i, ele) {
console.log(i); // 输出的是 name age 属性名
console.log(ele); // 输出的是 andy 18 属性值
})
// $("div").each(function (index, domEle) { xxx; })
})
语法:
$("<li></li>")
动态创建li标签
element.append("内容")
$("ul").append(li)
$("ul").prepend(li)
element.append(“内容”) 把内容放到匹配元素的最后面,类似原生的appendChild。
element.prepend(“内容”) 把内容放到匹配元素的最前面,类似原生的insertBefore
var div = $("<div>我是真的</div>")
element.after("内容") //放到目标元素后面
element.before("内容") //放到目标元素前面
$(".test").after(div)
$(".test").before(div)
内部添加元素后,生成之后,它们是父子关系
外部添加元素后,生成之后,它们是兄弟关系
element.remove()
删除匹配的元素(本身)
element.empty()
删除匹配的元素集合中的所有子节点(本身不会被删除)
element.html("")
清空匹配的元素内容
// 6. 删除商品模块
// (1) 商品后面的删除按钮
$(".p-action a").click(function() {
// 删除的是当前的商品
$(this).parents(".cart-item").remove();
getSum();
});
// (2) 删除选中的商品
$(".remove-batch").click(function() {
// 删除的是小的复选框选中的商品
$(".j-checkbox:checked").parents(".cart-item").remove();
getSum();
});
// (3) 清空购物车 删除全部商品
$(".clear-all").click(function() {
$(".cart-item").remove();
getSum();
})
| 语法 | 作用 |
|---|---|
| width()/height() | 取得匹配元素宽度和高度值 只算 width/height |
| innerWidth()/innerHieght() | 取得匹配元素的宽度和高度值包含 padding |
| outerWidth()/outerHeight() | 取得匹配元素宽度和高度值 包含padding,border |
| outerWidth(ture)/outerHeight(true) | 取得匹配元素宽度和高度值 包含padding,borde,margin |
以上参数为空,则是获取相应属性,返回的是数字型
如果参数为数字,则是修改相应的值
参数可以不必写单位
位置主要有三个 :offset(),position( ), scrollTop( ) / scrollLeft( )
设置或获取元素偏移
文档的偏移坐标,和父级没有关系。left,top.offset().top用于获取距离文档顶部的距离,offset().left用于获取距离文档左侧的距离。console.log($(".son").offset());
console.log($(".son").offset().top);
$(".son").offset({
top: 200,
left: 200
});
console.log($(".son").position());
这个方法只能获取不能设置偏移
$(function() {
$(document).scrollTop(100);
// 被卷去的头部 scrollTop() / 被卷去的左侧 scrollLeft()
// 页面滚动事件
var boxTop = $(".container").offset().top;
$(window).scroll(function() {
// console.log(11);
console.log($(document).scrollTop());
if ($(document).scrollTop() >= boxTop) {
$(".back").fadeIn();
} else {
$(".back").fadeOut();
}
});
// 返回顶部
$(".back").click(function() {
//没有动画效果
// $(document).scrollTop(0);
$("body, html").stop().animate({
scrollTop: 0
});
// $(document).stop().animate({
// scrollTop: 0
// }); 不能是文档而是 html和body元素做动画
})
})
带有动画的返回顶部
- 核心原理:使用animate动画返回顶部。
- animate动画函数里面有个scrollTop属性,可以设置位置。
- 但是是
元素做动画,因此$(“body,htmt”).animate({scrollTop:0}),不能是文档,而是html和body做动画。
语法:
element.事件(funcation(){})
$("div").click(funcation(){ 事件处理程序 })
$("div").click(function () {
$(this).css("background", "purple");
});
其他事件和原生基本一致。
比如 mouseover, mouseout,blur, focus,change,keydown,keyup,resize,scroll等
on() 方法在匹配元素上绑定一个或多个事件的事件处理函数
语法:
element.on(events,[selector],fn)
$("div").on({
mouseenter: function() {
$(this).css("background", "skyblue");
},
click: function() {
$(this).css("background", "purple");
},
mouseleave: function() {
$(this).css("background", "blue");
}
});
on( )方法优势1:
可以绑定多个事件,多个处理事件处理函数
on( )方法优势2:
可以事件委派操作。事件委派的定义就是,把原来加给子元素身上的事件绑定在父元素身上,就是把事件委派给父元素。
在此之前有bind(),live() delegate()等方法来处理事件绑定或者事件的委派,最新版本请用on替代它们。
on( )方法优势3:
动态创建的元素,click()没有办法绑定事件,on() 可以动态生成的元素绑定事件。
off( )方法可以移除通过on( )方法添加的事件处理程序。
$("div").off(); // 这个是解除了div身上的所有事件
$("div").off("click"); // 这个是解除了div身上的点击事件
$("div").off("click","li"); //解除事件委派
如果有的事件只想触发一次,可以使用one()来绑定事件。
// 2. one() 但是它只能触发事件一次
$("p").one("click", function() {
alert(11);
})
有些事件希望自动触发,比如轮播图自动播放功能和右键点击右侧按钮一致,可以利用定时器触发右侧按钮点击事件,不必鼠标点击触发。
element.click()
element.trigger("type")
element.triggerHandler(type)
$("div").triggerHandler("click");
$("input").on("focus", function() {
$(this).val("你好吗");
});
事件被触发,就会有事件对象的产生
element.on(events,[selector],funcation(event){})
阻止默认行为: event.privientDefault() 或者 return false
阻止冒泡: event.stopPropagation( )
如果想要把某个对象拷贝(合并)给另外一个对象使用,此时可以使用$.extend()方法
$.extend([deep] , target,objectl,[objectN])
$.extend(target, obj);
var targetObj = {};
var obj = {
id: 1,
name: "andy"
};
$.extend(targetObj, obj);
var targetObj = {
id: 0
};
var obj = {
id: 1,
name: "andy"
};
// $.extend(target, obj);
$.extend(targetObj, obj);
console.log(targetObj); // 会覆盖targetObj 里面原来的数据
浅拷贝是把被拷贝对象
复杂数据类型中的地址拷贝给对象,修改目标对象会影响被拷贝的对象
因为拷贝后指向的是地址,所以目标拷贝对象修改后,拷贝对象也会改变。
$.extend(true, targetObj, obj);
深拷贝把里面的
数据完全复制一份给目标对象 如果里面有不冲突的属性,会合并到一起
jquery使用 作 为 标 识 符 , 随 着 J Q u e r y 的 流 行 , 其 他 的 J s 库 也 会 用 这 作为标识符,随着JQuery的流行,其他的Js库也会用这 作为标识符,随着JQuery的流行,其他的Js库也会用这作为标识符,这样一起使用就会说引起冲突。
需要一个解决方案,让jQuery和其他的js库不存在冲突,可以同时存在,这叫多库共存。
$符号改为jQuery。比如jQuery(“div”) <script>
$(function() {
function $(ele) {
return document.querySelector(ele);
}
console.log($("div"));
// 1. 如果$ 符号冲突 我们就使用 jQuery
jQuery.each();
// 2. 让jquery 释放对$ 控制权 让用自己决定
var suibian = jQuery.noConflict();
console.log(suibian("span"));
suibian.each();
})
</script>
jQuery插件功能有限,想要更加复杂的特效效果,可以借助于jQuery插件完成。
注意:这些插件是依赖于JQuery来完成时的,所以
必须先引入jQuery文件,因此也称为jQuery插件
图片懒加载:图片使用延迟加载可以高网页下载速度它也能帮助轻服务器负载
当我们页面滑动到可视区域,再显示图片。
我们使用jquery插件库 EasyLoad 。
注意,此时的js引入文件和js调用必须写道DOM元素
图片最后面。
bootstrap框架也是依赖于jQuery开发的,因此里面的js插件使用,也必须引入jQuery文件。
但是本页面的内容刷新不会丢失使用localstorage来存储数据,可以满足第4点要求。
核心思路:不管按下回车,还是点击复选框,就是把本地存储的数据加载到页面中,这样保证刷新页面不hi丢失数据。
存储数据格式: var todolist = [{ tatle:‘xxx’, done: false}]
注意点1 :本地存储localStrage里面只能存储字符串格式,因此需要把对象转换成字符串 Json.stringify(data)
注意点2:获取本地存储数据,需要把里面的字符串转换成对象格式JSON.parse()我们才可以用里面的数据
localStorage.setItem("todo", JSON.stringify(todolist))
var data = localStorage.getItem("todo")
data = JSON.parse(data)
- 切记:页面中的数据,都要从本地存储里获取,这样刷新页面就不会丢失,所以把数据保存到本地存储里面。
- 利用
事件对象.keyCode判断用户按下回车键(13)- 声明一个数组,保存数组
- 先要读取本地存储里面的数据(声明函数 getData()) ,反到这个数组里面。
- 之后把最新的表单获取过来,追加到数组里面。
- 最后把数组存储给本地存储(声明函数 saveDate( ))

阮一峰ES6入门
ECMAScript6 ↩︎