2021-10-15 - js

JavaScript

介绍

概念

js: 是基于对象和事件驱动的解释性的脚本语言;

特点

\1. 基于对象: 一切皆对象, js可以使用自己创建的对象

\2. 事件驱动: 都是由事件来进行响应的

\3. 解释性: 相对于编译性来说, 浏览器可以直接识别js,并且去执行

\4. 跨平台性: 只要浏览器支持js 那么js就可以运行 与操作系统与环境无关

\5. 相对安全性: 有同源策略限制

组成部分

ECMAScript:语法标准

DOM: Document Object Model 文档对象模型

BOM: Browser Object Model 浏览器对象模型

与ECMAScript的关系?

js是ECMAScript的表现;

ECMAScript是js的语法标准;

引入

行内

行内: 事件 不推荐使用

缺点: 1. 没有实现三分离

\2. 不利于封装复用

\3. 局限性

<div οnclick="alert('Hello World')"></div>

内嵌

行内: 事件 不推荐使用

缺点: 1. 没有实现三分离

\2. 不利于封装复用

\3. 局限性

从上到下依次执行每一个script

<script>
    // 代码块
    alert('这是额外的弹出');
</script>

外链

外链式: script双标签 工作 推荐使用

script可以放在页面的任何位置 推荐放在body的结束标签之前

注意: 外链的script标签 不允许写内嵌代码

<script src="03.js">
    alert('这是外部2');
</script>
​
再写一个script放内嵌代码
<script>
    alert('这是外部3');
</script>

注意: js文件:

\1. 后缀.js

\2. 不用写script

注释

// 注释后的代码在文件中看到 没有任何作用
// 注释单行 ctrl + /
/* 
    块注释 ctrl + shift + /
    vscode--首选项---键盘快捷方式--搜索: comment ---修改块注释
​
​
    js: 不能出现 -
        必须使用英文符号
        每行代码结束必须加;
*/ 

调试

alert: 弹出框 警告框

alert('内容');

一次只能弹出一个 阻断页面

// alert('123');

prompt('提示内容', '默认值'); 对话框

有返回值, 可以接收

取消: null

确定: 输入框的内容

alert(prompt('请输入数字', '12'));

document.write('', '', '')

document.write(...data);

输出到页面, 不会覆盖自身输出的内容

可以识别标签

写在页面加载完成之后的时候 会覆盖页面的内容

document.write('12345');
document.write('<b>这是b标签</b>');

输出在控制台:

console.log(...data);

右键检查/f12---> Console --> 查看

快捷简写: log

console.log('1', '2', '3', 'adesdf');
console.log('123');

断点调试

断点: 阻断代码从头到尾执行 手动控制

\1. f12打开控制台-->Source

\2. 打开要调试的文件

\3. 设置断点: 点击对应的行数 切换到要调试的小的部分

\4. 刷新页面

\5. 具体查看

变量

概念

变量: 用来存储数据的容器

在内存中存储数据的名称

声明变量: var 变量名;

命名规范:

\1. 变量名由字母、数字、_、$组成, 其中数字不能开头

\2. 不能使用关键字和保留词 var let import const for break top(额外注意)

\3. 不能重复 如果重复后面的就会覆盖前面的

\4. 具有语义化 user password

\5. 使用驼峰命名法 多个小单词组成 从第二个之后的单词的首字母大写 userName familyName idCard userPassword

声明变量:

  1. 先声明 后赋值

    var user;
    user = '迪丽热巴'; // 将等号右边的赋值给等号左边
    console.log(user);
  2. 声明的同时并赋值 var 变量名 = 值;

    var pass = 123456;
    console.log(pass);
  3. 先多个声明 再赋值

    // var 变量名1 , 变量名2 , .... , 变量名n;

    // 变量名1 = 值1;

    var a1, a2, a3;
    a1 = 10;
    a2 = 20;
    a3 = 30;
    console.log(a1, a2, a3);
  4. 连等声明

    // var 变量名1 = 变量名2 = 值;

    var b1 = b2 = 500;
    console.log(b1, b2); // 500 500
  5. 错误提示:

    var _a = 10;
    var $ = 30;
    console.log(_a, $);
    
    // var一个变量名为var的变量
    // var var = 'a';  报错

特殊声明

  1. 只声明 不赋值 得到就是undefined

    // 1. 只声明 不赋值  得到就是undefined
    var a;
    console.log(a); // undefined
  2. 不声明 直接赋值

    // 2. 不声明 直接赋值
    // 不推荐大家使用 不能区分全局和局部变量  不能垃圾回收
    b = 30;
    console.log(b);
  3. 不声明 不赋值 直接使用

    // 3. 不声明 不赋值 直接使用
    // 报错
    console.log(c);
    //  c is not defined: c没有被定义

数据类型

为什么要分类

\1. 不同数据类型 在内存中所占的存储空间大小不同 存储的位置不同

\2. 不同数据类型 业务是不同的 数字进行计算 布尔值判断

分类

数据类型分类: 五大基础数据类型 一大复杂数据类型

基础: number string boolean null undefined

复杂: object(object array function)

验证:

typeof 数据

typeof(数据)

var a = 10;
typeof a; // 没有输出的
console.log(typeof a); // number
console.log(typeof(a)); // number

基础

number

\1. 整数 正整数 负整数 0

var a = 30;
var b = -500;
console.log(typeof b); // number

\2. 浮点数: 有一位小数点并且小数点后不为0

注意: 由于计算机存储精度问题, 不会用小数做计算

var c = 10.01;
console.log(c);
console.log(typeof c); // number
// js没有分数 /做除法
console.log(1/20);
console.log(1/3);

// 注意: 由于计算机存储精度问题, 不会用小数做计算
// 一定要用小数计算 可以同时扩大倍数后在计算
console.log(0.1, 0.2);
console.log(0.1 + 0.2); // 0.30000000000000004

\3. NaN: Not a Number 不是一个数字

\1. 自定义

\2. 计算错误/失败 10 - 'a'

特点:

\1. typeof以后返回number

\2. NaN与任何数值都不相等 包括自身

\3. NaN与任何其他数值计算结果都是NaN

var d = NaN;
console.log(d, typeof d); // number
console.log(10 - 'a'); // NaN

console.log(NaN == NaN); // false
console.log(NaN + 100); // NaN

\4. 进制数

4.1 八进制数: 以0为开头 并且没有超过8的数字

4.2 十六进制数: 以0x为开头 0-9a-f表示0-15 a: 10 b: 11 c: 12 d: 13 e: 14 f: 15

// 4.1 八进制数: 以0为开头 并且没有超过8的数字
var mn = 070;
// 0*8的0次 + 7*8的1次 = 56
console.log(mn);

// 4.2 十六进制数: 以0x为开头 0-9a-f表示0-15  a: 10 b: 11 c: 12 d: 13 e: 14 f: 15
var n = 0xf;
console.log(n);

\5. Infinity: 无穷大 正负 -Infinity

console.log(1/0);
console.log(-1/0);

\6. e: 10的幂

// 10000  1e4
var ab = 1e10;
console.log(ab);

string

string: 字符串 用成对的单双引号包裹的

var a = "1234a";
console.log(a);
console.log(typeof a); // string

var b = '123';
console.log(b);
console.log(typeof b); // string

''号中不允许出现换行 可以加\

var c = '赛场上我们胜了,赛场下我们同样胜了——今天中国人关注的“精彩”,远远不只是争金夺银的瞬间,“后发先至”“永不言弃”“公平竞争”“相互尊重”一样引来阵阵掌声。这是新时代的今天,投射到奥运赛场上的一种中国眼界、中国风范、中国情怀。赛道浓缩了发展史。1932年,刘长春在美国洛杉矶参加的两个项目,小组赛上均是最后一名;2021年,苏炳添在东京奥运会的百米赛道上,昂然刷新亚洲纪录。同样是奥运赛道,表述的却是从落后到腾飞的不一样的历史。';

字符串长度: 字符串.length

console.log(c.length);

获取指定下标的字符

下标: 从左往右数, 从0开始的数字

  1. 字符串.charAt(下标)

  2. 字符串[下标] ie8+

// 1. 字符串.charAt(下标)
console.log(c.charAt(51));
// 2. 字符串[下标] ie8+
console.log(c[51]);

字符串拼接

字符串需要拼接的时候 使用 + 进行连接

只要+左右有一边是字符串 就会进行字符串的拼接

步骤: 1. 删除 要替换的内容 2. 加 2个引号(与最外层引号一致的引号)2个加号(2个引号中间) 3. 拼 变量(两个+中间)

console.log('hello javascript');
var user = 'javascript';
// 字符串需要拼接的时候 使用 + 进行连接
// 只要+左右有一边是字符串 就会进行字符串的拼接
// 步骤: 1. 删除 要替换的内容  2. 加 2个引号(与最外层引号一致的引号)2个加号(2个引号中间) 3. 拼 变量(两个+中间)
console.log('hello ' + user + '');
// hello javascript, 今年 26 岁
var age = 27;
console.log('hello ' + user + ', 今年 ' + age + ' 岁');

boolean

boolean: 布尔值 只有2个值 true(真) false(假)

用于判断条件或者判断条件的结果

var a = 1;
var b = 1;
console.log(a == b); // true
console.log(typeof true); // boolean
// 了解
if(true) console.log(123);
if(false) console.log(456);

null

null: 唯一空值

来做占位 只有本身这一个值

var n = null;
console.log(n);

undefined

undefined: 值的空缺 本身该有 但是现在没有

只有本身这一个值

var m;
console.log(m); // undefined

js中规定 null和undefined相等但是不全等的

console.log(null == undefined); // true

// 数据类型不同
console.log(typeof null); // object
console.log(typeof undefined); // undefined

强制转换

为什么要强制转换

字符串加法会拼接,导致得不到正确的计算结果

所有输入框的值都是字符串

所以需要强制转换

\1. 数值: Number() parseInt parseFloat

\2. 字符: String toString

\3. 布尔: Boolean

Number

Number(数据);

不会改变原数据 返回转换以后的数据

只能转 纯数字字符串、空字符串、空格字符串、布尔值、null, 其他转换结果为NaN

var a = Number('123');
console.log(a, typeof a);
console.log(Number('')); // 0
console.log(Number('    ')); // 0
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
console.log(Number('12px'));// NaN
console.log(Number('px'));// NaN

parseInt

parseInt(数据, [进制]);

[进制]: 可写可不写 默认是十进制

转换规则: 从左往右依次转换每一个字符, 遇到不能转换的,结束转换, 如果第一个字符就转换失败 返回NaN

返回结果是整数

console.log(parseInt('80'));
console.log(parseInt('80px')); // 80
console.log(parseInt('80.25px')); // 80
console.log(parseInt('a80.25px')); // NaN

// 八进制数: 070 --> 转换到10 --> 56
console.log(parseInt('070')); // 70
console.log(parseInt('070', 8)); // 56  edge-->仿真--->ie8

parseFloat

parseFloat(数据);

转换规则: 从左往右依次转换每一个字符, 遇到不能转换的,结束转换, 如果第一个字符就转换失败 返回NaN

返回结果是整数、浮点数

console.log(parseFloat('80.25px')); // 80.25

String

\1. String(数据) 可以转换一切数据

\2. 数据.toString([进制]);

进制只对数值类型起作用

/* 
    1. String(数据) 可以转换一切数据 
*/
console.log(String(123));
console.log(String(true));
console.log(String(false));
console.log(String(null));
console.log(String(undefined));

/* 
    2. 数据.toString([进制]);
    进制只对数值类型起作用
*/
var a = 56;
console.log(a.toString(8)); // 将a转换成8进制的数字的字符串
console.log(a.toString()); // 默认10进制

console.log(true.toString());
console.log(false.toString());

//  Cannot read property 'toString' of null  不能在null上读取到属性toString
// js中的 . 相当于语文的 白勺 的
// console.log(null.toString());
// console.log(undefined.toString());

区别:

String: 强制转换 可以转换一切数据 不能被改变

toSting: 属于对象的一个方法 可以被改变 不能转换null和undefined

Boolean

Boolean(数据);

区分js中的数据的真假:

真: 除了假的都是真的

假: false 0 NaN 空字符 null undefined

console.log(false);
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean('')); // false
console.log(Boolean('   ')); // true
console.log(Boolean(null));
console.log(Boolean(undefined));
console.log(Boolean(-1)); // true

隐式转换

  1. isNaN

    isNaN: 判断一个数据 是不是 不是 一个数字

    如果数据是真正的数字 返回 false

    如果数据不是真正的数字 返回 true

    隐式调用 Number(), Number能转化成功的数据, isNaN返回false, 如果转换失败, isNaN返回true

    *
        console.log(isNaN( '123' )); // false
    *console.log(isNaN( '123a' )); // true
    console.log(isNaN( 'abc' )); // true
    console.log(isNaN( true )); // Number(true)---1---false
    console.log(isNaN( 'true' )); // Number('true') -- NaN true
    console.log(isNaN( String(null) ) ); // 'null' Number('null') true
  2. toFixed

    toFixed: 将数值转换成字符串 保留指定位数的小数 2位以上

    数值.toFixed(数字);

    返回字符串

    var num = 100.00;
    console.log(num);
    console.log(num.toFixed(2));
    console.log(typeof num.toFixed(2)); // string
    
    var a = 0.1;
    var b = 0.2;
    var c = a + b;
    console.log(c.toFixed(2));

    运算符

分类和概念

运算符: 将两个操作数联系起来的符号, 程序执行的符号

例如: + = - / *

表达式: 由2个以上的操作数和运算符组合起来的式子就叫做表达式

例如: var a = 10; c = 10 + 20;

运算符: 算术 赋值 比较 三目 逻辑

表达式: 由运算符来决定的

算术表达式 赋值 比较 三目 逻辑

算术运算符

算术: + - * / %(取余) ++ --

console.log(10 + 20);
var a = 'a的数据类型是:' + typeof 20;

console.log(20 - 10);
console.log(20 * 10);
console.log(20 / 10); // 2

console.log(20 % 10); // 0
console.log(20 % 3); // 2

++: 自加 在自身基础上加1, 可以数据的前面也可以写在数据的后面

var b = 10;
b++;
++b;

var c = 10;
c++;
console.log(c); // 11

var d = 10;
++d;
console.log(d); // 11

当++和其他代码放在一起的时候, ++在前, 先自加,在执行其他代码, 如果++在后,先执行其他代码,再自加

var e = 10;
console.log(++e); // ++e; log(e); 11
console.log(e); // 11

var f = 10;
console.log(f++); // log(f);--10 f++;
console.log(f); // 11

--: 自减 在自身基础上-1, 可以写在数据的前面也可以写在数据的后面

当--和其他代码放在一起的时候, --在前, 先自减,在执行其他代码, 如果--在后,先执行其他代码,再自减

var m = 10;
console.log(m--); // 10
console.log(m); // 9

var n = 10;
console.log(--n); // 9
console.log(n); // 9

隐式转换

  1. 数值之间正常计算

  2. 有字符串的+, 会变成字符串的拼接

  3. 除了字符串的+以外的所有运算,都会尽可能的使用Number()转成number后进行计算

  4. 如果遇到复杂数据类型,调用自身的toString方法转成字符串后再参考上述规则;

console.log(10 / 20); // 0.5
console.log(10 * 100); // 1000


console.log('a' + 10); // a10
console.log('a' + true); // atrue
console.log('a' + null); // anull
console.log('a' + undefined); // aundefined

console.log('a' - 10); // NaN - 10  NaN
console.log(true - 1); // 1 - 1  0
console.log(null + 10); // 0 + 10 10
console.log(10 / false);  // 10 / 0 Infinity

赋值运算符

赋值运算符: = += -= *= /= %=

=: 将右边的数值赋值给左边

10 = 20!!!! 不允许

+=: 累加

var a = 10;
a += 100; // a = a + 100;  a = 10 + 100
console.log(a); // 110

a %= 10; // a = a % 10;  a = 110 % 10; a = 0;
console.log(a);

比较运算符

比较运算符: > >= < <= ==(相等) ===(全等) !=(不等) !==(不全等)

比较运算符左右两边数据的一个大小 看这个表达式是否成立 成立返回true 否则返回false

字符串比较: 从左往右依次比较每一个字符的ASCII编码, 遇到可以比较出来大小的就会结束比较

空: 0

'0' -- 48

'9' -- 57

'A' -- 65

'Z' -- 90

'a' -- 97

'z' -- 122

console.log(1 > 2); // false 
console.log(1 < 2); // true
console.log(3 < 3); // false
console.log(3 <= 3); // true
console.log(3 >= 3); // true

console.log('2' < '10000'); // 50 < 49  false

== 与 === 区别:

== 只需要值相等

=== 值相等 并且 数据类型也要一致

console.log(1 == '1'); // true
console.log(1 === '1'); // 数据类型不同 false

console.log(1 != '1'); // false
console.log(1 !== '1'); // true  数值相等 数据类型不等

逻辑运算符

逻辑运算符: &&(与) ||(或) !(取反)

&&: 左右各自都有一个表达式, 如果两个表达式都为真(true), 整个表达式就为true, 有一个为假就是false

全真为真 一假为假

console.log(true && true); // true
console.log(false && true); // false
console.log(1 < 2 && 2 > 3); // false
console.log(true && 2 <= 3); // true
console.log(false && 2 >= 3); // false

||: 左右各自都有一个表达式, 如果两个表达式都为假(false), 整个表达式就为false, 有一个为真就是true

全假为假 一真为真

console.log(true || false); // true
console.log(true || true); // true
console.log(false || false); // false
console.log(false || true); // true
console.log(1 == '1' || 1 !== '1'); // true || true

!: 取反 返回布尔值 将true变成false 将false变成true

假: undefined null false 0 NaN 空字符串

console.log(!1); // false
console.log(!0); // true
console.log(!''); // true
console.log(!'abc'); // false

短路运算:

逻辑与短路: 当第一个表达式为false, 后面表达不在执行,如果第一个表达式为true, 后面表达式执行

在两个数之间做选择, 如果第一个为真 就执行第二个 如果第一个为假 就执行第一个

var a = true && false;
console.log(a);

var b = 1 && 0; // b = 1 && b = 0;
console.log(b); // 0

var c = 0 && 1; // 在0和1之间选1个数 如果第一个为真 就用第二个  如果第一个为假 就用第一个
console.log(c); // 0

var d = 'a' && 'b';
console.log(d); // 'b'

逻辑或短路: 当第一个表达式为false, 后面表达式继续执行,如果第一个表达式为true, 后面表达式不执行

在两个数之间做选择, 如果第一个为真 就执行第一个 如果第一个为假 就执行第二个

var m = true || false;
console.log(m); // true

var n = false || true;
console.log(n); // true

var mn = 0 || 1;
console.log(mn); // 1

var o = 'a' || '';
console.log(o); // 'a'

三目运算符

语法: 条件 ? 条件为真, 执行的代码 : 条件为假, 执行的代码;

1 > 2 ? alert('翻身农奴把歌唱') : 2 < 3 ? alert('外援赢了') : alert('2立于不败之地');

优先级

获取元素

\1. 通过id

语法: document.getElementById('id名')

document: 文档

get: 获取、得到

Element: 元素

ById: 通过Id

只能获取到一个元素, 前缀必须是document

console.log(document.getElementById('odiv')); // <div id="odiv"></div> 获取正确
console.log(document.getElementById('od')); // null 获取错误
// console.log(document.getElementbyId('od')); 
// document.getElementbyId is not a function: document.getElementbyId不是一个函数 拼写错误

\2. 通过tagName

语法: document/父元素.getElementsByTagName('标签名');

获取到的是一个集合, 前缀可以是document也可以是父元素

集合不能直接操作, 必须通过下标得到具体的元素之后才能操作

// 通过标签
console.log(document.getElementsByTagName('li')); // HTMLCollection(10) [li, li, li, li, li, li, li, li, li, li]

// 通过父元素获取标签 先获取到父元素
var odiv = document.getElementById('odiv');
// 通过父获取子
var lis = odiv.getElementsByTagName('li');
console.log(odiv);
console.log(lis); // HTMLCollection(3) [li, li, li]

// 下标: 从左往右 从0开始的数字
console.log(lis[0]);

\3. 通过className

语法: document/父元素.getElementsByClassName('类名');

获取到的是一个集合, 前缀可以是document也可以是父元素

集合不能直接操作, 必须通过下标得到具体的元素之后才能操作

只支持ie8以上

// 获取className为box的元素
var boxes = document.getElementsByClassName('box');
console.log(boxes);
console.log(boxes[0]);
console.log(boxes[2]);

鼠标事件

事件三部曲

\1. 获取元素

\2. 加事件 鼠标操作谁就给谁加事件

元素.事件 = function(){}

\3. 写 写具体的代码操作

所有点击之后发生的事情 都写在function后面的{}里

// 描述: 点击div  弹出1
// 1. 获取元素 div
var div = document.getElementsByTagName('div')[0];
console.log(div); // 每次获取元素 必须输出看调试 确定元素是否正确得到

// 2. 加事件
// onclick: 单击事件
div.onclick = function () {
  // 3. 写具体的代码操作
  console.log('单击');
};

鼠标事件

onclick: 单击事件

ondblclick: 双击

onmousedown: 按下

onmouseup: 抬起

onmouseover/onmouseenter 滑入

onmouseout/onmouseleave 滑出

onmousemove: 移动

oncontextmenu: 右键菜单

// onclick: 单击事件
div.onclick = function () {
    // 3. 写具体的代码操作
    console.log('单击');
};

// ondblclick: 双击
div.ondblclick = function () {
    console.log('双击');
};

// onmousedown: 按下
div.onmousedown = function () {
    console.log('按下');
};

// onmouseup: 抬起
div.onmouseup = function () {
    console.log('抬起');
};

// onmouseover/onmouseenter 滑入
div.onmouseover = function () {
    console.log('over');
};

div.onmouseenter = function () {
    console.log('enter');
};

// onmouseout/onmouseleave 滑出
div.onmouseout = function () {
    console.log('out');
};

div.onmouseleave = function () {
    console.log('leave');
};

// onmousemove: 移动
div.onmousemove = function () {
    console.log('move');
};

// oncontextmenu: 右键菜单
div.oncontextmenu = function () {
    console.log('右键');
};

over与enter的区别

over: 子元素会触发父元素的事件

enter: 子元素不会触发父元素的事件

// 1. 获取元素
var div = document.getElementsByTagName('div')[0];
console.log(div);

// 2. 添加事件
div.onmouseover = function () {
    console.log('over');
};

div.onmouseenter = function () {
    console.log('enter');
};

操作标签

操作表单标签

单标签只有表单标签有内容, 内容放在value

获取值: var 变量 = 元素.value;

// 1. 获取表单标签
var inp = document.getElementsByTagName('input')[0];
console.log(inp);

// 2. 获取值: var 变量 = 元素.value;
var txt = inp.value;
console.log(txt);

设置值: 元素.value = 值;

inp.value = '迪丽热巴';

获取下拉列表的值: select元素.value

var sel = document.getElementsByTagName('select')[0];
console.log(sel);
console.log(sel.value); // bj

设置值: 元素.value = 值;

值必须是value的内容 与value的值一模一样

sel.value = 'cs '; // 设置不上
sel.value = 'cs'; // 可以设置

操作闭合标签

操作闭合标签内容:

共同: 都是操作闭合标签 后面覆盖前面的

innerHTML: 可以识别标签

innerText: 不可以识别标签

语法:

获取内容: var 变量 = 元素.innerHTML/innerText;

设置内容: 元素.innerHTML/innerText = 值;

// 1. 获取元素
var div = document.getElementsByTagName('div')[0];
console.log(div);

// 2. 获取内容
var html = div.innerHTML;
var text = div.innerText;
console.log(html);
console.log(text);

// 3. 设置内容
// div.innerText = '<b>这是新内容</b>';
// div.innerHTML = '<b>这是新内容</b>';

// 4. 如果想要在元素内容的最后添加其他内容  不覆盖原来的内容
// 使用 原内容 + 新内容
div.innerHTML = div.innerHTML + '<b>这是新内容</b>';
// 简写
div.innerHTML += '<b>这是第二个新内容</b>';

操作属性

属性: 写在起始标签上的 除了标签名以外的都是属性

操作属性:

获取属性的值: var 变量 = 元素.属性;

设置属性的值: 元素.属性 = 值;

所有的属性都按照这种方式来进行操作, class特殊, 由于class是关键字, 不能直接使用, 使用className

// 获取title属性
var div = document.getElementsByTagName('div')[0];
console.log(div);

// 获取title的值
var t = div.title;
console.log(t);

// 设置title的值
div.title = '我是第一';


// 操作class属性
var cl = div.className;
console.log(cl);

div.className = 'abc';

操作样式

设置样式: 元素.style.属性名 = 值;

// 获取div
var div = document.getElementsByTagName('div')[0];
console.log(div);

// 改变背景色为天蓝色
div.style.background = 'skyblue';
div.style.width = '500px';
div.style.opacity = 0.5;

批量设置:

元素.style.cssText = 值;

cssText所设置的值内容格式与css一样 :;

div.style.cssText = 'width: 500px; background: skyblue; opacity: 0.5;';

\1. js中不能使用 - , 有用到连字符- 转成驼峰命名法

\2. cssText: 会覆盖原来行内的所有样式

div.style.fontSize = '50px';

流程控制语句

流程控制语句: 决定当前代码应该如何执行或者按照什么样的顺序执行

顺序语句: 代码按照从上到下的顺序依次执行

分支语句: if if-else switch

循环语句: for while do-while

分支语句

分支语句: 可以决定后续代码走哪一个代码块

if:

if(条件){

条件为真的时候 执行的代码;

}

简写:

if(条件) 条件为真的时候 执行的代码;

注意: 只能控制紧跟在条件后面的第一句代码

// 假如意外得到100 吃火锅
// var money = 100;
var money = 80;
// if(money == 100){
//     alert('吃火锅');
//     alert('五个菜');
// }

if(money == 100) alert('吃火锅'); alert('五个菜');

if-else: 用于二选一

if(条件){

条件为真执行的代码;

} else {

条件为假执行的代码;

}

if(money == 100){
    alert('吃火锅');
} else {
    alert('吃食堂');
}

多分支: if-else

多分支: 再有2种以上情况的时候 选择使用

if(条件1){

条件1为真 执行的代码

} else if(条件2){

条件2为真 执行的代码

} else if(条件3){

条件3为真 执行的代码

} else {

以上条件都不符合 执行的代码

}

var core = 88;
var core = -10;
if(core >= 90 && core <= 100){
    alert('优秀');
} else if(core >= 80 && core < 90){
    alert('良好');
} else if(core >= 70 && core < 80){
    alert('中等');
} else if(core >= 60 && core < 70){
    alert('及格');
} else {
    alert('再来一次');
}

分支语句嵌套

var core = 88;
var core = -10;
// 成绩取值 在 0--100
if (core >= 0 && core <= 100) {
    // 判断成绩
    if (core >= 90 && core <= 100) {
        alert('优秀');
    } else if (core >= 80 && core < 90) {
        alert('良好');
    } else if (core >= 70 && core < 80) {
        alert('中等');
    } else if (core >= 60 && core < 70) {
        alert('及格');
    } else {
        alert('再来一次');
    }
}

多分支: switch

switch: 适用于条件和结果比较单一的情况

switch(条件){

case 结果1:

条件符合结果1的时候执行的代码

break;

case 结果2:

条件符合结果2的时候执行的代码

break;

case 结果3:

条件符合结果3的时候执行的代码

break;

case 结果4:

条件符合结果4的时候执行的代码

break;

default:

以上结果都不符合的时候 执行的代码;

break;

}

break: 防止穿透

如果不加break, 当匹配到一个结果之后,后续的结果都不在比较,直接执行其中的所有代码

// 判断按钮 + - * /
var str = '+';
switch(str){
    case '+': console.log(10 + 20); break;
    case '-': console.log(10 - 20); break;
    case '*': console.log(10 * 20); break;
    case '/': console.log(10 / 20); break;
    default: alert('你太为难我了,换一个吧'); break;
}

循环语句

循环: 重复执行的操作

\1. 重复代码

\2. 只有数字 下标 改变

\3. 页面元素的渲染和操作

for

for(表达式一; 表达式二; 表达式三){
    循环体;
}

for(初始化变量; 循环结束条件; 变量更新){
    重复执行的代码块
}

1. 初始化变量: var 变量名 = 起始值(数字、下标);
2. 循环结束条件: 当条件为true的时候 循环可以继续执行  为false 循环结束
3. 变量更新: i++ i--

执行时机: for会在页面开始的一瞬间就执行完成
循环的执行过程, 需要使用断点调试

执行过程:
    1. 初始化变量: var i = 1;
    2. 循环条件: i <= 5
    3. 循环体: log(i);
    4. 变量更新: i++
    2342342342

循环必须有一个可用的结束条件 否则就会形成死循环
// 从1开始输出  输出1-5每一个数字
for(var i = 1; i <= 5; i++){
    console.log(i);
}

渲染页面

很多数据需要频繁更换\banner图、数据 前端不会把数据写死

使用for循环将后台返回的数据渲染到页面中

后台返回的数据的格式多为: 数组、对象

var 变量 = [数据1, 数据2, 数据3, ....];

步骤:

\1. 写一个静态页面

\2. 重复子节点注释掉

\3. 实现js渲染页面

3.1 获取父元素 ul

3.2 将每一个数据渲染到ul中

3.3 给父元素添加子节点

// 数据
var data = ['园区网络规划', 'web前端', 'python人工智能', 'Java'];
console.log(data[0]);
console.log(data[1]);
console.log(data[2]);
console.log(data[3]);
// 1. 获取父元素 ul
var ul = document.getElementsByTagName('ul')[0];
console.log(ul);
// 2. 将每一个数据渲染到ul中 
for(var i = 0; i < data.length; i++){
    console.log(data[i]); // 获取到数据中的每一个
    // 3. 给父元素添加子节点
    ul.innerHTML += '<li>' + data[i] + '</li>';
}

for异种

for: 异种结构

强调: 两个分号不能省

初始化变量;

for(;循环条件;){

循环体;

变量更新;

}

// 输出1-5
var i = 1;
for (; i <= 5;) {
    console.log(i);
    i++;
}

while

初始化变量;

while(循环条件){

循环体;

变量更新;

}

// 输出1-5
var j = 1;
while (j <= 5) {
    console.log(j, 'j');
    j++;
}

for和while的区别

for和while没有区别, 在使用时,根据场景的不同选择

明确循环次数, 用for 求1-100 给30给li加点击

没有明确循环次数, 用while 1000, 每天花当天钱数的一半 问什么时候到1元以下

do-while

初始化变量;

do{

循环体;

变量更新;

}whlie(循环条件);

// 1--5
var k = 1;
do {
    console.log(k, 'k');
    k++;
} while (k <= 5);

while和do-while的区别

whlie: 先判断后执行循环体

do-while: 先执行循环体后判断

break与continue

break: 防止穿透; 跳出循环, 结束整个循环;

continue: 跳出本轮循环, 下次循环继续;

// 酸汤水饺
// for(var i = 1; i <= 30; i++){
//     console.log('当前吃了'+ i + '个');
// }

// 吃到第五个水饺 发现了蟑螂
// for(var i = 1; i <= 30; i++){
//     if(i == 5){
//         break;
//     }
//     console.log('当前吃了'+ i + '个');
// }

// 吃到第五个水饺 饺子掉了
for(var i = 1; i <= 30; i++){
    if(i == 5){
        continue;
    }
    console.log('当前吃了'+ i + '个');
}

循环嵌套

for(外层循环初始化变量; 外层循环条件; 外层循环变量更新){

for(内层循环初始化变量; 内层循环条件; 内层循环变量更新){

循环体;

}

}

/* 
    外层循环控制行 内层循环控制列
    *               i = 1  j = 1
    * *             i = 2  j = 1 2
    * * *           i = 3  j = 1 2 3
    * * * *         i = 4  j = 1 2 3 4
    * * * * *       i = 5  j = 1 2 3 4 5
        
    j与i的关系: j <= i
*/
for(var i = 1; i <= 5; i++){
    // 列
    for(var j = 1; j <= i; j++){
        document.write('*&nbsp;&nbsp;');
    }
    // 行
    document.write('<br>');
}

for-in

json格式的数据: 对象 Object

以键值对的方式存在

var 变量 = {

属性名: 属性值,

属性名1: 属性值1

};

属性名可以加引号 也可以不加 建议使用字符串'''

.后面不能加'' .后面不能加变量

var obj = {
    name: '迪丽热巴',
    'age': 18,
    'height': 178
};
console.log(obj); // {name: "迪丽热巴", age: 18, height: 178}

获取

获取对象的属性值:

变量.属性名

对象[变量]

console.log(obj.name);
console.log(obj.age);
// console.log(obj.'age'); // .后面不能加'' .后面不能加变量
var a = 'age';
console.log(obj.a); // 得不到正确结果

// 语法: 对象[变量]
console.log(obj[a]);

设置

对象.属性名 = 值;

obj.age = 28;

遍历

for(var 变量名 in 对象){

变量名---> 对象中的每一个属性名

对象[变量名] ---> 对象中属性名对应的属性值

}

for-in 即可以遍历对象 也可以遍历 数组和集合

for(var k in obj){
    console.log(k, obj[k]);
}

// for-in 即可以遍历对象 也可以遍历 数组和集合
var arr = ['秦时明月', '海贼王', '死神来了'];
for(var i in arr){
    console.log(i, arr[i]);
}

函数

函数: 将具有独立作用的代码块放到一起 在有需要的时候调用

作用: 提高代码的复用率 减少代码量

场景:

\1. 事件处理函数: 元素.事件 = function(){}

\2. 对象的方法: var obj = {

'方法名': function(){}

}

\3. 代码的封装复用

函数声明

函数: 由事件驱动的或者在有需要的时候被重复调用的代码块

\1. 函数声明:

1.1 声明函数: function 函数名() { // 代码块 }

1.2 调用函数: 函数名();

// 1.1 声明函数: function 函数名() { // 代码块 }
function map() {
    for(var i = 0; i <= 100; i++){
        console.log(i);
    }
};

// 1.2 调用函数: 函数名();
map();

\2. 字面量声明/表达式声明:

2.1 声明函数: var 变量名 = function(){ // 代码块 }

2.2 调用函数: 变量名();

// 2.1 声明函数: var 变量名 = function(){ // 代码块 }
var map1 = function(){
    for(var i = 0; i <= 100; i++){
        console.log(i);
    }
}
// 2.2 调用函数: 变量名();
map1();

注意:

\1. 函数只声明 不调用 不起作用

\2. 函数命名规范和变量的命名规范一致

\3. 函数声明调用可以在声明之前或者之后, 字面量声明方式只能在声明之后

// 1.1 声明函数: function 函数名() { // 代码块 }
// map();
function map() {
    for(var i = 0; i <= 100; i++){
        console.log(i);
    }
};


// 2.1 声明函数: var 变量名 = function(){ // 代码块 }
// map1(); // map1 is not a function map1不是一个函数
var map1 = function(){
    for(var i = 0; i <= 100; i++){
        console.log(i);
    }
}

参数

介绍

可变的数据都抽取参数

形参: 形式参数 用来接收实参传递过来的数据 function后面的()里

类似于变量 命名规范和变量一致

实参: 实际数据 传递给函数的形参的具体的数 函数调用的()里

arguments: 实参的集合 在每一个函数中都有

注意:

\1. 形参实参一一对应

\2. 多个参数: 用 , 隔开

function sum(start) {
    var s = 0;
    for (var i = start; i <= 100; i++) {
        s += i;
    }
    console.log(s);
}
sum(1);
sum(50);
sum(70);

// 30 - 1000
// 50 - 800
// 600 - 900

/* 
    多个参数: 用 , 隔开
*/
function sum1(start, end) {
    var s = 0;
    for (var i = start; i <= end; i++) {
        s += i;
    }
    console.log(s);
}
sum1(1, 100);
sum1(30, 1000);
sum1(50, 800);

/* 
    3 5 6 7 8
    21 34
    100 30 40 56 90
    666  8888 9999 10001 111 121

    当参数个数不确定的时候  干脆一个都不写 用arguments 
    arguments也是一个集合 有长度和下标
        是实参的集合
*/
function sum2() {
    console.log(arguments);
    var s = 0;
    // 获取arguments中每一个数据
    for(var i = 0; i < arguments.length; i++){
        console.log(arguments[i]);
        s += arguments[i];
    }
    console.log(s);
};
sum2(3, 5, 6, 7, 8);
sum2(21, 34);
sum2(100, 30, 40, 56, 90);

arguments和形参关系:

是同一个, 都是用来存储实参的

两者互相影响

/* 
    arguments和形参关系: 
        是同一个, 都是用来存储实参的
        两者互相影响 
*/
function fn(a, b) {
    console.log(a, b); // a = 10 b = 20
    console.log(arguments); // [10, 20]
    a = 10000;
    console.log(arguments); // [10000, 20]

    arguments[1] = 666;
    console.log(a, b); // 10000 666
};
fn(10, 20);

参数问题

  1. 当形参和实参个数不相等的时候:

    当形参个数大于实参个数 多余的形参是undefined

    当实参个数大于形参个数 多余的实参不能通过形参获取 通过arguments获取

    function fn(a, b, c) {
        console.log(a, b, c);
    };
    fn(1, 2, 3);
    fn(20, 30); // a=20 b=30 c=undefined
    fn(20, 30, 40, 50, 60); // a=20 b=30 c=40 
  2. 函数名重复: 后面的覆盖前面的

    function fn1() {
        console.log(2);
    }
    
    function fn1() {
        console.log(20 + 30);
    }
    fn1(); // 50

参数的数据类型

number string null undefined boolean

object array function

都可以作为实参进行传递 一般不使用null undefined

function fnT(a) {
    console.log(a);
};
fnT(30);
fnT('abcd');
fnT(true);
fnT(null);
fnT(undefined);
var obj = {
    name: '张三丰',
    age: 88
};
fnT(obj);

var arr = [2, 3, 4, 5];
fnT(arr);

function sum() {
    console.log(10 + 20);
}
fnT(sum);

作用域

域: 区域 范围 空间

作用: 读、写

读---获取

写---设置

作用域: 变量和函数可以起作用的范围

es5中作用域通过function进行划分的

全局作用域: script标签下(function的{}外面)

在全局作用域下用var\function 声明的变量和函数 叫做全局变量\全局函数

作用于整个js 在整个js中都可以进行读写

局部作用域: function的{}中

在局部作用域下用var/function声明的变量和函数 叫做局部变量\局部函数

作用于当前的局部作用域 但凡出了{} 就会被销毁

// 外面--->全局作用域
var a = 10;
function fn() {
    // 函数里面--->局部作用域

    console.log(a);

    var b = 30;
    console.log(b);
}

fn();

作用域链

作用域链: 是js的一中查找机制, 先找自身作用域是否有值, 如果有就直接使用, 如果没有, 向上一级作用域去查找, 找到全局作用域, 如果还没有, 就报错: is not defined

决定了变量和函数向上一级作用域查找的过程

// s: 全局变量
var s = 10;
function sum() {
    // 局部作用域
    var s = 30;
    // sum的局部函数
    function fun() {
        console.log(s); // 30
    }
    fun();
}
sum();

预解析\变量提升

js代码在执行的时候 至少分成2步:

  1. 预解析: 找var、function, 将var声明的变量, 声明提到最前, 找function声明的函数, 将整个函数存储在内存中

  2. 逐行解析: 从上到下执行

console.log(a); // undefined
var a = 20;
/* 
    解析过程:
        var a;
        cobsole.log(a); // undefined
        a = 20;
*/

fn();
function fn() {
    console.log(10+20);
};

/* 
    解析过程:
        function fn() {
            console.log(10+20);
        };

        fn();
*/

局部作用域解析:

当函数被调用的时候, 就会行程一个新的局部作用域, 解析过程遵循预解析

function a() {
    console.log(a);
    var a = 20;
    console.log(a);
}
a();

/* 
    局部作用域解析过程:
        64: var a;
        63: log(a); undefined
        64: a = 20;
        65: log(a); 20
*/

带有参数的函数: 被调用的时候, 形参会在第一时间被赋值

function fn(a) {
    console.log(a);
    a = 30;
    console.log(a);
}
fn(15);
/* 
    预解析: 形参的声明: var a;
    逐行解析:
        形参的赋值: a = 15
        81: log(a); 15
        82: a = 30;
        83: log(a); 30
*/

函数返回值

函数就像一个小黑屋 将局部变量和函数囚禁在其中 在屋子外面得不到这个数据

每个函数被调用以后都有返回值, 默认返回值是undefined

接收返回值: var 变量 = 函数();

用 return 设置返回值

语法: return 要返回的值;

可以将函数的局部变量或者局部函数返回到函数外面

return:

\1. 设置返回值, 一次只能返回一个值;

如果返回多个数据 可以使用数组或者对象(推荐)

\2. 结束代码

function sum() {
    var a = 20 + 30;
    console.log(a);
}
var f = sum();
console.log(f); // undefined

function sum1() {
    var b = 30 + 40;
    return b;
}
var f1 = sum1();
console.log(f1);

// 1. 设置返回值, 一次只能返回一个值; 
// 如果返回多个数据 可以使用数组或者对象(推荐)
function sum2() {
    var a = 30;
    var b = 40;
    // return a,b;
    return {
        'a': a,
        'b': b
    };
}
var f2 = sum2();
console.log(f2);

// 2. 结束代码
function sum3() { 
    var a = 20;
    return a;
    var b = 30;
    console.log(b);
}
sum3();

函数封装

\1. 实现单个效果 6!

\2. 新建一个空函数

\3. 重复代码放进去

\4. 调用函数 确定可以执行

\5. 抽参: 将不确定的数据变成形参

\6. 传参: 抽出来谁就把谁传进去

\7. 设置返回值并接收返回值

function getMax(data) {
    var max = data[0];
    // console.log(max);
    // 每一个
    for (var i = 0; i < data.length; i++) {
        // 每一项和最大值进行比较
        // console.log(data[i]);
        if (data[i] > max) {
            max = data[i];
        }
    }
    // console.log(max);
    return max;
}
var m = getMax(arr);
console.log(m);
var m1 = getMax(arr1);
console.log(m1);
var m2 = getMax(arr2);
console.log(m2);

函数的返回值

函数的返回值的数据类型可以是一切数据类型

function gr() {

    function inner() {
        console.log(123456);
    }
    return inner;
    return [40, 30];
    return {
        a: 30,
        b: 40
    };
    return undefined;
    return null;
    return true;
    return 'abc';
    return 30;
}
var a = gr();
console.log(a); // a=function inner(){}
// a();

页面重复效果实现

\1. 获取到父元素(结构一致的父元素) 可以复制粘贴的部分最大的层级 li

\2. 实现一个父元素中的效果

\3. 封装效果

\4. 循环实现每一个父元素的效果

注意: 一般不单独抽取下标作为参数 将整个元素作为形参抽取出来

获取元素样式

基础语法

标准(ie9及以上): getComputedStyle(元素).属性名

ie(ie8及以下): 元素.currentStyle.属性名

// 获取元素
var div = document.getElementsByTagName('div')[0];
console.log(div);
var w = getComputedStyle(div).width;
console.log(w);
var c = getComputedStyle(div).color;
console.log(c);

/* 
    getComputedStyle在ie下会报错
*/
console.log(div.currentStyle); // undefined 
// console.log(div.currentStyle.width);


// getComputedStyle是一个函数 在ie下不存在的
// 所有的全局的函数和变量都属于 window
console.log(window);
console.log(window.getComputedStyle); // 标准: 函数 ie: undefined
console.log(div.currentStyle); // 标准: undefined ie: 对象

兼容:

当一个是undefined一个不是的时候 用方法/属性是否存在来做判断

if(window.getComputedStyle){
    // 标准
    var w = getComputedStyle(div).width;
    console.log(w);
} else {
    // ie
    var w = div.currentStyle.width;
    console.log(w);
}

封装

js中.相当于白勺的 后面全都是字符串 如果要使用变量 用[变量]

如果封装的函数里面有数据要在函数外面使用的时候 要设置返回值

// 获取元素样式
function getStyle(ele, attr) {
    // ele: 元素
    // attr: 属性
    if (window.getComputedStyle) {
        var w = getComputedStyle(ele)[attr];
    } else {
        var w = ele.currentStyle[attr];
    }
    // console.log(w);
    return w;
}
var c = getStyle(div, 'background');
console.log(c);

var w = getStyle(div, 'width');
console.log(w);

使用

js库: 将封装好的函数 放到一个js文件中 在后续有需要的时候 直接引入js库 调用函数

每个函数 必须要: 函数的作用 参数说明

<p>qwert</p>
<!-- 1. 引入js库 -->
<script src="fsy.js"></script>
<!-- 2. 再写script -->
<script>
    var p = document.getElementsByTagName('p')[0];
    var w = getStyle(p, 'width');
    console.log(w);
</script>

this

概念

this: 指代词 存在于页面的任何位置

不同的位置this具有不同的含义

指向:

\1. 全局: window

\2. 事件处理函数: 触发源 点谁就是谁

\3. 普通函数: window

\4. 对象的方法: 对象

console.log(window);

var div = document.getElementsByTagName('div')[0];
div.onclick = function () {
    console.log(this);
};

function sum() {
    console.log(this);
}
sum();

var obj = {
    name: '王一博',
    'tip': function () {
        console.log(this);
    }
}
obj.tip();

this使用场景

for循环嵌套的事件中, 获取到当前元素, 通过this来获取

/ 获取元素
var lis = document.getElementsByTagName('li');
console.log(lis);

// 每个
for(var i = 0; i < lis.length; i++){
    console.log(lis[i]);
    // 添加事件
    lis[i].onclick = function () {
        // 当前li的内容 
        // 获取到当前li
        console.log(i); // 
        console.log(lis[i]); // undefined
        console.log(this);
        console.log(this.innerHTML);
    };
}

排他思想:

除了自己 其他都默认值的情况

  1. 先将所有的都回归默认值

  2. 再给当前这一个单独设置

// 1. 获取元素
var lis = document.getElementsByTagName('li');
console.log(lis);
// 2. 每一个
for(var i = 0; i < lis.length; i++){
    // 3. 添加事件
    lis[i].onclick = function () {
        // 4. 让所有li的内容隐藏
        for(var j = 0; j < lis.length; j++){
            lis[j].style.color = '#fff';
        }

        // 5. 让当前li的内容显示
        // 获取当前li
        console.log(this);
        this.style.color = '#000';
    };
}

自定义属性

概念

属性: 写在起始标签上的 除了标签名以外的都是属性

固有属性: 规定好作用的属性 id class title

自定义属性: 由开发人员自己规定的属性名和属性值的属性 ttt="abc"

获取属性: 元素.属性

设置属性: 元素.属性 = 值;

直接写在标签上的自定义属性 获取不到 得到的是undefined

通过js设置的自定义属性 在标签上看不到的 但是可以正常的获取和设置

var div = document.getElementsByTagName('div')[0];
console.log(div);
// 获取属性
// 直接写在标签上的自定义属性 获取不到 得到的是undefined
var t = div.ttt;
console.log(t);

// 设置
// 通过js设置的自定义属性 在标签上看不到的 但是可以正常的获取和设置
div.abc = 123;
console.log(div.abc); // 123

使用

使用场景: 当多个元素 每个都需要有2个及以上状态的时候 每个元素都需要自己的开关的时候 使用自定义属性来标识

// 1. 获取元素
var divs = document.getElementsByTagName('div');
console.log(divs);

// 每个div都要有一个假设的状态
// 使用自定义属性存储
// divs[0].tag = 1; // 1--40  2--100
// divs[1].tag = 1; // 1--40 2--100
// divs[2].tag = 1; // 1--40 2--100
// divs[3].tag = 1; // 1--40 2--100
// divs[4].tag = 1; // 1--40 2--100

// for(var i = 0; i < divs.length; i++){
//     divs[i].tag = 1;
// }

// 每个div做判断的时候  用自己的tag判断
for(var i = 0; i < divs.length; i++){
    // 设置自定义属性
    divs[i].tag = 1;
    // 点击
    divs[i].onclick = function () {
        // 用自己的tag判断 先获取自己
        console.log(this, this.tag);
        if(this.tag == 1){
            this.style.height = '100px';
            this.tag = 2;
        } else {
            this.style.height = '40px';
            this.tag = 1;

        }
    }
}

自定义索引

自定义索引: 自定义属性, 存储的值变成了下标

快速获取body: document.body

var arr = ['pink', 'red', 'skyblue', 'green'];
//        [button, button, button,  button]
var btns = document.getElementsByTagName('button');
console.log(btns);

// 数据和按钮的关系: 一一对应  下标一致
// 点击每一个按钮 切换背景色 换的是 按钮对应的数组中的颜色
// 要想切换背景色 必须先得到按钮的下标

// 自定义索引: 自定义属性, 存储的值变成了下标
// btns[0].tag = 0;
// btns[1].tag = 1;
// btns[2].tag = 2;
// btns[3].tag = 3;

// 每一个
for(var i = 0; i < btns.length; i++){
    // 存储自定义属性
    btns[i].tag = i;

    // 添加事件
    btns[i].onclick = function () {
        // 切换背景色
        // 先得到按钮的下标
        console.log(i); // 得不到正确的下标
        // 得到自定义索引  获取自定义属性tag
        console.log(this.tag);
        // 通过下标 得到数组arr中的值 数组[下标]
        console.log(arr[this.tag]);
        // 设置给body 
        // 快速获取body: document.body
        document.body.style.background = arr[this.tag];
    };
}

定时器

概念

定时器: 让代码每隔一段时间或等待一段时间后再执行的代码就叫做定时器

延迟定时器

延迟定时器: 让代码等待一会之后 在执行

只执行一次

语法: setTimeout(函数, 时间);

时间单位: 毫秒 1s = 1000ms

场景: 一次性广告 关不掉广告

setTimeout(function () {
    console.log('等待');
}, 3000);

间隔定时器

间隔定时器: 让代码每隔一段时间 就执行一次

不间断的执行

语法: setInterval(函数, 时间)

时间单位: 毫秒 1s = 1000ms

场景: 计时器 倒计时 轮播图 时钟 动态效果

setInterval(function () {
    console.log(1);
}, 1000);


function a() {
    console.log('输出');
}
// 每隔1s 执行a
setInterval(a, 1000);

清除定时器

定时器一旦开启 不会自动清除, 当不在需要定时器, 需要进行手动清除

定时器开启的时候, 会返回一个数字, 这个数字就是唯一标识

定时器一旦清除 再也找不到

var 变量 = setTimeout/setInterval(函数, 时间);

延迟定时器: 只执行一次

清除: clearTimeout(唯一标识timerId);

间隔定时器: 一直执行

清除: clearInterval(timerId);

var n = 5;
var timerId = setInterval(function () {
    n--;
    console.log(n);
    // 当n变成0之后 清除定时器
    if(n == 0){
        clearInterval(timerId);
    }
}, 1000);
console.log(timerId, 'id');

注意

唯一标识声明在全局

定时器的封装:

当定时器的函数执行的代码一样的时候 而是将定时器的第一个参数的函数 直接抽取封装

// 每隔
var t = null;
t = setInterval(auto, 1000);
console.log(t, 't');

function auto() {
    // 切换到下一张 1-->2-->3-->4--->5-->1
    n++;
    console.log(n);

    // 判断是否到最后
    if (n == 6) n = 1;

    // 改变图片地址
    img.src = './image/' + n + '.jpg';
}

对象

概念和分类

对象: 一切皆对象 js中所有的内容都可以看做一个对象

本地/原生对象: Number String Boolean Object Array Function Date RegExp Error

(三基础三复杂三其他)

内置对象: Global Math

宿主对象: DOM BOM

全局对象: window

Math

console.log(Math);
console.log(Math.PI); // π
console.log(Math.ceil(4.000001)); // 当小数点后有任意一个数 向上进一
console.log(Math.floor(3.999999)); // 向下取整 舍掉小数 
console.log(Math.round(4.49999)); // 四舍五入
console.log(Math.round(4.5000001)); // 四舍五入
console.log(Math.pow(2, 3)); // 2的3次方 pow 幂次方
console.log(Math.sqrt(9)); // 开根号
console.log(Math.abs(-10)); // 10
/* 
    Math.random() : 求0-1之间的随机数
    Math.random() * 数 : 求 0-数 之间的随机数
    Math.random() * (y-x) + x: 求 x-y 之间的随机数 y > x
*/
console.log(Math.random());
console.log(Math.random() * 10);
// 30-40随机数
console.log(Math.random() * (40 - 30) + 30);

console.log(Math.max(32,43,5765,7723,54,12)); // 求最大值
console.log(Math.min(32,43,5765,7723,54,12)); // 求最小值

时间

创建时间

创建当前时间: var 变量名 = new Date();

当前这一行执行到的时候的一瞬间的时间

var date = new Date();

console.log(date);

/* 

		Tue Aug 17 2021 10:39:21 GMT+0800 (中国标准时间)

		 星期 八月 日 年   时:分:秒  时区

*/

特殊格式的时间

console.log(date.toLocaleDateString()); // 2021/8/17

console.log(date.toLocaleTimeString()); // 上午10:43:17

创建其他时间(过去、未来)

var 变量 = new Date(数值, 数值, 数值, 数值, 数值, 数值);

月: 0-11表示1-12月

var d1 = new Date(1997, 0, 1, 21, 21, 21);

console.log(d1);

var 变量 = new Date('字符串'); 不允许使用中文字符

var d2 = new Date('2021/8/20 21:21:21');

var d2 = new Date('2021 8 20 20:21:21');

var d2 = new Date('2021&8&20 19:21:21');

var d2 = new Date('2021-8-20 18:21:21');

// var d2 = new Date('2021_8_20 17:21:21'); // 中文字符不能用

console.log(d2);

获取单个时间

// 创建时间
var d = new Date();
console.log(d);

// 年
console.log(d.getFullYear()); // 2021

// 月
console.log(d.getMonth()); // 0-11表示1-12月 7

// 日
console.log(d.getDate()); // 17

// 星期: 0-6表示周日-周六
console.log(d.getDay()); // 2
// 常见的星期处理
var week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
var w = d.getDay(); // 下标
console.log(week[w]);

// 时
console.log(d.getHours()); // 24小时制 10

// 分
console.log(d.getMinutes()); // 分钟 56

// 秒
console.log(d.getSeconds()); // 11

// 毫秒/时间戳
console.log(d.getTime()); // 从1970-1-1到现在的毫秒数 1629169075807

moment

  1. 百度: momentjs

Moment.js 中文网

  1. 保存js文件:

moment.js: 未压缩 学习

moment.min.js: 压缩 工作

  1. 使用

<!-- 3.1 引入公用库 -->
<script src="./js/moment.js"></script>
<!-- 3.2 自己的script标签 -->
<script>
    /* 
        format
    */
    // 创建时间对象
    var m = moment();
    console.log(m);
    // 格式化:
    console.log(m.format('YYYY')); // 年
    console.log(m.format('MM')); // 月
    console.log(m.format('DD')); // 日
    console.log(m.format('d')); // 星期
    console.log(m.format('HH')); // 小时
    console.log(m.format('mm')); // 分钟
    console.log(m.format('ss')); // 秒

    // 可以用任何格式拼接起来
    document.body.innerHTML = m.format('YYYY年MM月DD日 星期d HH:mm:ss');
</script>

String

创建方式

\1. 字面量创建: 是一个包装对象, 不是一个真正的字符串对象

// 1. 字面量创建: 是一个包装对象, 不是一个真正的字符串对象
var str = 'abc123';
console.log(str, typeof str);

\2. 关键字创建

// 2. 关键字创建
var str1 = new String('abcsdsew1234');
console.log(str1, typeof str1); // object

\3. 字符串有长度有下标

// 3. 字符串有长度有下标
// 长度: 字符串.length
console.log(str1.length);
// 下标
console.log(str1[3]);

\4. 字符串的比较规则: 从左往右比较每一个字符的ASCII码

// 4. 字符串的比较规则: 从左往右比较每一个字符的ASCII码
// 0--48  9--57  A--65 Z--90 a--97 z--122 
console.log('2' > '10000'); // true 50 > 49

查找

charAt

/* 
    1. 找到指定下标字符: 字符串.charAt(下标)
*/
var str = '123456789';
console.log(str.charAt(5)); // 6

charCodeAt

/* 
    2. 找到指定下标的字符的ASCII值: 字符串.charCodeAt(下标);
*/
console.log(str.charCodeAt(5)); // 54

indexOf

/* 
    3. 字符在字符串中出现的位置:
        字符串.indexOf(字符a, [起始下标]);
        起始下标: 可选, 默认从0开始
        找字符串中字符a出现的位置,如果找到就返回下标,如果找不到就返回-1
*/
var str = 'ehdgfewyetryuiodfghjsdrty';
// g
console.log(str.indexOf('g')); // 3
console.log(str.indexOf('g', 4)); // 17
console.log(str.indexOf('g', 18)); // -1

lastIndexOf

/* 
    4. 字符在字符串中出现的位置:
    字符串.lastIndexOf(字符a, [起始下标]);
    起始下标: 可选, 默认从最后一位开始
    找字符串中字符a出现的位置,如果找到就返回下标,如果找不到就返回-1
*/
console.log(str.lastIndexOf('g')); // 17
console.log(str.lastIndexOf('g', 16)); // 3
console.log(str.lastIndexOf('g', 2)); // -1

截取

substring

语法: 字符串.substring(起始下标, 结束下标);

起始下标/结束下标: 可选 可写可不写

返回: 截取出来的字符

不传参: 返回整个字符串

传一个参数: 表示从当前下标位置开始截取到整个字符串的末尾

传两个参数:

\1. 起始下标 < 结束下标: 表示从起始下标位置开始 截取到结束下标位置为止 包含起始下标的字符 不包含结束下标的字符

\2. 起始下标 > 结束下标: 互换位置 参考上述规则

\3. 为负数: 将负数转成0 参考上述规则

var str = 'abcdefg';
console.log(str.substring());
console.log(str.substring(2)); // cdefg
console.log(str.substring(2, 4)); // cd
console.log(str.substring(4, 2)); // cd
console.log(str.substring(4, -2)); // 4, 0 0--4  abcd

slice

语法: 字符串.slice(起始下标, 结束下标);

起始下标/结束下标: 可选 可写可不写

返回: 截取出来的字符

不传参: 返回整个字符串

传一个参数: 表示从当前下标位置开始截取到整个字符串的末尾

传两个参数:

\1. 起始下标 < 结束下标: 表示从起始下标位置开始 截取到结束下标位置为止 包含起始下标的字符 不包含结束下标的字符

\2. 起始下标 > 结束下标: 返回空字符

\3. 结束下标为负数: 表示从右往左有几位不要

var str = 'abcdefg';
console.log(str.slice()); // abcdefg
console.log(str.slice(2)); // cdefg
console.log(str.slice(2, 4)); // cd
console.log(str.slice(4, 2)); // 空字符
console.log(str.slice(0, -2)); // abcde

substr

语法: 字符串.substr(起始下标, 长度);

起始下标/长度: 可选 可写可不写

返回: 截取出来的字符

不传参: 返回整个字符串

传一个参数: 表示从当前下标位置开始截取到整个字符串的末尾

传2个参数: 从起始下标开始截取长度为第二个数的字符

var str = 'abcdefg';
console.log(str.substr()); // abcdefg
console.log(str.substr(2)); // cdefg
console.log(str.substr(2, 4)); // cdef

其他

split

Split: 分割字符串 返回数组

语法: 字符串.split('分割符');

分割符可以是一切字符 标签 字符 可传可不传

不传: 默认整个字符串为数组的一项

var str = 'abcabcabcabc';

console.log(str.split());

console.log(str.split('')); // 把字符串的每一个字符都变成数组的一项

console.log(str.split('ab')); // ["", "c", "c", "c", "c"]

replace

replace: 替换字符串

语法: 字符串.replace('被替换的字符'/正则, '新字符'/函数);

一次只能替换一个

var str = 'abcabcabc';

console.log(str.replace('abc', '***'));

toUpperCase/toLowerCase

转大写: 字符串.toUpperCase();

转小写: 字符串.toLowerCase();

var str = 'DFyhuhiuGUYG';

console.log(str.toUpperCase());

console.log(str.toLowerCase());

// 忽略大小写 等号左右两边都转成大写 或者 都转成小写

var s1 = 'abcdEfG';

var s2 = 'AbcdEFG';

console.log(s1.toUpperCase() == s2.toUpperCase());

trim

trim: 去除左右空格

字符串.trim();

var str = '    you are a happy child      ';

console.log('(' + str + ')');

console.log('(' + str.trim() + ')');

数组

概念

数组: 用来存储不定数量不定类型的数据的容器

有长度有下标

创建数组

\1. 字面量创建:var 变量 = [值, 值, ...];

\2. new关键字创建:

var 变量 = new Array(...data);

参数只有一个并且是数字: 表示当前数组的长度

var arr = [1, 2, 3, 4, 5];
console.log(arr);
/* 
    2. new关键字创建: 
        var 变量 = new Array(...data);
        参数只有一个并且是数字: 表示当前数组的长度
*/
var arr1 = new Array(1,2,3,4);
console.log(arr1);

var arr2 = new Array('abc');
console.log(arr2);

var arr3 = new Array(4);
console.log(arr3); // [empty × 4]

length

长度: 可以获取可以设置

获取: 数组.length

设置: 数组.length = 值;

var arr = ['a', 'b', 'c', 'd', 'e'];
console.log(arr.length);

arr.length = 10;
console.log(arr.length, arr);
arr.length = 3;
console.log(arr);

下标

下标: 索引, 标志每个数据的位置

通过下标取值: 数组[下标]

设置值: 数组[下标] = 值;

var arr = [1,2,3,4,5,6,7,8];
console.log(arr[5]);
arr[10] = 11;
console.log(arr);

数据存储

栈: 基础数据类型的声明和数据 复杂数据类型的声明和地址

堆: 复杂数据类型的数据

基础数据类型: 数据相对单一 数据量相对较小 声明和数据同时存储在栈中

复杂数据类型: 数据多样化 数据量相对较大 声明存储在栈 数据存储在堆

var arr = [1,2,3,4];
console.log(arr);

arr[5] = 1000;
console.log(arr);

深浅拷贝

浅拷贝

浅拷贝: 地址的赋值 出现一改全改的问题

var arr = [1, 2, 3, 4];
var brr = arr;
console.log(arr, brr);
arr[4] = 1000;
console.log(arr);
console.log(brr);

深拷贝

深拷贝: 重新划分一块内存 将原来的数据在单独存储到新的内存中

var crr = [5, 6, 7, 8];
var drr = [];
// 将crr的每一个数据对应的存储到drr中
// crr的每个数据的下标和drr的下标一致
// 每一个
for(var i = 0; i < crr.length; i++){
    drr[i] = crr[i]
}
console.log(crr, drr);

crr[4] = 1000;
console.log(crr, drr);

栈方法

push: 在数组的末尾添加一项或者多项, 返回添加后的数组的长度

数组.push(...data);

pop: 在数组的末尾删除一项, 返回被删除的项

数组.pop();

unshift: 在数组的开头添加一项活着的多项, 返回添加后数组的长度

数组.unshift(...data);

shift: 在数组的开头删除一项, 返回被删除的项

数组.shift();

var a = arr.push(3,4,5);
console.log(arr, a);

var b = arr.pop();
console.log(arr, b);

var c = arr.unshift('a', 'b');
console.log(arr, c);

var d = arr.shift();
console.log(arr, d);

splice

splice: 万能的splice 增删改

语法: 数组.splice(起始下标, 删除的个数, ...data)

...data: 多个添加进来的数据 可写可不写

返回值: 被删除的项组成的新数组

删除: 数组.splice(起始下标, 删除的个数)

添加: 数组.splice(起始下标, 0, ...data)

替换: 删几个加几个 数组.splice(起始下标, 删除个数, ...data)

var arr = ['貂蝉', '吕布', '小乔', '周瑜', '大乔', '孙策'];
var brr = arr.splice(3, 1);
console.log(arr, brr);

// 添加
arr.splice(3, 0, '鲁班', '王昭君', '恺', '程咬金', '蔡文姬');
console.log(arr);

// 替换
var crr = arr.splice(2, 1, '后羿');
console.log(arr, crr);

查找

indexOf: 数组.indexOf(项, 起始下标)

lastIndexOf: 数组.lastIndexOf(项, 起始下标)

找到了就返回下标 找不到就返回-1

查找的项和数组中的项必须全等才能找到

var arr = [1, 2, 3, '2', '3'];
console.log(arr.indexOf('1'));

concat

concat: 多个值拼接到数组中, 返回拼接后的 新数组 数组.concat(...data);

var arr = [1, 2, 3];
var brr = [5, 6, 7];
var ab = arr.concat(4, brr);
console.log(arr, brr);
console.log(ab);

slice

slice: 截取指定下标的数组中的项 返回组成的 新数组 数组.slice(起始下标, 结束下标); 不传参: 整个数组 传1个参数: 从起始下标开始截取到数组的结尾 传2个参数: 起始 < 结束: 从起始下标开始截取到结束下标位置的项 包含起始下标 不包含结束下标 结束 < 起始: 返回空数组 结束下标为负数: 后面有几个不要

var arr = [1, 2, 3, 4, 5];
console.log(arr.slice()); // [1, 2, 3, 4, 5]
console.log(arr.slice(3)); // [4, 5]
console.log(arr.slice(2, 5)); // [3, 4, 5]
console.log(arr.slice(5, 2)); // []
console.log(arr.slice(1, -2)); // [2, 3]

reverse

翻转: reverse 数组.reverse();

var arr = [4, 5, 6, 7, 8];
arr.reverse();
console.log(arr);

join

join: 将数组的每一个项用连接符连接起来 返回 字符串 数组.join('连接符'); 连接符可以是一切字符 可传可不传 默认以,链接

var arr = [1, 2, 3, 4];
console.log(arr.join()); // 1,2,3,4
console.log(arr.join('')); // 1234
var a = arr.join('<b>123</b>');
console.log(a);
document.body.innerHTML = a;

实现翻转字符串

var str = 'abcdefg'; // gfedcba
// 5.1 将字符串转数组
// 5.2 使用数组的翻转方法
// 5.3 数组在拼接成字符串
var arr = str.split('').reverse().join('');
console.log(arr);

排序算法

选择

原理: 那数组的每一项和当前项后面的每一项做对比 如果当前项比后面项大,互换位置

var arr = [33, 58, 66, 77, 88, 22, 12, 6, 8];
// 每一项
for(var i = 0; i < arr.length; i++){
    // 当前项后面的每一项
    for(var j = i + 1; j < arr.length; j++){
        // console.log(arr[i], arr[j]);
        // 如果当前项比后面项大
        if(arr[i] > arr[j]){
            var temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
}

冒泡

原理: 用相邻的两个数字做比较 如果前面的比后面的大 互换位置

var brr = [99, 1, 46, 37, 33, 22, 11, 5];

// 有多少个项 循环多少次
for(var i = 0; i < brr.length; i++){
    for(var j = 0; j < brr.length - i; j++){
        // j = 0  1
        // j = 1  2
        // j = 2  3
        // console.log(brr[j], brr[j+1]);
        //  如果前面的比后面的大
        if(brr[j] > brr[j+1]){
            // 互换位置
            var temp = brr[j];
            brr[j] = brr[j+1];
            brr[j+1] = temp;
        }
    }
}
console.log(brr);

sort

数组.sort(函数);

函数可写可不写

默认按照从小到大的ASCII值排序

var arr = [9, 3, 4, 5, 2, 6, 4, 10, 40];
arr.sort();
console.log(arr);

// 函数: 有2个参数 表示相邻的两个数据
var arr = [9, 3, 4, 5, 2, 6, 4, 10, 40];
arr.sort(function (a, b) { // 形参一直存在 名字自定义
    // console.log(a, b);
    // 设置返回值
    // return a-b; // 从小到大
    return b-a; // 从大从小
});
console.log(arr);

中文排序

按照本地语言环境进行对比

中文排序: 字符串.localeCompare(字符串2)

返回值: -1 0 1

var s1 = '张三';
var s2 = '李四';
console.log(s1.localeCompare(s2));
console.log(s2.localeCompare(s1));
console.log(s2.localeCompare(s2));

迭代方法

迭代: 数据筛选过滤和处理

every: 对数组的每个项做一个判断,如果每个数据执行函数后返回结果都为true, 返回结果就是true, 如果有一个是false, 返回结果就是false

数组.every(函数);

用函数的返回值来做判断

有3个形参(项, 下标, 原数组)

some: 对数组的每个项做一个判断,如果每个数据执行函数后返回结果都为false, 返回结果就是false, 如果有一个是true, 返回结果就是true

数组.some(函数);

用函数的返回值来做判断

有3个形参(项, 下标, 原数组)

filter: 挑选 每个数据执行函数后 返回结果为 true的 数据, 组成新的数组 返回 返回一个新数组

数组.filter(函数);

用函数的返回值来做判断

有3个形参(项, 下标, 原数组)

map: 遍历数组 接收每个函数的返回值 组成新数组 返回

forEach: 遍历数组 纯粹遍历 没有任何返回值

var arr = [1, 2, 3, 4, 5, 6];
// 判断arr的每个数据是不是都大于0
var res = arr.every(function (a, b, c) {
    console.log(a, b, c);
    return a < 3;
    return a > 0;
});
console.log(res);


var res1 = arr.some(function (val, ind, array) {
    console.log(val, ind, array);
    return val > 1;
});
console.log(res1);


var res2 = arr.filter(function (val, ind, array) {
    console.log(val, ind, array);
    // return val >= 3;
    return val % 2 == 0;
});
console.log(res2);

var res3 = arr.map(function (v, i, a) {
    console.log(v, i, a);
    // return i;
    // return a;
    return 1;
});
console.log(res3);

var res4 = arr.forEach(function (v, i, a) {
    console.log(v, i, a);
    // arr[i] = 10;
    return 1;
});
console.log(res4); // undefined
console.log(arr);

正则

概念

正则: RegExp, 用提前定义好的特殊字符组成的‘规则字符串’, 用来检索、替换文本

\1. 屏蔽敏感词

\2. 登录注册

创建

\1. new关键字创建

var 变量 = new RegExp('规则字符串', '修饰符');

var reg = new RegExp('web', 'ig');
console.log(reg); // /web/gi
console.log(typeof reg); // object

\2. 字面量创建

var 变量 = /规则字符串/修饰符;

var reg1 = /web/ig;
console.log(reg1);

修饰符作用

i: ignore case 忽略大小写

g: global 全局(整个字符串)

检索方法

字符串

replace

replace: 字符串.replace('字符'/正则, '新字符/函数); 函数有形参: 匹配到的符合条件的字符 函数的返回值 就是替换的新字符

var str = 'web123web456web789Web1WEB23';
console.log(str.replace('web', '**'));

var reg = /web/ig;
console.log(str.replace(reg, '*'));
// 在替换的字符长度不确定的时候 使用函数来做替换
var a = str.replace(reg, function (s) {
console.log(s);
return 'abc';
});
console.log(a);

split

split: 字符串.split('分割符'/正则);

var str = 'web123web456web789Web1WEB23';
var reg = /\d/; // 匹配数字0-9
var reg = /web/i;
console.log(str.split(reg));

search

search: 字符串.search(正则) 找到返回下标 找不到返回-1

var str = 'web123web456web789Web1WEB23';
var reg = /\d/;
var reg = /\s/; // 空格
console.log(str.search(reg));

match

match: 将符合正则的项组成新数组返回 一个: ["WEB", index: 22, input: "web123web456web789Web1WEB23", groups: undefined] 匹配的结果 下标 原字符串 多个: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "1", "2", "3"]

var str = 'web123web456web789Web1WEB23';
var reg = /WEB/;
console.log(str.match(reg));

var reg = /\d/g;
console.log(str.match(reg));

正则

惰性查找: 一次只匹配一个 下一次再找下一个

exec

exec: 返回匹配到的项 组成新数组返回

正则.exec(字符串);

不加g: 每次查找都从0开始

加g: 从上一次匹配到的结果的下一个字符开始查找

var str = 'web123web456web789Web1WEB23';
// var reg = /web/;
var reg = /web/g;
console.log(reg.lastIndex); // 下一正则开始查找的位置
console.log(reg.exec(str));
console.log(reg.lastIndex); // 下一正则开始查找的位置
console.log(reg.exec(str));
console.log(reg.lastIndex); // 下一正则开始查找的位置
console.log(reg.exec(str));
console.log(reg.lastIndex); // 下一正则开始查找的位置
console.log(reg.exec(str)); // null
console.log(reg.lastIndex); // 下一正则开始查找的位置
console.log(reg.exec(str)); // 从0开始

test

test: 返回是否有符合正则的字符 有返回true 没有返回false 正则.test(字符串); 不加g: 每次查找都从0开始 加g: 从上一次匹配到的结果的下一个字符开始查找

var str = 'web123web456web789Web1WEB23';
// var reg = /web/;
var reg = /web/g;
console.log(reg.lastIndex); // 0
console.log(reg.test(str));
console.log(reg.lastIndex); // 3
console.log(reg.test(str));

元字符

  1. .: 匹配除换行以外的任意字符;

    var str ='\n123\n456';
    console.log(str);
    var reg = /./;
    console.log(reg.exec(str));
  2. 字符集: 不需要加任何引号、分隔

    /* 
    2. 字符集: 不需要加任何引号、分隔
      []: 字符集, 表示匹配字符集中的任意一个字符
      [^]: 非字符集, 表示匹配除字符集以外的任意一个字符
      0-9 0-9之间的每一个数字
      a-z a-z之间的每一个字母
      A-Z A-Z之间的每一个字母
    */
    var str = ',today is not bad day';
    var reg = /[today,is]/; // 匹配的字母有: t o d a y i s ,
    console.log(reg.exec(str));
    
    var reg = /[^to,day]/;
    console.log(reg.exec(str)); // 空格 [" ", index: 6, input: ",today is not bad day", groups: undefined]
    
    
    var str = '9web123';
    var reg = /[0-9]/;
    console.log(reg.exec(str));
  3. 数字

    /* 
    3. 数字
      \d: 数字0-9
      \D: 除数字以外的任意字符
    */
    var str = 'today is 4';
    var reg = /\d/;
    console.log(reg.exec(str)); // 4
    
    var reg = /\D/;
    console.log(reg.exec(str)); // t
  4. 数字、字母、_

     /* 
     4. 数字、字母、_
       \w: 表示匹配字母、数字、_任何一个
       \W: 表示匹配除字母\数字\_以外的任何一个
     */
     var str = '1you are a beautiful girl';
     var reg = /\w/;
     console.log(reg.exec(str));
     
     var reg = /\W/;
     console.log(reg.exec(str)); // 空格
  5. 空格

     /* 
     5. 空格
       \s: 匹配空格
       \S: 匹配除空格外的任何一个
     */
     var str = ' How are you';
     var reg = /\s/;
     console.log(reg.exec(str)); // 0
     
     var reg = /\S/;
     console.log(reg.exec(str)); // H
  6. 边界, 一个字母有2个边界

    /* 
    6. 边界, 一个字母有2个边界
      \b: 单词边界
      \B: 非单词边界
    */
    var str = 'today is a finaly day';
    var reg = /\ba/; // 匹配a的左边是空格的a
    console.log(reg.exec(str)); // 9
    
    var reg = /\Ba\B/; // 匹配a的左边不是空格并且a的右边不是空格的a
    console.log(reg.exec(str)); // 3
  7. 开头、结尾 整个字符串来做判断

    /* 
    7. 开头、结尾 整个字符串来做判断 
      一个字符串只有一个开头(第一个字符) 一个结尾(最后一个)
      ^a: 以a为开头
      a$: 以a为结尾
    
      有明确长度、有长度范围 先写^$
    */
    var str = ' we are web0713';
    var reg = /^w/;
    console.log(reg.exec(str));
    
    var reg = /\d$/;
    console.log(reg.exec(str));

量词

量词: 单位

a?

a? : 匹配是0个或者1个a

var str = 'awebweb123';
var reg = /b?/;
var reg = /a?/;
console.log(reg.exec(str));

a*

a* : 匹配是0个或者 连续 的多个a 尽可能多的去匹配

var str = '1234567a1234567';
var str = 'a1234567a1234567';
var reg = /\d*/;
console.log(reg.exec(str));

a+

a+: 匹配 连续 的多个a 尽可能多的去匹配 至少匹配1位

var str = 'aaa1234567a1234567';
var reg = /\d+/;
console.log(reg.exec(str));

a{m,n}

{m,n} : 匹配至少m次,最多n次 尽可能多的去匹配 m,n中间不能加空格

{m,} : 匹配至少m次 逗号不能省略

{m} : 匹配 m 次

var str = '12345aa678901234';
var reg = /\d{5,10}/;
console.log(reg.exec(str)); // 12345

var str = '12345678901234';
var reg = /\d{3,}/;
console.log(reg.exec(str)); // 12345678901234

var reg = /\d{6}/;
console.log(reg.exec(str));

或和

|或

a|b : 或 匹配a或者b

var str = 'web23webabc';
var reg = /web1|web2/;
console.log(reg.exec(str));

()和

() : 分组

每个分组的匹配结果都会在结果中展示, 数组第2项以后的就是分组的匹配结果

分组结果: $1 $2

var reg = /web(1|2)(2|3)/;
console.log(reg.exec(str));
console.log(RegExp.$1);
console.log(RegExp.$2);

var str = '13322221111';
// 将中间4位加密 133****1111
var reg = /^(1[3-9]\d)(\d{4})(\d{4})$/;
console.log(reg.exec(str));
console.log(str.replace(reg, '$1****$3'));


var str = 'hello RegExp'; // RegExp hello
var reg = /(hello) (RegExp)/;
console.log(str.replace(reg, '$2 $1'));

// 验证某几种情况选一个
// https://www.baidu.com/
// com cn net edu
var reg = /^(http|https):\/\/www\.\w+\.(com|cn|net|edu)$/; 
// 转义: 将vscode规定好的特殊的符号转成常规字符 用\
// .: 正则规定好的特殊的符号转成常规字符 用\
var str = 'https://www.baidu.com';
console.log(reg.exec(str));

前瞻后顾

(?:)

(?:a) : 非获取匹配

不获取分组中的小结果

var str = 'hello world';
var reg = /(hello) (world)/;
console.log(reg.exec(str));

var str = 'web1web2webawebb';
// var reg = /web(1|2)/;
var reg = /web(?:1|2)/;
console.log(reg.exec(str));

(?=)

(?=a) : 正向肯定预判

var str = '123@345';
var reg = /\d(?=@)/; // 匹配后面跟着@的数字
console.log(reg.exec(str));

(?!)

(?!a): 正向否定预判

var str = '123@345';
var reg = /\d(?!@)/; // 匹配后面不跟着@的数字
console.log(reg.exec(str));

DOM

DOM: Document Object Model 文档对象模型

DOM: 在页面生成的时候会形成一个树状结构 这个树状结构就叫做DOM树 当做节点

DOM树由节点组成

获取元素

获取元素: 静态获取 获取元素这一行代码执行的时候 页面中有多少就获取到多少 后续添加的得不到的 ie8+

document/父元素.querySelector('css选择器'); 获取到符合选择器的第一个元素

document/父元素.querySelectorAll('css选择器'); 获取到复合选择器的所有元素 集合

var li = document.querySelector('li');
console.log(li);
var lis = document.querySelectorAll('li');
console.log(lis); // NodeList(5) [li, li, li, li, li]

var lis1 = document.getElementsByTagName('li');
console.log(lis1); // HTMLCollection(5) [li, li, li, li, li]

var boxes = document.querySelectorAll('.box');
console.log(boxes);

var boxa = document.querySelectorAll('.box.a');
console.log(boxa);

var c2 = document.querySelectorAll('li:nth-child(2)');
console.log(c2);

获取子节点

标准浏览器: 节点.children

ie: 节点.childNodes 在标准浏览器中会获取到换行节点

console.log(ul.childNodes);
console.log(ul.childNodes[0]);

节点属性

\1. 节点名称: 节点.nodeName text comment LI UL P

\2. 节点类型: 节点.nodeType 0-12 1--标签 2--属性 3--文本 8--注释 9--document

\3. 节点内容: 节点.nodeValue 只有文本节点才有

// 节点属性:
// 1. 节点名称: 节点.nodeName text comment LI UL P
console.log(ul.childNodes[0].nodeName);
console.log(ul.childNodes[1].nodeName);
console.log(ul.childNodes[2].nodeName);

// 2. 节点类型: 节点.nodeType 0-12 1--标签 2--属性 3--文本 8--注释 9--document
console.log(ul.childNodes[0].nodeType);
console.log(ul.childNodes[1].nodeType);
console.log(ul.childNodes[2].nodeType);

// 3. 节点内容: 节点.nodeValue 只有文本节点才有
console.log(ul.childNodes[0].nodeValue);
console.log(ul.childNodes[1].nodeValue); // null
// 先获取标签节点的子节点(文本)再获取内容
// console.log(ul.childNodes[1].childNodes[0].nodeValue);

获取父节点

直接父节点: 当前子节点的上一级 节点.parentNode

定位父节点: 具有定位属性的父节点 没有定位属性的父元素 获取的就是body 节点.offsetParent

/* 
    获取父元素  
    先获取子元素
*/
var box = document.querySelector('.box');
console.log(box);

// 获取父节点: 
// 直接父节点: 当前子节点的上一级 节点.parentNode
// 定位父节点: 具有定位属性的父节点 没有定位属性的父元素 获取的就是body  节点.offsetParent
console.log(box.parentNode);
console.log(box.offsetParent);

获取其他节点

获取首节点

首节点: 节点.firstElementChild 节点.firstChild

标准: 标签 换行

ie: undefined 标签

var ul = document.querySelector('ul');
console.log(ul);
console.log(ul.firstElementChild, ul.firstChild);

兼容:

当一个是undefined 一个是有值 用||来连接 逻辑或短路 将有可能是undefined写在前面

console.log(ul.firstElementChild || ul.firstChild);

获取尾节点

获取尾节点:

节点.lastElementChild 节点.lastChild

标准: 标签 换行

ie: undefined 标签

兼容: 节点.lastElementChild || 节点.lastChild

console.log(ul.lastElementChild || ul.lastChild);

获取上一个兄弟

获取上一个兄弟节点:

节点.previouElementSibling 节点.previousSibling

标准: 标签 换行

ie: undefined 标签

兼容: 节点.previousElementSibling || 节点.previousSibling

var box = document.querySelector('.box');
console.log(box);
console.log(box.previousElementSibling || box.previousSibling);

获取下一个兄弟

获取下一个兄弟节点:

节点.nextElementSibling 节点.nextSibling

标准: 标签 换行

ie: undefined 标签

兼容: 节点.nextElementSibling || 节点.nextSibling

console.log(box.nextElementSibling || box.nextSibling);

删除节点

删除自身: 节点.remove(); ie8+

删除子节点: 节点.removeChild(子节点);

var ul = document.querySelector('ul');
var box = document.querySelector('.box');
console.log(box, ul);
// ul.removeChild(box);
box.remove();

创建节点

  1. 创建标签节点

  2. 创建文本节点

  3. 将文本节点追加到标签节点中

  4. 将li追加到ul中

// 1. 创建标签节点
// var 变量 = document.createElement('标签名');
var li = document.createElement('li');
console.log(li);

// 2. 创建文本节点
// var 变量 = document.createTextNode('内容');
var txt = document.createTextNode('12345');
console.log(txt);

// 3. 将文本节点追加到标签节点中
// 父节点.appendChild(子节点)
li.appendChild(txt);
console.log(li);

// 2-3步简化: 标签.innerHTML = 值;

// 4. 将li追加到ul中
ul.appendChild(li);

追加节点

  1. 追加到父元素末尾: 父元素.appendChild(子);

    // 先创建li标签
    var li = document.createElement('li');
    // 设置内容
    li.innerHTML = '123456';
    // 1. 追加到父元素末尾: 父元素.appendChild(子);
    var ul = document.querySelector('ul');
    ul.appendChild(li);
  2. 插入到某个节点之前: 父元素.insertBefore(new, ref)

    var li1 = document.createElement('li');
    li1.innerHTML = '新的003';
    
    // 获取box
    var box = document.querySelector('.box');
    
    ul.insertBefore(li1, box);
    
    // 插入到第一个
    var li2 = document.createElement('li');
    li2.innerHTML = '新的001';
    ul.insertBefore(li2, ul.children[0]);

替换节点

父元素.replaceChild(new, ref);

var li = document.createElement('li');
li.innerHTML = '新的li';

var ul = document.querySelector('ul');
ul.replaceChild(li, box);

克隆节点

节点.cloneNode(boolean);

boolean : true--克隆节点的内容 false--不克隆节点内容(默认)

var cli = box.cloneNode();
var cli = box.cloneNode(false);
var cli = box.cloneNode(true);
console.log(cli);
ul.appendChild(cli);

操作属性

操作属性:

获取: var 变量 = 元素.属性名; var 变量 = 元素[属性名];

设置: 元素.属性名 = 值; 元素[属性名] = 值;

.相当于 的 后面只能跟 字符串

局限: 上面两种 只能操作固有属性 写在标签上了的自定义属性获取不到

通过上面两种设置的属性 在页面上 看不到 但是可以正常获取和设置

var box = document.querySelector('.box');
console.log(box);
console.log(box.id, box.tag); // abc undefined
box.a = 1;
console.log(box.a);

获取属性

获取属性: 节点.getAttribute('属性名');

/* 
    1. 获取属性: 节点.getAttribute('属性名');
*/
console.log(box.getAttribute('tag'));
console.log(box.getAttribute('id'));

设置属性

设置属性: 节点.setAttribute('属性名', '属性值');

class不需要用className 直接class

box.setAttribute('class', 'a b c');

移除属性

移除属性: 节点.removeAttribute('属性名');

box.id = '';
box.removeAttribute('id');

注意

写属性名就能起作用的属性 在js中的值就是布尔 true false

不能使用set

一般推荐设置的时候使用 . []

var btn = document.querySelector('button');
var inps = document.querySelectorAll('input');
console.log(btn, inps);

inps[1].checked = true;
inps[1].setAttribute('checked', true);

快速获取表格元素

// 1. 获取table
var table = document.getElementsByTagName('table')[0];
console.log(table);
// 2. 快速获取
console.log(table.tHead); // 头
console.log(table.tFoot); // 脚
console.log(table.tBodies); // 表格体的集合 [tbody]
console.log(table.tBodies[0]); // 第一个表格体
console.log(table.rows); // 表格的行的集合 [tHead, tr, tr, tr]
console.log(table.tBodies[0].rows); // 第一个表格体中所有的行
// 表格是由行组成 行是由单元格
// 单元格必须通过行获取
console.log(table.tBodies[0].rows[0].cells); // 表格体中的第一个行的所有的单元格
console.log(table.cells); // undefined

表单元素

快速获取表单元素: 语法: form.name值

获取form表单的值: form.name值.value

<form action="">
    姓名: <input type="text" name="username" id="" value="张三" placeholder="123"><br>
    密码: <input type="password" name="password" id=""> <br>
    城市: <select name="city" id="">
        <option value="bj">北京</option>
        <option value="tj">天津</option>
        <option value="sh">上海</option>
    </select> <br>
    性别: <input type="radio" name="sex" id="" value="man" checked>男
        <input type="radio" name="sex" id="" value="woman">女 <br>
    爱好: 
        <input type="checkbox" name="hobby" id="">LOL
        <input type="checkbox" name="hobby" id="" checked>唱
        <input type="checkbox" name="hobby" id="">跳
        <input type="checkbox" name="hobby" id="" checked>rap
        <input type="checkbox" name="hobby" id="">打篮球

</form>

<script>
    /* 
        1. 快速获取表单元素
    */
    var form = document.querySelector('form');
    console.log(form);

    // 每个表单元素需要有name值
    // 语法: form.name值
    console.log(form.username);
    // 获取form表单的值: form.name值.value
    console.log(form.username.value);

    console.log(form.password);
    console.log(form.city);
    console.log(form.sex);
    console.log(form.hobby);
</script>

form表单事件:

\1. 提交 onsubmit

return true; 当前表单可以提交 默认

return false; 当前表单不提交

\2. 重置 onreset

return true; 当前表单可以重置 默认

return false; 当前表单不重置

var form = document.querySelector('form');
form.onsubmit = function () {
    console.log(1);
    // return false;
    // return true;
    // 如果用户名是123 密码是123 禁止提交 否则 允许提交
    if(form.user.value == '123' && form.pass.value == '123'){
        console.log('禁止提交');
        return false;
    } else {
        return true;
    }
};


form.onreset = function () {
    console.log('重置');
    // return true;
    // return false;
};

form中的表单元素事件:

\1. 聚焦: onfocus: 当光标定位到输入框的时候 触发的事件

\2. 失焦: onblur: 当光标在输入框移出 触发的事件

\3. 表单失去焦点且内容改变事件: onchange

\4. 边输入边改变: oninput(标准) onpropertychange(ie)

form.user.onfocus = function () {
    this.style.border = '10px solid red';
};

form.user.onblur = function () {
    this.style.border = '1px solid black';
};

form.pass.onchange = function () {
    this.style.background = 'red';
};

form.pass.oninput = form.onpropertychange = function () {
    console.log(this.value);
};

form.user.oninput = function () {
    console.log(this.value);
}

方法:

form表单: reset() submit()

表单中的元素: blur() focus() select();

// form.user.select();
form.pass.focus();

setTimeout(function () {
    form.pass.blur();
}, 3000);


var divs = document.getElementsByTagName('div');
divs[0].onclick = function () {
    form.reset();
};

divs[1].onclick = function () {
    form.submit();
};

BOM

BOM: Browser Object Model 浏览器对象模型

window 最大对象

所有全局中声明的变量和方法都属于window

document也是存在于window中

其他: location localstorage cookie document history 提示框 frames

对话框

\1. 警告框

\2. 带有确认取消按钮的对话框 true---确认 false--取消

\3. 带有输入框的对话框 确认--输入框的内容 取消--null

// 1. 警告框
// alert('是否同意此协议');

// 2. 带有确认取消按钮的对话框  true---确认 false--取消
// var c = confirm('是否选择购买99999的套餐');
// console.log(c);

// 3. 带有输入框的对话框 确认--输入框的内容 取消--null
// var res = prompt('请输入要购买的金额', '99');
// console.log(res);

open与close

open

open(打开地址, 打开的方式, 特殊值);

打开的方式: _blank: 新的页面 _self: 自身

特殊值: 页面样式 打开方式必须是_blank 属性名=属性值,属性名=属性值

具有返回值: 将新页面的window对象返回回来

setTimeout(function () {
    // 打开百度
    // open('https://www.baidu.com', '_blank');
    // open('https://www.baidu.com', '_self');
    var w = open('https://www.baidu.com', '_blank', 'width=100px, height=100px');
    console.log(w);
    setTimeout(function () {
        w.close();
    }, 2000);
}, 3000);

close

close: window对象.close();

close写在页面结构html中 window不可省略

setTimeout(function () {
  w.close();
}, 2000);

location

location既是BOM的对象 也是window下的一个对象

整个BOM中最有用的对象的之一 相关当前页面的网址相关信息

// http://www.ujiuye.com/zt/webqzgcs/
// http://xue.ujiuye.com/list/?title=web
console.log(location);
console.log(location.href); // 完整地址
console.log(location.protocol); // 协议 file http https
console.log(location.host); // 服务器名称+端口号 ---> 映射地址
console.log(location.hostname); // 服务器名称
console.log(location.port); // 端口号
console.log(location.pathname); // 地址
console.log(location.hash); // 哈希值 散列 #+后面
console.log(location.search); // 搜索内容 ?a=1&b=1

// setTimeout(function () {
//     location.reload(); // 刷新页面
// }, 3000)

// 跳转到其他
// location.href = 'https://www.baidu.com';
window.location.href = 'https://www.baidu.com';

history

history.back(); 回退到上一个页面

history.forward(); 前进到下一个页面

history.go(数字); 跳转到某个页面

正数: 前进到后面第几个页面

负数: 回退前面第几个页面

0: 刷新

01: 
<button οnclick="history.go(0);">刷新</button>
<button οnclick="history.go(2);">前进到03</button>
<button οnclick="history.forward();">前进到下一个页面</button>

02:
<a href="./08 history03.html">history03</a>
<button οnclick="history.back();">回退到01</button>

03:
<button οnclick="history.go(-2);">回退到01</button>

事件

onload

// 1. 等待页面加载: 等页面结构及资源加载完成后 在执行function
// 当js写在页面结构之前
// 外链的js文件中
window.onload = function () {
    var div = document.getElementsByTagName('div')[0];
    console.log(div); 
};

onscroll

// 2. 页面滚动
window.onscroll = function () {
    console.log('滚滚滚');
};

onresize

// 3. 窗口大小发生改变
window.onresize = function () {
  console.log('变变变');
};

client

client: 可视宽高

clientWidth/clientHeight: 元素的可视宽/可视高 content+padding

clientLeft/clientTop: left/top的边框的宽度

var div = document.getElementsByTagName('div')[0];
console.log(div);
console.log(div.clientWidth, div.clientHeight); // 200+20+40 300+10+30
console.log(div.clientTop, div.clientLeft); // 3 1

获取浏览器的可视宽高:

document.documentElement.clientHeight/clientWidth

console.log(document.documentElement.clientHeight, document.documentElement.clientWidth);

offset

offset: 占位宽高

offsetWidth/offsetHeight: 元素的占位宽/元素的占位高 content+padding+border

offsetLeft/offsetTop: 元素距离具有定位属性的父元素的偏移的距离, 如果没有定位父元素 距离body的偏移距离

left: 左 top: 上

console.log(div.offsetWidth, div.offsetHeight); // 200+20+40+1+5=266 300+10+30+3+2=345
console.log(div.offsetLeft, div.offsetTop); // 50 0  -- 50 20

scroll

scroll: 滚动距离

scrollWidth/scrollHeight: 元素内容所占的实际的宽高

scrollLeft/scrollTop: 元素的滚动的距离

left: 水平 top: 垂直

console.log(div.scrollWidth, div.scrollHeight);
div.onscroll = function () {
    console.log(div.scrollTop, div.scrollLeft);
};

页面的滚动距离:

document.documentElement.scrollLeft/scrollTop

window.onscroll = function () {
  	console.log(document.documentElement.scrollTop, document.documentElement.scrollLeft);
};

懒加载

\1. 布局 元素必须有宽高

\2. 将图片地址存储在img的自定义属性(_src)上

\3. 如果img进入页面 将自定义属性的地址赋值给 src 属性

offsetTop == scrollTop + clientHeight 刚刚好进入页面

offsetTop < scrollTop + clientHeight 图片进入页面且超出页面的过程

offsetTop <= scrollTop + clientHeight

auto();

// 当窗口大小发生改变的时候 
window.onresize = window.onscroll = function () {
    auto();
};

// 事件可以连等
function auto() {
    // 5. 获取滚动距离
    var t = document.documentElement.scrollTop;
    var cw = document.documentElement.clientHeight;
    // console.log(cw);
    // console.log(t);
    // 3. 判断每一张
    for (var i = 0; i < imgs.length; i++) {
        // 4. 获取每个img距离页面顶部的距离
        // console.log(imgs[i].offsetTop);
        if (imgs[i].offsetTop <= t + cw) {
            // 6. 将img的_src的值赋值给src
            // console.log(imgs[i].getAttribute('_src'));
            imgs[i].src = imgs[i].getAttribute('_src');
        }
    }
}

事件对象

事件对象: 当页面中触发事件的时候 浏览器会将当前相关事件的信息都存储在一个对象中, 就是事件对象

ie/chrome/高ff: window.event

低ff: 以事件处理函数的第一个形参

事件对象: 鼠标、触发源、页面、事件...

var div = document.querySelector('div');
console.log(div);

div.onclick = function () {
    console.log(window.event);
    console.log(event.type); // 事件类型
    console.log(event.target, event.srcElement); // 事件的触发源
    console.log(event.target || event.srcElement); // 事件的触发源
    console.log(event.clientX, event.clientY); // 鼠标相对于屏幕的可视区域的左上角的位置
    console.log(event.pageX, event.pageY); // 鼠标相对于页面body左上角的距离
    console.log(event.screenX,event.screenY); // 鼠标相对于电脑屏幕的左上角的距离
};

事件绑定

元素.事件 = function(){} 只能给同一个元素的同一个事件添加一个处理函数 如果添加多个后面的就会覆盖前面的

div.onclick = function () {
   console.log(1);
}
div.onclick = function () {
   console.log(5);
}

语法

ie: 元素.attachEvent(on+事件类型, 事件处理函数)

标准: 元素.addEventListener(事件类型, 事件处理函数, 是否捕获)

// ie: 对象不支持“addEventListener”属性或方法
// 标准: div.attachEvent is not a function div.attachEvent不是一个函数
console.log(div.addEventListener); // ie: undefined 标准: 函数
console.log(div.attachEvent); // ie: 函数  标准: undefined

// div.addEventListener('click', function () {
//     console.log(2);
// }, false);

// div.attachEvent('onclick', function () {
//     console.log(3);
// });

兼容

if (div.attachEvent) {
    div.attachEvent('onclick', function () {
        console.log(3);
    });
} else {
    div.addEventListener('click', function () {
        console.log(2);
    }, false);

}

封装

bind(div, 'click', a);
bind(div, 'click', b);

function bind(ele, type, fn) {
    // ele: 元素
    // type: 事件类型
    // fn: 函数
    if (ele.attachEvent) {
        ele.attachEvent('on' + type, fn);
    } else {
        ele.addEventListener(type, fn, false);
    }
}

事件解绑

元素.事件 = 事件处理函数 元素.事件 = null;

元素.addEventListener 元素.removeEventListener(事件类型, 函数名, 是否捕获);

元素.attachEvent 元素.detachEvent(on+事件类型, 函数名);

unbind(div, 'click', a);

function unbind(ele, type, fn) {
    // ele: 元素
    // type: 事件类型
    // fn: 函数名
    if (ele.removeEventListener) {
        ele.removeEventListener(type, fn, false);
    } else {
        ele.detachEvent('on' + type, fn);
    }
}

函数高级

回调函数

回调函数: 等一个动作执行完成后 还要执行的动作

// 先定义一个后续要使用的函数
function a() {
    console.log(1);
}

// 等待点击页面之后 执行a函数中的代码
document.onclick = function () {
    console.log('点击');
    a();
}

function b() {
    console.log('成功');
}
// 获取数据
function getData(fn) { 

    // 执行自己代码的函数
    fn();
}

getData(b);
getData(a);

匿名函数

匿名: 没有名字的函数

匿名函数直接写会报错 将匿名函数转成表达式 外面加上()

  1. 匿名函数自执行:

  2. 匿名函数可以传参: 形参写在function后面的() 实参写在调用()

  3. 匿名函数可以接受返回值:

(function () {
    console.log('匿名函数');
});
// IIFE: 立即执行函数 Immediately Invoke Function Expression
// 注意: 必须加;
// 匿名函数自执行:
(function () {
    console.log('匿名函数自执行');
})();

(function () {
    console.log('匿名函数自执行');
}());

// 匿名函数可以传参: 形参写在function后面的()  实参写在调用()
(function (a, b) {
    console.log(a, b); // 10, 20
    console.log(arguments);
})(10, 20);

// 匿名函数可以接受返回值:
var res = (function () {
    return 10 + 20;
})();
console.log(res);

闭包

闭包: 可以访问其他函数内部变量的函数(函数里面套函数, 内部函数访问外部函数的变量)

优点: 扩大了内部变量的作用范围

缺点: 数据量大量缓存 导致内存浪费

unction outer() {
    var b = 10;
    function inner() {
        b++;
        console.log(b);
    }

    // 设置返回值
    return inner;
};

var res = outer(); // res == inner 
res(); // 11
res(); // 12
res(); // 13

F12 开控制台 ---> Sources

----> 点到自己的文件

设置断点:

\1. 外层函数outer的第一行代码

\2. 内层函数inner的带一行代码

查看Scope:

local: 当前局部作用域

global: 全局作用域

Closure: 闭包

// 外层函数每调用一次就形成一个新的闭包
var r = outer();
r(); // 11

// 闭包一直存在与内存中 造成内存浪费(垃圾回收)
r = null;

闭包应用

解决全局变量i的影响

原因: for循环中的 i 是一个全局变量 由于点击函数没有局部变量

解决: 给循环的事件的时候 添加局部变量

for(var j = 0; j < btns.length; j++){
    (function (s) {
        console.log(s);
        btns[s].onclick = function () {
            console.log(s);
        }
    })(j);
}

模拟私有变量

function student(name) {
    var user = name; // 档案入库
    // console.log(user);

    // 查看函数
    function see() {
        console.log(user);
    }

    // 修改函数
    function edit() {
        user = '迪丽热巴';
    }

    // 提供接口 设置返回值
    return {
        'see': function () {
            console.log(user);
        },
        'edit': edit
    };
}
var res = student('张三');
console.log(res); // {see: ƒ, edit: ƒ}
// 查看名字
res.see();
res.edit();

res.see();

递归

递归: 函数里面调用自己 必须要有函数结束的条件

报错: Maximum call stack size exceeded 栈溢出

解决: 加上函数结束的条件

阶乘

function jc(n) {
    if(n == 1) {
        return 1;
    }
    return n * jc(n-1);
}
var s = jc(6);
console.log(s);

console.log(jc(1000));

斐波那契数列

月 兔子

1 1

2 1

3 1 1

4 1 1 1

5 1 1 1 1 1

6 1 1 1 1 1 1 1 1

1月 1

2月 1

3月 2 = 1+1

4月 3 = 2+1

5月 5 = 3+2

6月 8 = 5+3

// 计算第6个月有多少对兔子
function fib(n) {
    /* 
        第n个月的兔子 = 第n-1个月 + 第n-2个月
        6 = 5 + 4
          = (4 + 3) + 4
          = (3 + 2 + 3) + 3 + 2
          = 2 + 1 + 2 + 2 + 1 + 2 + 1 + 2
          = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1

    */
    // 判断条件
    if(n == 1 || n == 2) return 1;
    return fib(n-1) + fib(n-2);
}
console.log(fib(6));

// 不要算20以上
console.log(fib(21));

快速排序/二分法

\1. 找到中间下标

\2. 找到中间下标对应的值

\3. 原数组中删除中间值

\4. 声明2个空数组

\5. 判断原数组剩下的每一个项和中间值得大小, 比中间值小的 放在left

比中间值大的放在 right

\6. 封装代码

\7. 设置结束条件

\8. 设置整个函数的返回值

function qs(array) {
    // 7. 设置结束条件
    if(array.length <= 1){
        return array;
    }
    // 1. 找下标
    var ind = Math.floor(array.length / 2);
    // 2. 存值
    var val = array[ind];
    // console.log(val);
    // 3. 删除中间值
    array.splice(ind, 1);
    // console.log(array);
    // 4. 声明2个空数组
    var left = [],
        right = [];
    // 5. 每一个
    for (var i = 0; i < array.length; i++) {
        if (array[i] < val) {
            left.push(array[i]);
        } else {
            right.push(array[i]);
        }
    }
    // console.log(left, right);
    // 6. 递归排序
    // 8. 设置整个函数的返回值
    return qs(left).concat(val, qs(right));
}

var a = qs(arr);
console.log(a);

防抖

防抖: 只要用户触发事件, 清除定时器, 重新开始计时

避免造成全局污染 选择使用闭包实现效果

// 当鼠标滑动的时候 对n进行累加 div的内容显示n
var n = 0;
// 事件三部曲
// 获取元素
var div = document.getElementsByTagName('div')[0];
// 加事件
div.onmousemove = debounce(100, a);
function a() {
    n++;
    // div的内容显示n
    div.innerHTML = n;
}

// 防抖: 只要用户触发事件, 清除定时器, 重新开始计时
// 避免造成全局污染 选择使用闭包实现效果
function debounce(date, fn) {
    // 声明一个变量 用来接收定时器的唯一标识
    var timer = null;
    // 内部函数表示事件处理函数
    function inner() {
        // 清除定时器
        clearTimeout(timer);
        // 重新开始计时
        timer = setTimeout(fn, date);
    };
    // 设置返回值
    return inner;
}

节流

节流: 让用户在一段时间之内 只能执行一次

判断当前的状态tag tag是true 允许用户执行 tag是false不让执行

到时间之后重新变成可执行状态

// 当鼠标滑动的时候 对n进行累加 div的内容显示n
var n = 0;
// 事件三部曲
// 获取元素
var div = document.getElementsByTagName('div')[0];
// 加事件
div.onmousemove = throttle(500, a);
function a() {
    n++;
    // div的内容显示n
    div.innerHTML = n;
}

// 节流: 让用户在一段时间之内 只能执行一次
// 判断当前的状态tag tag是true 允许用户执行 tag是false不让执行
// 到时间之后重新变成可执行状态
function throttle(date, fn) {
    // date: 间隔时间
    // fn: 执行的函数
    // 声明一个变量 接收唯一标识
    var timer = null;
    // 假设一个可以执行的状态
    var tag = true;
    // 内部代码 表示 用户的事件处理函数
    function inner() {
        // 判断函数是否可以执行
        if(tag){
            timer = setTimeout(function () {
                fn();
                // 当定时器函数执行的时候 表示用户的间隔时间已经到了
                // 将tag = true
                tag = true;
                // 定时器执行后 清除定时器
                clearTimeout(timer);
            }, date);

            // 更新状态
            tag = false;
        }
    }
    // 设置返回值
    return inner;
}

call与apply

作用: 改变this的指向

区别: 传参的时候不同

call和apply都是用来改变函数中this的指向

call: 函数.call(this的新指向, 值1, 值2, ... 值n);

apply: 函数.apply(this的新指向, [值1, 值2, ... 值n]);

call

function a() {
  console.log(this);
}
a(); // window

// 改变this的指向
a.call(1);
a.call(document);
a.call([]);

function b(x, y) {
  console.log(this, x, y);
}
b(10, 20); // window 10 20
b.call(1, 'a', 'b'); // {1} 'a' 'b'

// 用来判断数据的类型
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof null); // object

// 使用对象的toString方法可以判断数据类型
// prototype: 原型对象
console.log(Object.prototype.toString());
console.log(Object.prototype.toString.call(123)); // [object Number]
console.log(Object.prototype.toString.call('qwer')); // [object String]
console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call({})); // [object Object]
console.log(Object.prototype.toString.call([]).slice(8, -1)); // Array
console.log(Object.prototype.toString.call({}).slice(8, -1)); // Object

// 复杂-->对象
var obj = {
    name: '迪丽热巴',
    say: function () {
        console.log(this);
        console.log(this.name);
    }
}
obj.say(); // obj  {name: "迪丽热巴", say: ƒ}  迪丽热巴
var o1 = {
    name: '杨洋'
};
obj.say.call(o1); // o1  {name: "杨洋"} 杨洋

apply

// apply: 找到数组的最大值
var arr = [32, 54, 13, 54, 233, 54, 23, 457, 99, 5];
console.log(Math.max(3, 4, 5, 6));
// this的新指向写任何东西
console.log(Math.max.apply(1, [3, 4, 5, 6]));
console.log(Math.max.apply(1, arr));

面向对象创建

字面量

语法:

var 变量 = {

属性名: 属性值,

方法名: 方法

}

优点: 直观

缺点: 只适用于创建单个对象

var obj = {
    name: '迪丽热巴',
    age: 32,
    work: function () {
        console.log('演戏、唱歌、跳舞');
    }
};
console.log(obj);

console.log(obj.name);
console.log(obj.age);
obj.work();

new关键字创建

var 变量 = new Object();

变量.属性名 = 属性值;

变量.方法名 = 函数;

缺点: 代码冗余

var obj = new Object();
obj.name = '迪丽热巴';
obj.age = 32;
obj.work = function () {
    console.log('唱歌跳舞演戏');
};
console.log(obj);

工厂模式

工厂模式问题: 识别不清

对象 instanceof 函数名 判断对象是否由函数创建 false-不是 true--是

function createObj(name, age) {
    // 1. 创建对象
    var obj = new Object();

    // 2. 添加属性和方法
    obj.name = name;
    obj.age = age;

    obj.work = function () { 
        console.log('唱歌跳舞演戏');
    }

    // 3. 出厂 设置返回值
    return obj;
};
var dlrb = createObj('迪丽热巴', 32);
var yy = createObj('杨洋', 33);
console.log(dlrb, yy);


// 问题: 识别不清
// 对象 instanceof 函数名   判断对象是否由函数创建  false-不是  true--是
console.log(dlrb instanceof createObj);

构造函数

构造函数: 就是个函数 用来构造对象

\1. 函数名首字母大写(约定)

\2. 所有的方法和属性 加给 this

\3. 调用的时候必须用new调用 否则和普通函数一样

\4. 不需要创建和设置返回值

缺点: 内存浪费

new的时候发生了什么:

\1. 创建一个空对象

\2. 将this指向空对象

\3. 将函数的prototype赋值给对象的__proto__

\4. 指向函数中的代码 添加属性和方法

\5. 隐式返回
function CreateObj(name, age) {
    console.log(this);
    this.name = name;
    this.age = age;
    this.work = function () {
        console.log('演戏唱歌跳舞');
    }
}

var obj = new CreateObj('迪丽热巴', 32);
var yy = new CreateObj('杨洋', 32);
console.log(obj, yy);

// 优点: 解决了识别不清
console.log(obj instanceof CreateObj);

obj.work();
yy.work();

// 判断是否是同一个函数 ==
console.log(obj.work == yy.work); // false

原型

原型对象 prototype: 在每一个函数被创建的时候 用来存储共享的方法和属性的对象

原型属性 proto: 在每一个实例对象被创建的时候 用来存储共享的方法和属性的对象

共享的方法和属性都加给原型对象prototype, 后期通过构造函数创建的实例化对象都可以使用共享的方法和属性

console.log(String);
console.log(String.prototype);

var str = new String(123);
console.log(str);
console.log(str.__proto__);

console.log(String.prototype == str.__proto__); // true

原型创建

缺点: 1. 不能传参

  1. 一改全改

function CreateObj() {  }
// 给原型对象添加属性和方法
CreateObj.prototype.name = '张三';
CreateObj.prototype.age = 33;
CreateObj.prototype.money = ['基金', '股票', '影视'];
CreateObj.prototype.work = function () {
    console.log('吃饭睡觉打豆豆');
};

// 实例化对象
var obj = new CreateObj();
console.log(obj);
console.log(obj.name);

var obj1 = new CreateObj();
console.log(obj1);

console.log(obj.work == obj1.work); // true

obj1.name = '迪丽热巴';

console.log(obj.name, obj1.name);
console.log(obj.money, obj1.money); // ["基金", "股票", "影视"]

// 一改全改
obj.money.push('定期');
console.log(obj.money, obj1.money);

原型链: 当一个对象被创建的时候所自带的链表关系, 可以实现继承和查找, 从自身开始查找, 有就直接使用, 没有往上一级原型上去查找.

混合创建

混合创建: 构造函数(可变的) + 原型创建(不变的 共享的)

// 构造函数
function CreateObj(name, age) {
    this.name = name;
    this.age = age;
    this.money = ['基金', '股票', '影视'];
};

// 原型创建
CreateObj.prototype.work = function () {
    console.log('挣钱');
};

// 实例化对象
var obj = new CreateObj('迪丽热巴', 32);
var obj1 = new CreateObj('杨洋', 33);
console.log(obj, obj1);
console.log(obj.name, obj1.name);


console.log(obj.money, obj1.money);
obj.money.push('定期');
console.log(obj.money, obj1.money);


console.log(obj.work == obj1.work); // true

面向对象继承

特点: 封装 继承 多态(date + null '123'+null 123null 123+null=123)

继承: 子承父

原型链继承

原型链: 当一个对象被创建的时候 所自带的链表关系 实现继承和查找

继承: 子类构造函数的原型对象 = 父类构造函数的实例化对象;

// 父类构造函数
function Father(name, age) {
    this.name = name;
    this.age = age;
    this.arr = ['理财', '股票', '期权'];
};
Father.prototype.money = function () {
    console.log('月入100w');
};

// 子类构造函数
function Son() { }

// 继承: 子类构造函数的原型对象 = 父类构造函数的实例化对象;
Son.prototype = new Father('张恒', 38);


// 子类构造函数:实例化对象
var obj = new Son();
console.log(obj);

console.log(obj.name);
console.log(obj.toString);

查找过程

先找自身, 自身没有就往上一级找,

找到自己的原型属性(父类构造函数的实例化对象),

找不到在找父类构造函数的原型属性,

如果没有,找object, 如果没有返回undefined, 有就直接返回;

问题:

\1. 不能传参

\2. 一改全改

var obj1 = new Son();
console.log(obj.arr, obj1.arr);

obj.arr.push('定期');
console.log(obj.arr, obj1.arr);

对象冒充继承

对象冒充继承: 将父类构造函数的this指向变成子类构造函数的this

问题: 不能继承父类构造函数的原型对象上的方法和属性

核心: 在子类构造函数中调用父类构造函数 改变this

// 父类构造函数
function Father(name, age) {
    this.name = name;
    this.age = age;
    this.arr = ['基金', '股票'];
}
Father.prototype.money = function () {
    console.log('月入百万');
};

// 子类构造函数
function Son(name, age) {
    // 在子类构造函数中调用父类构造函数 改变this
    Father.call(this, name, age);
    this.play = function () {
        console.log('玩王者荣耀');
    };
};
Son.prototype.work = function () {
    console.log('写作业');
};


// 实例化
var obj = new Son('张恒', 38);
var obj1 = new Son('郑爽', 36);
console.log(obj, obj1);
console.log(obj.toString);
console.log(obj.money); // undefined

console.log(obj.arr, obj1.arr);
obj.arr.push('定期');
console.log(obj.arr, obj1.arr);

组合继承

组合继承: 对象冒充继承 + 原型链继承

问题:

\1. 父类构造函数的属性和方法会存储2次

\2. 子类构造函数的原型对象上的方法和属性找不到

// 父类构造函数
function Father(name, age) {
    this.name = name;
    this.age = age;
    this.arr = ['基金', '股票'];
}
Father.prototype.money = function () {
    console.log('月入百万');
};

// 子类构造函数
function Son(name, age) {
    // 在子类构造函数中调用父类构造函数 改变this
    Father.call(this, name, age);
    this.play = function () {
        console.log('玩王者荣耀');
    };
};
Son.prototype.work = function () {
    console.log('写作业');
};

// 原型链继承: 子类构造函数的原型对象 = 父类构造函数的实例化对象
Son.prototype = new Father();


// 实例化
var obj = new Son('小凯', 23);
console.log(obj);
console.log(obj.toString);

寄生式组合继承

寄生式组合继承: 对象冒充继承 + 原型链继承

\1. 在子类构造函数中调用父类构造函数 改变this

\2. 原型链继承: 子类构造函数的原型对象 = 利用父类构造函数的原型对象创建的实例化对象

\3. 手动修改子类构造函数的原型对象指向的构造函数

// 寄生式组合继承: 对象冒充继承 + 原型链继承
// 父类构造函数
function Father(name, age) {
    this.name = name;
    this.age = age;
    this.arr = ['基金', '股票'];
}
Father.prototype.money = function () {
    console.log('月入百万');
};

// 子类构造函数
function Son(name, age) {
    // 1. 在子类构造函数中调用父类构造函数 改变this
    Father.call(this, name, age);
    this.play = function () {
        console.log('玩王者荣耀');
    };
};

// 2. 原型链继承: 子类构造函数的原型对象 = 利用父类构造函数的原型对象创建的实例化对象
// Object.create(原型对象): 使用原型对象创建一个对象
Son.prototype = Object.create(Father.prototype);
// 3. 手动修改子类构造函数的原型对象指向的构造函数
Son.prototype.constructor = Son;



// 子类构造函数的原型对象
Son.prototype.work = function () {
    console.log('写作业');
};

// 实例化
var obj = new Son('小凯', 23);
console.log(obj);

console.log(obj.toString);

Less

Less是一个CSS预处理器, 用js实现的可以在live

使用变量 利于修改网站风格

实现嵌套 代码编写更简洁明了

查找:

less: Less 快速入门 | Less.js 中文文档 - Less 中文网

使用:

插件: easy Less

写完less文件后 按ctrl+s保存后 就会生成css文件

\1. 创建后缀为.less的文件 写less

\2. 在html引入.css后缀的文件

配置:

设置--->扩展设置-->在setting.json中设置

"out": "../css/",

out: 产出css的位置

变量

@变量名: 设置的值;

@color: blue;
/* 这是边框 */
@bd: 10px dotted pink;

div{
    color: @color;
    border: @bd;
}

注释:

/* 块注释 */ 在css中会显示

// 单行注释 在css中不显示

// @color: red;
@color: blue;
/* 这是边框 */
@bd: 10px dotted pink;

作用域

@color: yellow;

div{
    @color: blue;
    color: @color;
}

混入Mixins

在一个选择器中 使用其他选择器的所有样式

选择器a{

选择器b();

}

.a{
    width: 200px;
    height: 200px;
    background: red;
}

.b{
    // 混入
    .a();
    color: yellow;
    border: 1px solid #000;
}

嵌套

父{

子{}

&: 表示当前这级选择器

}

*{
    margin: 0;
    padding: 0;
    list-style: none;
}

// 轮播图
#wrap{
    width: 1180px;
    height: 350px;
    margin: 40px auto;
    position: relative;

    ul{
        position: relative;
        width: 100%;
        height: 100%;
        li{
            position: absolute;
            top: 0;
            left: 0;
            display: none;
            width: 100%;
            height: 100%;
            img{
                width: 100%;
                height: 100%;
            }
            &.active{
                display: block;
            }
            &:hover{
                // border: 1px solid #000;
                animation: auto 2s linear infinite;
            }
        }
        &::after{
            content: '';
            clear: both;
            display: block;
        }
        @keyframes auto {
            0%{
                transform: rotate(0deg);
            }
            100%{
                transform: rotate(360deg);
            }
        }

        @media screen and (min-width: 1200px) {
            width: 1180px;
        }
        @media screen and (min-width: 920px) and (max-width: 1199px){
            width: 800px;
        }
        @media screen and (min-width: 768px) and (max-width: 919px) {
            width: 760px;
        }
    }
}

转义

转义(Escaping)允许你使用任意字符串作为属性或变量值。

当需要一串字符串原样输出 , 常用于样式过长且字符过多的时候

@变量: ~"字符";

@变量: ~'字符';

简化:

@变量: (字符);

@color: red;
@aw12: ~"max-width: 1200px";
@iw12: ~'min-width:1200px';
// 报错不影响页面的css的生成和渲染
@aw92: (min-width: 920px);
div{
    color: @color;
    width: 1200px;
    height: 400px;
    background: pink;
    @media screen and (@iw12) {
        width: 1200px;
    }
    @media screen and @aw92 and (@aw12) {
        width: 990px;
    }
}

计算

计算: 倍数的计算

对任何数字、颜色或变量进行运算

如果单位之间可以转换会尽可能的转换,不能的就忽略单位

@w: 1000px;
@h: 500px;
@r: 50;
div.a{
    margin: 0;
    padding: 0;
    width: 1000px;
    height: 500px;
    .left{
        width: @w - 300 + 100 + 10pt;
        height: @h - 200 + 10rem + 10pt;
        background: rgb(@r * 4, @r * 10, 0);
    }
}

映射

映射: 用于有一系列相关的数据的时候 颜色

声明:

#变量名(){

属性名: 属性值;

}

使用: #变量名[属性名]

#color(){
    default: #000;
    high: blue;
    light: skyblue;
}

div:nth-child(1){
    color: #color[default];
}
div:nth-child(2){
    color: #color[high];
}
div:nth-child(3){
    color: #color[light];
}

导入

在less文件中要引入其他的less文件或者css文件

// 引入less文件的时候 后缀.less可以省略
@import "13";

// 引入css文件的时候 后缀.css不可以省略
@import "../css/14.css";

项目流程

部门及职责

产品: 接收到需求 出需求文档 原型图

UI: 出设计图

web: 精准还原 渲染数据 实现功能

后台: 接口

测试: 测试场景

项目规范:

\1. 规范目的

\2. 规范部分

2.1 文件命名规范: 各版块分文件夹 英特殊符文+号_ 对应文件命名: 首页的html\css\js: index.html\css\js

2.2 样式规范 提高选择器的优先级 父子 后代 交叉 属性 内容

主题风格 颜色、使用变量

2.3 页面结构 语义化 起名 banner onlinelist poster 从大块划小块

2.4 js: 引入位置: body的结束标签

2.4.1 引入数据

2.4.2 公用js库

2.4.3 引入小的板块

2.4.4 自己的js window.onload---一个页面只能出现一个

事件绑定

数据渲染

\1. 先写板块注释

\2. 获取到数据

\3. 获取要渲染的父元素 ul

\4. 页面原有的子元素注释掉

\5. 生成页面片段

本地缓存

所需要的数据存储到电脑中

所存储的所有数据全部都是字符串

记住密码、记住登录状态

// localStorage: 对象
console.log(localStorage);

// 存储数据
// 对象.属性名 = '属性值';
localStorage.name = '张三四';

// localStorage.setItem('属性名', '属性值');
localStorage.setItem('name1', '李四三');


// 获取数据
// 对象.属性名
console.log(localStorage.name);

// localStorage.getItem('属性名');
console.log(localStorage.getItem('name1'));

// 删除数据
// localStorage.removeItem('属性名')
localStorage.removeItem('name');

// 清空本地缓存
// localStorage.clear();

console.log(localStorage);

video

src: 视频播放的地址

width: 宽

height: 高

controls: 控制器

poster: 海报

muted: 静音

autoplay: 自动播放 只有静音状态下

currentSrc: 当前播放的地址

volume: 音量: 0-1

duration: 时长 在视频可以播放之后才能拿到 NaN 单位: s 秒

playbackRate: 当前视频的播放速度 默认1 可设置: >0 改变当前视频的播放速度

defaultPlaybackRate: 默认视频的播放速度 默认1 可设置: >0 改变后续视频的播放速度

paused: 暂停状态 true--暂停 false--播放

ended: 结束状态 true--结束 false--未结束

currentTime: 当前的播放时间的位置

loop: 循环播放

获取属性

// 获取video
var video = document.querySelector('video');
console.log(video);


// video的属性均可操作
// 获取: 直接写属性名就能起作用的在js中的值就是true和false
console.log(video.src);
console.log(video.currentSrc); // 当前播放的地址
console.log(video.width, video.height);
console.log(video.controls); // 是否有控制器
console.log(video.poster); // 海报地址
console.log(video.muted);
console.log(video.autoplay);
console.log(video.volume); // 音量: 0-1
console.log(video.duration); // 时长 在视频可以播放之后才能拿到 NaN 单位: s 秒
console.log(video.playbackRate); // 当前视频的播放速度 默认1 可设置: >0  改变当前视频的播放速度
console.log(video.defaultPlaybackRate); // 默认视频的播放速度 默认1 可设置: >0 改变后续视频的播放速度
console.log(video.paused); // 暂停状态 true--暂停 false--播放
console.log(video.ended); // 结束状态 true--结束 false--未结束
console.log(video.currentTime); // 当前的播放时间的位置  
console.log(video.loop); // 循环播放

设置属性

// video.loop = true;
video.poster = './小U课堂/img/index/tbanner2.png';
video.autoplay = true;

var btns = document.querySelectorAll('button');
btns[0].onclick = function () {
    video.src = './video/岳小康、计应3班2019020336.mp4';
};

btns[1].onclick = function () {
    video.width = 1000;
    video.height = 700;
};

btns[2].onclick = function () {
    video.controls = !video.controls;
    console.log(video.controls);
};

btns[3].onclick = function () {
    video.muted = !video.muted;
    console.log(video.muted);
};

video.volume = 1;
btns[4].onclick = function () {
    video.volume += 0.1;
    console.log(video.volume);
};

btns[5].onclick = function () {
    // video.playbackRate = 0.1;            
    video.defaultPlaybackRate = 0.1;
    console.log(video.playbackRate, video.playbackRate);
};
btns[6].onclick = function () {
    // video.playbackRate = 1;            
    video.defaultPlaybackRate = 1;
    console.log(video.playbackRate, video.playbackRate);

};
btns[7].onclick = function () {
    // video.playbackRate = 10;            
    video.defaultPlaybackRate = 10;
    console.log(video.playbackRate, video.playbackRate);

};

btns[8].onclick = function () {
    video.currentTime = video.duration / 2;
};

事件

// 事件
video.onplay = function () {
    console.log(video.currentSrc); // 当前播放的地址
    console.log(video.duration); // 时长 在视频可以播放之后才能拿到 NaN 单位: s 秒
    console.log(video.paused); 
    console.log(video.ended);
};

// 当用户播放过程中时间发生改变
video.ontimeupdate = function () {
    console.log(video.currentTime);
}

// 当整个视频播放结束 且没有下一个的时候
video.onended = function () {
    console.log(video.ended);
};

// 当视频暂停的时候 触发的事件
video.onpause = function () {
    console.log('当前视频是否暂停', video.paused);
};

方法

load: 重新载入视频

pause: 暂停播放

play: 开始播放

btns[9].onclick = function () {
    video.load(); 
};

btns[10].onclick = function () {
    video.pause(); 
};

btns[11].onclick = function () {
    video.play(); 
};

Jquery

介绍

jquery: js的一个插件库

06年 Join resig

理念: 写得少 做得多(write less, do more)

特点:

完善的DOM操作机制

强大的选择器

链式调用

隐式迭代

解决了兼容: 1XX 兼容ie >2XX 不兼容ie

完善ajax实现数据请求

开源

jq的完善文档

使用:

jquery (v3.6.0) - jQuery 是一个高效、精简并且功能丰富的 JavaScript 工具库。它提供的 API 易于使用且兼容众多浏览器,这让诸如 HTML 文档遍历和操作、事件处理、动画和 Ajax 操作更加简单。 | BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务

jquery.js: 未压缩 学习

jquery.min.js: 压缩 工作

api网站: jQuery API 中文文档 | jQuery API 中文在线手册 | jquery api 下载 | jquery api chm

<!-- 1. 引入cdn地址 -->
<!-- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> -->
<!-- 2. 引入本地: 下载之后 -->
<!-- 验证是否引入成功: $ 是否是个函数 -->
<script src="js/jquery.js"></script>
<script>
    console.log($);
</script>

ready

window.onload: 等待页面和资源加载完成后在执行

ready: 等待页面结构加载完成

window.onload和ready方法的区别:

load: 等待页面和资源都加载完成后才执行, 后面的会覆盖前面的, 没有简写

ready: 等待页面加载完成后执行, 多个会叠加依次执行, 有简写 $(function(){});

// $ is not defined: jq没有引入
window.onload = function () {
    console.log(1);
};

window.onload = function () {
    console.log(2);
};

$(document).ready(function () {
    console.log(3);
});

$().ready(function () {
    console.log(4);
});

$(function () {
    console.log(5);
});

冲突解决

当jq的$覆盖其他人的$

<script>  
    var $ = 30;
    console.log($);
</script>

<script src="./js/jquery.js"></script>
<script>
    console.log($, window.$);
    jQuery.noConflict(); // 将$的控制权交给其他
    console.log($, window.$);
    console.log(jQuery, window.jQuery);
    // 使用自执行函数 接收jQuery为实参 $为形参
    (function ($) {
        console.log($);
    })(jQuery);
</script>

当别人的覆盖自己的:

<script src="./js/jquery.js"></script>
<script>
    var $ = 30;
    console.log($);
    console.log(jQuery);
    // 使用自执行函数
    (function ($) {
        console.log($);
    })(jQuery);
</script>

对象互转

js的方法和属性只能给js对象使用 jq的方法和属性只能给jq对象使用

原生转成jq对象 $(原生js对象)

console.log($(div));
console.log($(div[0]));

jq对象转js对象

\1. 通过下标获取到具体的元素

\2. get方法: jq对象.get(下标);

// 1. 通过下标获取到具体的元素
console.log(div1[0]);

// 2. get方法: jq对象.get(下标);
console.log(div1.get(0));

jq方法特性

  1. 取赋值一体化: 取值、赋值用的是同一个方法

    1. 取值: 获取到符合选择器条件的第一个元素的值 除了text

    2. 赋值: 隐式迭代设置所有的元素

  2. 隐式迭代: 所有的设置\所有的添加事件\所有的动画 在做添加的时候, 而是隐式的遍历所有的元素设置上

  3. 链式调用: 方法可以使用连点的方式依次执行

    原理: jq的方法都有返回值, 返回被操作的对象或者操作以后的对象

选择器

基础选择器

基础选择器: tagname .classname #id

console.log($('li'));
console.log($('.box'));
console.log($('#awrap'));
console.log($('.box, #awrap'));

层级选择器

父 子: 后代选择器 在父元素获取所有的后代的子元素

父 > 子: 直接子元素 在父元素中获取直接包裹的第一级子元素

兄a + 弟b: 相邻兄弟选择器 获取紧跟着a选择器后面的b选择器

兄a ~ 弟b: 后面兄弟 获取a后面所有的b

console.log($('ul li')); // 6
console.log($('ul > li')); // 5
console.log($('li + div'));
console.log($('.box + div')); // 不能
console.log($('.box ~ div')); // .box后面所有的div标签

基础过滤选择器

/ 通过样式设置
// jq对象.css(属性名, 属性值);
$('ul li:first').css('background', 'red'); // 获取li中的第一个
$('ul li:last').css('background', 'red'); // 获取li中的最后一个
$('ul li:nth-child(2)').css('background', 'red'); // 获取li中的第2个

// 奇偶数
$('ul li:odd').css('background', 'pink'); // 获取li中下标为奇数
$('ul li:even').css('background', 'skyblue'); // 获取li中下标为偶数

// 大于小于
$('ul li:gt(4)').css('background', 'blue'); // 获取li下标大于4
$('ul li:lt(4)').css('background', 'blue'); // 获取li下标小于4
$('ul li:eq(4)').css('background', 'red'); // 获取li下标等于4

// 不为
$('ul li:not(.box)').css('background', 'pink'); // 获取li中类名不为box的

属性过滤选择器

$('li[class]').css('background', 'red'); // 获取li中有class属性
$('li[class=box]').css('background', 'skyblue'); // 获取li中class值为box的元素
$('li[class^=b]').css('background', 'orange'); // 获取li中class属性值以b为开头的元素
$('li[class$=b]').css('background', 'purple'); // 获取li中class属性值以b为结尾的元素
$('li[class*=b]').css('background', 'aqua'); //获取li中class属性值有b的元素
$('li[class!=box]').css('background', 'deeppink'); // 获取li中class属性值不等于box的元素

表单过滤选择器

console.log($(':input')); // 获取所有表单元素
console.log($(':input:text'));
console.log($(':input:password'));
console.log($(':input:radio'));
console.log($(':input:checkbox'));


console.log($(':checked'));
console.log($(':radio:checked'));
console.log($(':checkbox:checked'));

节点遍历

// 查找子节点: jq对象.children(筛选条件)
console.log($('ul').children()); // 找到直接子节点
console.log($('ul').children('.box')); // 找到直接子节点
console.log($('ul').find('.box')); // 找到子节点
console.log($('ul').find('div')); // 找到子节点


// 找父节点
console.log($('.box').parent()); // 直接父节点
console.log($('.box').parents()); // 所有父节点 html

// 上面的兄弟节点 prev/prevAll(筛选条件)
console.log($('.box').prev()); // 紧跟的上一个
console.log($('.box').prevAll()); // 前面所有的

// 下面的兄弟节点
console.log($('.box').next()); // 紧跟的下一个
console.log($('.box').nextAll()); // 后面的所有的


// 所有兄弟节点
console.log($('.box').siblings());

操作属性

prop:

语法: jq对象.prop(属性名, 属性值)

获取: jq对象.prop(属性名)

设置: jq对象.prop(属性名, 属性值)

操作固有属性

attr:

语法: jq对象.attr(属性名, 属性值)

获取: jq对象.attr(属性名)

设置: jq对象.attr(属性名, 属性值)

操作所有的属性

移除属性:

jq对象.removeProp('属性名');

jq对象.removeAttr('属性名');

console.log($('div').prop('id'));
console.log($('div').prop('class'));
console.log($('div').prop('tag')); // undefined

console.log($('div').attr('id'));
console.log($('div').attr('class'));
console.log($('div').attr('tag')); // 123456

$('div').prop('class', 'a');
$('div').prop('tag', '这是tag'); // 没效果

$('div').attr('tag', '这是小的taga');


$(':checkbox').attr('checked', true);

// $(':checkbox').attr('checked', false);
$('div').removeAttr('class');

操作类名

添加: jq对象.addClass('类名') 在原有的基础上添加新的类名

删除: jq对象.removeClass('类名') 在原有的基础上删除类名

切换: jq对象.toggleClass('类名') 原来有就去掉 原来没有就加上

// $('div').addClass('active');
// $('div').removeClass('active');
$('div').click(function () {
    console.log(this);
    $(this).toggleClass('active');
});

操作样式

语法: jq对象.css('属性名', '属性值'); jq对象.css({});

获取: jq对象.css('属性名'); 获取一个属性的值

设置: jq对象.css('属性名', '属性值');

jq对象.css({

'属性名': '属性值',

'属性名': '属性值'

});

属性名: 引号可加可不加 建议加 可以使用-

属性值: 数字 加不加单位都可以

表达式 '+=' '-='

$('div').click(function () {
    console.log($(this).css('background'));
    // var a = $(this).css('background', 'red');
    // console.log(a);
    // a.css('height', 200);


    $(this).css('background', 'red').css('height', 200).css({
        // 'width': 200,
        // fontSize: 30
        'font-size': 30,
        'width': '+=10'
    });
});

操作内容

val

表单: jq对象.val(); jq对象.val(值);

单复选框: 默认的value值就是on

val: 设置单选、复选的值: jq对象.val(['值', "值"]);

console.log($(':text').val());
console.log($(':text').val('admin'));

console.log($(':radio'));
console.log($(':radio:checked').val());

console.log($(':checkbox').val());

$(':radio').val(['man']);
$(':checkbox').val(['smooking', 'yq']);


console.log($('select').val());
console.log($('select').val('sh'));

html

共同点: 后面的会覆盖前面的

获取: jq对象.html();

可以识别标签的

设置: jq对象.html(值);

不想覆盖原内容 原内容 + 新内容

console.log($('div').text());
console.log($('div').html());
var a = $('div').html();

$('div').text('这是一个新的内容');
$('div').html('<b>这是一个新的内容</b>');
// 不想覆盖原内容  原内容 + 新内容
$('div').html(a + '<i>这是斜体</i>');

text

共同点: 后面的会覆盖前面的

获取: jq对象.text();

会获取到所有符合选择器元素的内容, 不能识别标签

设置: jq对象.text(值);

不想覆盖原内容 原内容 + 新内容

console.log($('div').text());
var a = $('div').text();

$('div').text('这是一个新的内容');
$('div').html('<b>这是一个新的内容</b>');
// 不想覆盖原内容  原内容 + 新内容
$('div').text(a + '<i>这是斜体</i>');

元素宽高

内容宽高

width(数值)

height(数值)

console.log($('div').width(), $('div').height());
// console.log($('div').width(300), $('div').height(200));

可视宽高

可视宽高: 内容 + 内边距

innerWidth(数值)

innerHeight(数值)

屏幕的可视宽高:

$(window).innerWidth(), $(window).innerHeight()

console.log($('div').innerWidth(), $('div').innerHeight()); // 340 225
// console.log($('div').innerWidth(300), $('div').innerHeight(200)); // cont(260) + 40 = 300  cont(175) + 25 = 200
// 屏幕的可视宽高
console.log($(window).innerWidth(), $(window).innerHeight());

占位宽高

占位宽高: 内容 + 内边距 + 边框

布尔: 是否包含外边距在内 false: 默认 不包含外边距margin true: 包含

outerWidth(数值, 布尔)

outerHeight( 数值, 布尔)

console.log($('div').outerWidth()); // 200 + 40 + 22 = 262
console.log($('div').outerWidth(true)); // 200 + 40 + 22 + 60 = 322
$('div').outerWidth(400); // cont(338) + 40 + 22 = 400
$('div').outerWidth(400, true); // cont(278) + 40 + 22 + 60 = 400

获取元素偏移距离

offset(): 获取的是元素距离页面左侧和顶部的距离

{top: 0, left: 0}

console.log($('div').offset()); // {top: 10, left: 40}
console.log($('div').offset().top); // 10

滚动距离

scrollLeft()

scrollTop()

$(window).scroll(function () {
    console.log($(window).scrollTop(), $(window).scrollLeft());
});
$('button').click(function () {
    $(window).scrollTop(500);
    $(window).scrollLeft(500);
});

循环

jq对象.map(函数) jq对象.each(函数)

map会将函数的返回值组成新数组返回

each就返回被操作的对象

var res = $('div').map(function (i, v) { // 第一个形参: 下标  第二个形参: 项
    console.log(i, v);
    return 1;
});

var res1 = $('div').each(function (i, v) { // 第一个形参: 下标 第二个形参: 项
    console.log(i, v);
    return 2;
});
console.log(res, res1);

创建节点

var li = $('<li>新节点</li>');
console.log(li);

添加节点

追加到父节点的末尾

父.append(子);

子.appendTo('父');

// $('ul').append(li);
li.appendTo('ul');

添加到父节点的开头

父.prepend(子);

子.prependTo(父);

$('ul').prepend('<li>新1</li>');
$('<li>新2</li>').prependTo('ul');

添加到某个节点之后

参考节点.after(新节点);

新节点.inserAfter(参考节点);

$('.box').after('<li>加入1</li>');
$('<li>加入2</li>').insertAfter('.box');

添加到某个节点之前

参考节点.before(新节点);

新节点.insertBefore(参考节点);

$('.box').before('<li>before1</li>');
$('<li>before2</li>').insertBefore('.box');

删除节点

detach: 删除元素,返回被删除的元素,会保留元素原来的事件

remove: 删除元素,返回被删除的元素,不保留元素原来的事件

empty: 清空元素

$('li').click(function () {
    $(this).css('background', 'skyblue');
});
$('button').click(function () {
    // var li = $(this).parent().detach();
    var li = $(this).parent().remove();
    console.log(li);
    $('ul').append(li);


    return false;
});

$('div').click(function () {
    $('ul').empty();
});

克隆节点

clone: jq对象.clone(boolean);

返回一个新节点

true: 克隆行为

false: 不克隆行为

$('li').click(function () {
    $(this).css('background', 'red');
});
// var l = $('.box').clone();
var l = $('.box').clone(true);
console.log(l);
l.appendTo('ul');

替换节点

参考节点.replaceWith(新节点);

新节点.replaceAll(参考节点);

$('li').eq(0).replaceWith(li);
$('<li>4</li>').replaceAll($('li').eq(1));

事件对象

事件对象: 当事件发生的时候 浏览器会将相关事件的信息存储在一个对象中 这个对象就叫做事件对象(鼠标位置、触发源、事件类型...)

jq: 事件对象的兼容, 是以事件处理函数的第一个形参

$('div').click(function (ev) {
    console.log(ev); // jQuery.Event  jq的事件对象
    console.log(ev.originalEvent); // js的事件对象
    console.log(ev.target); // 触发源
    console.log(ev.delegateTarget); // 事件绑定的对象
    console.log(ev.type); // 事件类型
    console.log(ev.ctrlKey, ev.altKey, ev.shiftKey); // 对应的键是否被按下
    console.log(ev.which); // 对应的按键的编码  左中右(123)
    console.log(ev.clientX, ev.clientY); // 页面距离屏幕可视区域左侧和顶部的距离
    console.log(ev.pageX, ev.pageY); // 鼠标距离页面左侧和顶部的距离
    console.log(ev.screenX, ev.screenY); // 鼠标距离屏幕左侧和顶部的距离
    console.log(ev.offsetX, ev.offsetY); // 鼠标距离触发源左侧和顶部的距离  不推荐
});

$('div').contextmenu(function (ev) {
    console.log(ev.which);
    ev.preventDefault();

});


$('p').click(function (ev) {
    // 阻止冒泡兼容:
    // ev.stopPropagation();
    // 取消默认行为
    // ev.preventDefault();

    // 阻止冒泡 + 取消默认行为
    return false;
});

事件绑定on

  1. 给同一事件添加多个事件处理函数

    jq对象.on('事件类型', 事件处理函数);

    不会覆盖 会叠加

    $('div').on('click', fn1);
    $('div').on('click', fn2);
  2. 给多个事件添加同一事件处理函数

    jq对象.on('事件 事件 事件', 事件处理函数);

    function fn3(ev) {
        console.log(ev.type);
    }
    $('div').on('mouseenter mouseleave', fn3);
  3. 给多个事件添加不同事件处理函数

    jq对象.on({

    事件类型: 事件处理函数,

    事件类型: 事件处理函数,

    事件类型: 事件处理函数

    });

    $('div').on({
        mousedown: fn1,
        mouseup: fn2,
        mousemove: fn3
    });
  4. 绑定自定义事件

    事件类型: 自己定义

    手动触发自定义事件: jq对象.trigger('事件类型');

    其他元素控制本元素事件 \ 页面结构清晰

    $('div').on('call', function () {
        console.log('你妈妈喊你回家吃饭');
    });
    // 点击按钮 触发call事件
    $('button').click(function () {
        $('div').trigger('call');
    });
  5. 命名空间: 当一个项目足够大的时候 命名不够用

    jq对象.on('事件类型.名', 事件处理函数);

    $('div').on('click.fn1', function () {
        console.log('这是新的fn1');
    });
  6. 事件委托:

    jq对象.on('事件类型', '子选择器', 事件处理函数)

    this--> 触发的子元素

    $('ul').on('click', 'li, div', function () {
        console.log(this);
    });
    
    // 优势: 元素可以发生在未来
    $('ul').append('<li>这是li</li>');

一次性事件 one

one: 与on方法用法一致

只能触发一次

$('div').one('click mousemove', function () {
    console.log(this);
});

取消事件

jq对象.off();

不传参: 表示取消所有的事件

事件类型: 表示取消当前事件的所有事件处理函数

两个参数: 表示取消当前事件的指定的事件处理函数

// $('div').on('click mousemove mouseenter', function (ev) {
//     console.log(ev.type);
// });

// $('div').on('mousemove', function () {
//     console.log(1);
// });

function fn1() {
    console.log(1);
};
function fn2() {
    console.log(2);
};
$('div').on('click', fn1);
$('div').on('click', fn2);
$('div').on('click.fn1', function () {
    console.log('这是新的fn1');
});
$('button').click(function () {
    // $('div').off();
    // $('div').off('mousemove');
    // $('div').off('click', fn1);
    $('div').off('click.fn1'); // 事件类型.名: 表示取消当前的事件类型下的事件处理函数
});

合成事件

hover: 滑入滑出

jq对象.hover(函数);

一个函数: 划入滑出都触发这个函数

两个函数: 第一个划入 第二个滑出

// $('div').hover(function (ev) {
//     console.log(ev.type);
// });

$('div').hover(function (ev) {
    console.log(ev.type);
}, function () {
    console.log(2);
});

动画

显示隐藏

show hide toggle

改变: w + h + o

不传参: 没有动画效果

show(speed, easing, callback)

speed: 动画执行的时间 单位: ms

easing: linear匀速 swing慢快慢

callback: 当动画执行完成后的回调函数

$('button').eq(0).click(function () {
    // $('div').eq(0).show();
    $('div').eq(0).show(2000, 'swing', function () {
        console.log('动画已经完成');
    });
});

$('button').eq(1).click(function () {
    // $('div').eq(0).hide();
    $('div').eq(0).hide(2000, 'swing', function () {
        console.log('完成');
    });
});

$('button').eq(2).click(function () {
    // $('div').eq(0).toggle();
    $('div').eq(0).toggle(1000, 'linear', function () {
        console.log('toggle');
    });
});

下拉收起

slideDown slideUp slideToggle

不传参: 有默认动画 400ms

slideDown(speed, easing, callback)

speed: 动画执行的时间 单位: ms

easing: linear匀速 swing慢快慢

callback: 当动画执行完成后的回调函数

$('button').eq(0).click(function () {
    // $('div').slideDown();
    $('div').slideDown(1000, 'swing', function () {
        console.log('下拉结束');
    });
});

$('button').eq(1).click(function () {
    // $('div').slideUp();
    $('div').slideUp(1000, 'linear', function () {
        console.log('收起结束');
    });
});

$('button').eq(2).click(function () {
    // $('div').slideToggle();
    $('div').slideToggle(1000, 'swing', function () {
        console.log('切换完成');
    });
});

透明度

fadeIn fadeOut fadeToggle

不传参: 有动画效果 400ms

fadeIn(speed, easing, callback)

fadeTo(speed, to, easing, callback)

speed: 动画执行的时间 单位: ms

easing: linear匀速 swing慢快慢

callback: 当动画执行完成后的回调函数

to: 到某一个透明度 0-1

$('button').eq(0).click(function () {
    // $('div').fadeIn();
    $('div').fadeIn(1000, 'swing', function () {
        console.log('显示了');
    });
});

$('button').eq(1).click(function () {
    // $('div').fadeOut();
    $('div').fadeOut(2000, 'linear', function () {
        console.log('隐藏');
    });

});

$('button').eq(2).click(function () {
    // $('div').fadeToggle();
    $('div').fadeToggle(2000, 'swing', function () {
        console.log('切换');
    });
});

$('button').eq(3).click(function () {
    $('div').fadeTo(2000, 0.5, 'swing', function () {
        console.log('0.5');
    });
});

自定义

jq对象.animate({动画属性}, speed, easing, callback);

$('button').click(function () {
    $('div').animate({
        width: 500,
        opacity: 0.1,
        height: 300
    }, 2000, 'linear', function () {
        console.log('已完成');
    });
});

jq对象.animate({动画属性}, {options});

options:

duration: 动画时长

easing: 运动曲线

complete: 回调函数

step: 每一步的回调函数

queue: 是否队列 布尔值 true: 排队(等前面动画执行完成) false: 不排队(跟随第一个动画一起执行)

var n = 0;
$('button').click(function () {
    $('div')
    .animate({margin: 100}, 2000)
    .animate({borderWidth: 100}, 2000)
    .animate({
        width: 500,
        opacity: 0.1,
        height: 300
    },{
        duration: 3000,
        easing: 'linear',
        complete: function () {
            console.log('完成');
        },
        step: function () {
            n++;
            console.log('当前走了', n);
        },
        // queue: true
        queue: false
    });
});

停止动画

jq对象.stop(clearQueue, gotoEnd):

clearQueue:

false/不传: 开始下一个动画

true: 后续所有动画都清除

gotoEnd: 是否在停止的一瞬间到达本次动画的结束位置

false/不传: 在哪里停就在哪里

true: 挺值得一瞬间到达本次动画的结束位置

jq对象.finish(): 1.8+ 一次性结束所有动画并且到达目标值

$('button').eq(0).click(function () {
    $('div').animate({
        width: 1000,
        height: 1000
    }, 10000).animate({
        opacity: 0.1
    }, 10000);
});

$('button').eq(1).click(function () {
    // $('div').stop(false, false); // 停止后下一个动画继续执行 不到达目标值,留在当前位置
    // $('div').stop(true, false); // 停止后后续没有动画 不到达目标值,留在当前位置
    // $('div').stop(true, true); // 停止后后续没有动画 到达目标值

    $('div').finish();
});

循环

jq对象.map/each

jq对象.map(函数)

jq对象.each(函数)

2个形参: 第一个下标 第二个值

map: 会接受返回值组成一个新数组返回

each: 返回被操作的对象

var res = $('li').map(function (i, v) {
    console.log(i, v);
    return 1;
});
console.log(res);

var res1 = $('li').each(function (i, v) {
    console.log(i, v);
    return 1;
});
console.log(res1);


var arr = [1,2,3,4,5];
/* 
    数组.map()
        第一个形参: 值 第二个形参: 下标

    数组不可以使用each
*/
var r1 = arr.map(function (v, i) {
    console.log(i, v);
    return 2;
});
console.log(r1);

// 报错
// var r2 = arr.each(function (i, v) {
//     console.log(i, v);
//     return 2;
// });
// console.log(r2);

$.map/each

$.each(数据, 回调函数)

第一个形参: 下标/属性名

第二个形参: 项

$.map(数据, 回调函数)

第一个形参: 项

第二个形参: 下标/属性名

map: 会接受返回值组成一个新数组返回

each: 返回被操作的对象

var obj = {
    name: '迪丽热巴',
    age: 33,
    height: 173
};
console.log(obj);
var e1 = $.each(obj, function (key, val) {
    console.log(key, val);
    return 3;
});
console.log(e1);

var m1 = $.map(obj, function (val, key) {
    console.log(key, val);
    return val;
});
console.log(m1);

extend

浅拷贝

浅拷贝: deep: 可传可不传 不传/false默认浅拷贝

比较每一个对象的属性名, 如果属性名相同, 用后面的覆盖前面的, 如果属性名不同 拷贝到目标对象

var obj = {
    name: '迪丽热巴',
    age: 33,
    money: {
        movie: '热火军校',
        song: 'sugar',
        dance: '明日之子'
    }
};

var obj1 = {
    name: '李现',
    height: 177,
    money: {
        movie: '河神'
    }
};

var o = $.extend(false, {}, obj, obj1);
console.log(o);

深拷贝

深拷贝: 第一个参数是true, 递归拷贝, 会比较每一属性名, 如果属性名相同并且属性值都是对象, 对比子属性, 如果相同, 后面的覆盖前面的, 如果不同, 直接拷贝

var o1 = $.extend(true, {}, obj, obj1);
console.log(o1);

深拷贝合集

  1. $.extend(true, 目标对象, 拷贝对象)

    // 深拷贝
    var o1 = $.extend(true, {}, obj);
    // console.log(o1);
    // console.log(o1 == obj);
  2. JSON.stringify: 将js数据转成json数据

    JSON.parse: 将json数据转成js数据

    // var s = JSON.stringify(obj);
    // console.log(s);
    // var o2 = JSON.parse(s);
    var o2 = JSON.parse(JSON.stringify(obj));
    // console.log(o2, o2 == obj);
  3. 递归拷贝: 封装递归函数实现拷贝

    // 1. 函数
    function deepClone(json) {
        // console.log(json);
        // 2. 克隆: 拷贝的是数组 创建新的数组 拷贝的是对象 创建新的对象 其他的数据 直接返回
        // console.log(getType(json));
        if(getType(json) == 'Object'){
            var obj = {};
        } else if(getType(json) == 'Array'){
            var obj = [];
        } else {
            // 其他数据不做克隆和处理 直接返回
            return json;
        }
    
        // 3. 存数据: 将原来数据每一个属性都存储
        for(var key in json){
            // console.log(key, json[key]);
            // 4. 判断要存储的数据有没有数组或者对象 如果有 深拷贝 如果不是数组或对象 直接存储
            // console.log(getType(json[key]));
            if(getType(json[key]) == 'Object' || getType(json[key]) == 'Array'){
                obj[key] = deepClone(json[key]);
            } else {
                obj[key] = json[key];
            }
        }
        // console.log(obj);
    
        // 4. 设置返回值
        return obj;
    }
    var o = deepClone(obj);
    var a = deepClone([1,2,4]);
    console.log(o);
    console.log(a);

使用插件

插件: 在jq基础上二次封装实现的功能性函数

百度

CSDN

swiper

fullpage

github

jq22.com

用:

\1. 找

\2. 下载

<link rel="stylesheet" href="css/style.css">
<div class="nav">
    <div class="nav_li">
        <ul>
            <li><a href="#">Demo1</a></li>
            <li><a href="#">Demo2</a></li>
            <li><a href="#">Demo3</a></li>
            <li><a href="#">Demo4</a></li>
        </ul>
    </div>
</div>

<script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script>
<script type="text/javascript" src="js/style.js"></script>

插件拓展

对象级别插件拓展

插件相当于将功能进行封装

$.fn.extend({

方法名: 函数,

方法名: 函数

});

对象级别插件使用: jq对象.方法();

$.fn.extend({
    'lunbo': function () {
        // console.log(1);
        // 实现轮播功能
        // 1. this: 调用方法的jq对象
        console.log(this);
        // 存储正确的this
        var that = this;
        // 2.1 假设当前是第一张
        var n = 0;
        // 2. 每隔3s换下一张图
        setInterval(function () {
            n++;

            // 判断
            if(n == $(that).find('li').length){
                n = 0;
            }
            // console.log(this); // this-->window
            $(that).find('li').animate({
                'opacity': 0
            }, {
                'duration': 500
            }).eq(n).animate({
                'opacity': 1
            }, {
                'duration': 500,
                'queue': false
            });
            // 更新小圆点
            $(that).find('span').removeClass('active').eq(n).addClass('active');
        }, 3000);

        // 设置返回值
        return $(that);
    },
    'drag': function () {  }
});

类级别插件拓展

用类级别插件:

$.extend({

方法名: 函数,

方法名: 函数

});

调用: $.方法名();

$.extend({
    getMax: function (string) {
        var obj = {};
        // 每个字符
        for (var i = 0; i < string.length; i++) {
            // split: 将字符按照分割分割成数组
            var arr = string.split(string[i]);
            obj[string[i]] = arr.length - 1;
        }

        // 找到最大次数的字符
        // 用每一个字符出现的次数做对比 
        var max = 0;
        var maxstr = '';
        for (var k in obj) {
            // console.log(k, obj[k]); // 字符 字符的次数
            if (max < obj[k]) {
                max = obj[k];
                maxstr = k;
            }
        }
        // console.log(max, maxstr);
        return {
            max: max,
            ms: maxstr
        };
    }
});

Zepto

介绍

zepto专门给移动端设计的轻量级的javascript库 只针对现代高级浏览器

几乎一样 但是还有2点是不一样

官网: Zepto.js: 轻量且兼容 jQuery API 的 JavaScript 工具库 | Zepto.js 中文网

github: GitHub - madrobby/zepto: Zepto.js is a minimalist JavaScript library for modern browsers, with a jQuery-compatible API

\1. jq有 zepto没有: innerWidth/innerHeight outerWidth/OuterHeight

\2. offset: jq: {top: 0, left: 0} zepto: {top:0, left: 0, width: 0, height: 0}

/* 
    zepto专门给移动端设计的轻量级的javascript库 只针对现代高级浏览器
    几乎一样 但是还有2点是不一样
*/
// 1. jq有 zepto没有: innerWidth/innerHeight  outerWidth/OuterHeight
// console.log($('div').innerWidth(), $('div').outerWidth());

// 2. offset: jq: {top: 0, left: 0} zepto: {top:0, left: 0, width: 0, height: 0}
console.log($('div').offset());

模块使用

  1. 先引入完整的zepto文件

  2. 再引入src下的模块的文件

<!-- 
    src文件下的 zepto 禁止使用!!!!
-->
<!-- 先引入完整的zepto文件 -->
<script src="./js/zepto.js"></script>
<!-- 再引入src下的模块的文件 -->
<script src="./src/touch.js"></script>
<script>
    /* 
        doubleTap 双击
        tap, singleTap 单击
        longTap 长按
        swipe 滑动
        swipeLeft 左滑
        swipeRight 右滑
        swipeUp 上滑
        swipeDown 下滑
    */
    $('div').on('tap singleTap doubleTap swipe swipeUp swipeDown swipeLeft swipeRight', function (ev) {
        console.log(ev.type);
    });
</script>

Bootstrap

bootstrap: html和css和js的框架

官网: Bootstrap v3 中文文档 · Bootstrap 是最受欢迎的 HTML、CSS 和 JavaScript 框架,用于开发响应式布局、移动设备优先的 WEB 项目。 | Bootstrap 中文网

注意: bootstrap的js都是基于jq基础, 先引入jq

简单使用

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <h1>你好,世界!</h1>

    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
  </body>
</html>

容器

固定布局

固定布局: 1200px 左右自带15px内边距

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./bootstrap-3.4.1-dist/css/bootstrap.min.css">
</head>
<body>
    <!-- 固定布局: 1200px 左右自带15px内边距 -->
    <div class="container">
        123
    </div>

    <script src="./js/jquery.min.js"></script>
    <script src="./bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
</body>
</html>

流式布局

流式布局: 占满整个视口 左右自带15px内边距

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./bootstrap-3.4.1-dist/css/bootstrap.min.css">
</head>
<body>
    <!-- 固定布局: 1200px 左右自带15px内边距 -->
    <div class="container">
        fcghds
      </div>

    <!-- 流式布局: 占满整个视口 左右自带15px内边距 -->
    <div class="container-fluid">
        456
    </div>

    <script src="./js/jquery.min.js"></script>
    <script src="./bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
</body>
</html>

栅格系统

使用

认为页面都是有行与列组成, 认为一行分12列

会先化 行 row

再写 列 col--

第一个星: lg md sm xs

第二个星: 1-12数字

移动端的尺寸:

超大屏幕: > 1200px

中等屏幕: 992 < x < 1200

小屏幕: 768 < x < 992

超小屏幕: < 768

col-lg-*: 在>=1200以上堆叠排列 <1200 水平排列

col-md-*: 在>=992堆叠排列 <992 水平排列

col-sm-*: 在>=768堆叠排列 <768 水平排列

col-xs-*: 始终堆叠排列

<div class="container">
    <div class="row">
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
        <div class="col-lg-1">col-lg-1</div>
    </div>
    <div class="row">
        <div class="col-lg-12">col-lg-12</div>
    </div>
    <div class="row">
        <div class="col-lg-3">col-lg-3</div>
        <div class="col-lg-3">col-lg-3</div>
        <div class="col-lg-3">col-lg-3</div>
        <div class="col-lg-3">col-lg-3</div>
    </div>
    <div class="row">
        <div class="col-lg-2">col-lg-2</div>
        <div class="col-lg-10">col-lg-10</div>
    </div>
</div>

兼容

处理屏幕尺寸不同显示兼容: 给一个列加多个类名

1200以上 一行显示6个

992-1200 一行显示 4个

768-992 一行显示3个

768 一行显示2个

<div class="row">
    <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">内容1</div>
    <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">内容2</div>
    <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">内容3</div>
    <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">内容4</div>
    <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">内容5</div>
    <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">内容6</div>
</div>

列偏移

col--offset-:

第一个星: lg md sm xs

第二个星: 1-12

col-lg-offset-6: >1200 向右偏移 6 个

col-md-offset-4: >992 < 1200 向右偏移4个

col-sm-offset-3: >768 <992 向右偏移3个

col-xs-offset-2: <768 向右偏移2个

<div class="row">
    <div class="col-lg-2 col-lg-offset-6 col-md-offset-4 col-sm-offset-3 col-xs-offset-2">偏移</div>
</div>

push

不会改变其他元素的位置 会形成重叠

col--push-:

第一个星: lg md sm xs

第二个星: 1-12

<div class="row">
    <div class="col-xs-2 col-lg-push-6 col-md-push-3 col-sm-push-2 col-xs-push-1" style="background: pink;">col-xs-1</div>
    <div class="col-xs-2">col-xs-21</div>
    <div class="col-xs-2">col-xs-22</div>
    <div class="col-xs-2">col-xs-23</div>
    <div class="col-xs-2">col-xs-24</div>
</div>

pull

不会改变其他元素的位置 会形成重叠

col--push-/col--pull-:

第一个星: lg md sm xs

第二个星: 1-12

<div class="row">
    <!-- 
        不会改变其他元素的位置 会形成重叠
        col-*-push-*/col-*-pull-*:
            第一个星: lg md sm xs
            第二个星: 1-12
    -->
    <div class="col-xs-2 col-lg-push-6 col-md-push-3 col-sm-push-2 col-xs-push-1" style="background: pink;">col-xs-1</div>
    <div class="col-xs-2">col-xs-21</div>
    <div class="col-xs-2">col-xs-22</div>
    <div class="col-xs-2 col-lg-pull-6 col-md-pull-5 col-sm-pull-3 col-xs-pull-1" style="background: skyblue;">col-xs-23</div>
    <div class="col-xs-2">col-xs-24</div>
</div>

列嵌套

每一个列都可以在当做一个新的行做栅格系统划分

<div class="container">
<div class="row">
    <div class="col-md-4">col-md-4</div>
    <div class="col-md-4">col-md-4</div>
    <div class="col-md-4">col-md-4</div>
</div>
<div class="row">
    <div class="col-md-4">
        <div class="row">
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
            <div class="col-md-1">col-md-1</div>
        </div>
    </div>
    <div class="col-md-4">col-md-4</div>
    <div class="col-md-4">col-md-4</div>
</div>

表格

table: 表格

table-striped: 条纹表格

table-bordered:边框

table-hover:悬停

table-responsive:响应式

<table class="table">
    <thead>
        <th>#</th>
        <th>姓名</th>
        <th>性别</th>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
    </tbody>
</table>

<table class="table table-striped table-bordered table-hover">
    <thead>
        <th>#</th>
        <th>姓名</th>
        <th>性别</th>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr>
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr>
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr>
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr class="active">
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr class="success">
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr class="warning">
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr class="danger">
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
        <tr class="info">
            <td>1</td>
            <td>张三</td>
            <td>22</td>
        </tr>
    </tbody>
</table>

<div class="table-responsive">
    <table class="table">
        <thead>
            <th>#</th>
            <th>姓名</th>
            <th>性别</th>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>张三</td>
                <td>22</td>
            </tr>
        </tbody>
    </table>
</div>

表单

垂直表单

使用form-group添加单行

<form>
    <div class="form-group">
        <label for="exampleInputEmail1">中文邮箱:</label>
        <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
    </div>
    <div class="form-group">
        <label for="exampleInputPassword1">密码:</label>
        <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
    </div>
    <div class="form-group">
        <label for="exampleInputFile">选择文件:</label>
        <input type="file" id="exampleInputFile">
        <p class="help-block">如果需要帮助可以点击这里.</p>
    </div>
    <div class="checkbox">
        <label>
            <input type="checkbox"> Check me out
        </label>
    </div>
    <button type="submit" class="btn btn-default">Submit</button>
</form>

水平表单

form-horizontal: 实现水平排列表单

使用form-group添加单行

<form class="form-horizontal">
    <div class="form-group">
        <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
        <div class="col-sm-10">
            <input type="email" class="form-control" id="inputEmail3" placeholder="Email">
        </div>
    </div>
    <div class="form-group">
        <label for="inputPassword3" class="col-sm-2 control-label">Password</label>
        <div class="col-sm-10">
            <input type="password" class="form-control" id="inputPassword3" placeholder="Password">
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <div class="checkbox">
                <label>
                    <input type="checkbox"> Remember me
                </label>
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-default">Sign in</button>
        </div>
    </div>
</form>

内联表单

form-inline: 实现内联表单布局

<form class="form-inline">
    <div class="form-group">
        <label for="exampleInputName2">Name</label>
        <input type="text" class="form-control" id="exampleInputName2" placeholder="Jane Doe">
    </div>
    <div class="form-group">
        <label for="exampleInputEmail2">Email</label>
        <input type="email" class="form-control" id="exampleInputEmail2" placeholder="jane.doe@example.com">
    </div>
    <div class="form-group">
        <label for="addressInput">adress</label>
        <input type="email" class="form-control" id="addressInput" placeholder="beijing">
    </div>
    <button type="submit" class="btn btn-default">Send invitation</button>
</form>

<form class="form-inline">
    <div class="form-group">
        <label class="sr-only" for="exampleInputEmail3">Email address</label>
        <input type="email" class="form-control" id="exampleInputEmail3" placeholder="Email">
    </div>
    <div class="form-group">
        <label class="sr-only" for="exampleInputPassword3">Password</label>
        <input type="password" class="form-control" id="exampleInputPassword3" placeholder="Password">
    </div>
    <div class="checkbox">
        <label>
            <input type="checkbox"> Remember me
        </label>
    </div>
    <button type="submit" class="btn btn-default">Sign in</button>
</form>

表单控件大小

input-lg: 大尺寸

input-sm:小尺寸

col-*-*:在不同屏幕尺寸下控制大小

<input class="form-control input-lg" type="text" placeholder=".input-lg">
<input class="form-control" type="text" placeholder="Default input">
<input class="form-control input-sm" type="text" placeholder=".input-sm">

<select class="form-control input-lg">
    <option value="bj">北京</option>
    <option value="sh">上海</option>
    <option value="tj">天津</option>
</select>
<select class="form-control">
    <option value="bj">北京</option>
    <option value="sh">上海</option>
    <option value="tj">天津</option>
</select>
<select class="form-control input-sm">
    <option value="bj">北京</option>
    <option value="sh">上海</option>
    <option value="tj">天津</option>
</select>


<form class="form-horizontal">
    <div class="form-group form-group-lg">
        <label class="col-sm-2 control-label" for="formGroupInputLarge">Large label</label>
        <div class="col-sm-10">
            <input class="form-control" type="text" id="formGroupInputLarge" placeholder="Large input">
        </div>
    </div>
    <div class="form-group form-group-sm">
        <label class="col-sm-2 control-label" for="formGroupInputSmall">Small label</label>
        <div class="col-sm-10">
            <input class="form-control" type="text" id="formGroupInputSmall" placeholder="Small input">
        </div>
    </div>
</form>


<div class="row">
    <div class="col-xs-2 col-md-3">
        <input type="text" class="form-control" placeholder=".col-xs-2">
    </div>
    <div class="col-xs-3 col-md-3">
        <input type="text" class="form-control" placeholder=".col-xs-3">
    </div>
    <div class="col-xs-4 col-md-3">
        <input type="text" class="form-control" placeholder=".col-xs-4">
    </div>
</div>

图片

图片形状

<!-- 圆角边框 -->
<!-- <img src="../day06/img/1.jpg" alt="..." class="img-rounded"> -->
<!-- 圆形 -->
<!-- <img src="../day06/img/1.jpg" alt="..." class="img-circle"> -->
<!-- 带有边框的直角图片 -->
<!-- <img src="../day06/img/1.jpg" alt="..." class="img-thumbnail"> -->

响应式图片

<img src="../day06/img/1.jpg" class="img-responsive" alt="Responsive image">

字体图标

使用过程: 新建一个空标签 复制icon的类名 直接粘贴就可以使用

<i class="glyphicon glyphicon-play"></i>
<i class="glyphicon glyphicon-pause"></i>
<i class="glyphicon glyphicon-hdd"></i>

导航

默认

data-toggle: dropdown 控制是否显示下拉菜单

navbar-default: 默认导航

navbar-right: 放在菜单的右侧

navbar-left: 放在菜单的左侧

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <a class="navbar-brand" href="#">首个菜单</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">链接 <span class="sr-only">(c当前)</span></a></li>
                <li><a href="https://www.baidu.com">百度</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                        aria-haspopup="true" aria-expanded="false">下拉菜单 <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                        aria-haspopup="true" aria-expanded="false">下拉菜单1 <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">1</a></li>
                        <li><a href="#">2</a></li>
                        <li><a href="#">3</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">4</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">5</a></li>
                    </ul>
                </li>
            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                        aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>

反差色

<nav class="navbar navbar-inverse">
    <!-- <button class="btn btn-default">首页</button> -->
    <div class="container-fluid">
        <ul class="nav nav-tabs">
            <li role="presentation" class="active"><a href="#">Home</a></li>
            <li role="presentation"><a href="#">Profile</a></li>
            <li role="presentation"><a href="#">Messages</a></li>
            <li role="presentation">
                <div class="dropdown">
                    <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1"
                        data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
                        Dropdown
                        <span class="caret"></span>
                    </button>
                    <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </div>
            </li>
        </ul>
    </div>
</nav>

模态框

基础使用

data-target: 按钮控制的元素

data-toggle: 控制元素显示的方式 modal模态框

data-dismiss: 元素消失的效果 modal模态框

通过为 .modal-dialog 增加一个样式调整类实现大小控制:

modal-lg: 大模态框

modal-sm: 小模态框

<div class="container">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#my">
    Launch demo modal
</button>

<button id="open">打开模态</button>
<button id="change">切换模态</button>

<!-- Modal -->
<div class="modal fade" id="my" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                        aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">这是标题</h4>
            </div>
            <div class="modal-body">
                这是内容部分
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary" id="save">Save changes</button>
            </div>
        </div>
    </div>
</div>

事件

// 显示事件
$('#my').on('show.bs.modal', function (e) {
    console.log('显示');
});
// 动画显示完成后触发
$('#my').on('shown.bs.modal', function (e) {
    console.log('显示');
});
// 隐藏事件
$('#my').on('hide.bs.modal', function (e) {
    console.log('隐藏');
});
// 动画隐藏完成后
$('#my').on('hidden.bs.modal', function (e) {
    console.log('隐藏');
});

方法

$('#id').modal();

// open按钮 打开模态框
$('#open').click(function () {
    $('#my').modal('show');
});

// save按钮 隐藏模态框
$('#save').click(function () {
    $('#my').modal('hide');
});

// 点击change按钮 切换模态框
$('#change').click(function () {
    $('#my').modal('toggle');
});

菜单

下拉菜单

<div class="dropdown">
    <button id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Dropdown trigger
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" aria-labelledby="dLabel">
        <!-- 具体菜单展示的内容 -->
        <li>html</li>
        <li>css</li>
        <li>js</li>
        <li>jq</li>
    </ul>
</div>

上拉菜单

<div class="dropup">
    <button id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Dropdown trigger
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" aria-labelledby="dLabel">
        <!-- 具体菜单展示的内容 -->
        <li>html</li>
        <li>css</li>
        <li>js</li>
        <li>jq</li>
    </ul>
</div>

按钮式下拉菜单

<!-- Single button -->
<div class="btn-group">
    <a class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Action <span class="caret"></span>
    </a>
    <ul class="dropdown-menu">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
        <li role="separator" class="divider"></li>
        <li><a href="#">Separated link</a></li>
    </ul>
</div>

分裂下拉菜单

<!-- Split button -->
<div class="btn-group">
    <a class="btn btn-danger" href="https://www.baidu.com">跳转链接</a>
    <button type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
        <span class="caret"></span>
        <span class="sr-only">Toggle Dropdown</span>
    </button>
    <ul class="dropdown-menu" id="menu">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
        <li role="separator" class="divider"></li>
        <li><a href="#">Separated link</a></li>
    </ul>
</div>

方法

$().dropdown('toggle');

$('.only').click(function () {
    console.log(1);
    // 选中的是下拉的整个菜单
    $('.btn-group').dropdown('toggle');
});

事件

// 显示事件
$('.btn-group').on('show.bs.dropdown', function () {
    // do something…
    console.log('显示');
});
// 动画显示
$('.btn-group').on('shown.bs.dropdown', function () {
    // do something…
    console.log('动画显示');
});

// 隐藏事件
$('.btn-group').on('hide.bs.dropdown', function () {
    // do something…
    console.log('隐藏');
});
// 动画隐藏
$('.btn-group').on('hidden.bs.dropdown', function () {
    // do something…
    console.log('动画隐藏');
});

标签页

无动画切换

nav-tabs: 标题

id: 控制的是哪一部分 名字的显示

tab-panes: 显示的标签块

aria-controls: 当前按钮 点击切换显示的内容 tab-panes中的div的id一致

data-toggle: 切换方式 tab--标签页

<div>
    <!-- Nav tabs -->
    <ul class="nav nav-tabs" role="tablist">
        <li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab"
                data-toggle="tab">Home</a></li>
        <li role="presentation"><a href="#profile" aria-controls="profile" role="tab"
                data-toggle="tab">Profile</a></li>
        <li role="presentation"><a href="#messages" aria-controls="messages" role="tab"
                data-toggle="tab">Messages</a></li>
        <li role="presentation"><a href="#settings" aria-controls="settings" role="tab"
                data-toggle="tab">Settings</a></li>
    </ul>

    <!-- Tab panes -->
    <div class="tab-content">
        <div role="tabpanel" class="tab-pane active" id="home">home</div>
        <div role="tabpanel" class="tab-pane" id="profile">profiles</div>
        <div role="tabpanel" class="tab-pane" id="messages">msg</div>
        <div role="tabpanel" class="tab-pane" id="settings">set</div>
    </div>
</div>

透明度显示和隐藏

给tab-pane 加 fade 类名

给默认显示的 tab-pane 加 in 类名

<div>

    <!-- Nav tabs -->
    <ul class="nav nav-tabs last" role="tablist">
        <li role="presentation" class="active"><a href="#html" aria-controls="html" role="tab"
                data-toggle="tab">html</a></li>
        <li role="presentation"><a href="#css" aria-controls="css" role="tab" data-toggle="tab">css</a></li>
        <li role="presentation"><a href="#js" aria-controls="js" role="tab" data-toggle="tab">js</a></li>
        <li role="presentation"><a href="#jq" aria-controls="jq" role="tab" data-toggle="tab">jq</a></li>
    </ul>

    <!-- Tab panes -->
    <div class="tab-content">
        <div role="tabpanel" class="tab-pane fade in active" id="html">html</div>
        <div role="tabpanel" class="tab-pane fade" id="css">csss</div>
        <div role="tabpanel" class="tab-pane fade" id="js">js</div>
        <div role="tabpanel" class="tab-pane fade" id="jq">jq</div>
    </div>
</div>

方法

$('.last a').click(function (e) {
    e.preventDefault();
    $(this).tab('show');
});

事件

$('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
    console.log(e.target); // 即将出现的标签页
    console.log(e.relatedTarget); // 即将消失的标签页
});
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
    console.log(e.target); // 即将出现的标签页
    console.log(e.relatedTarget); // 即将消失的标签页
});
$('a[data-toggle="tab"]').on('hide.bs.tab', function (e) {
    console.log(e.target); // 即将出现的标签页
    console.log(e.relatedTarget); // 即将消失的标签页
});
$('a[data-toggle="tab"]').on('hidden.bs.tab', function (e) {
    console.log(e.target); // 即将出现的标签页
    console.log(e.relatedTarget); // 即将消失的标签页
});

轮播图

data-ride: 元素块的功能 carousel: 轮播

data-target: 整个轮播图最外层盒子的id

data-slide-to: 切换到第几张

data-slide: 切换方式 prev: 上一张 next: 下一张

<div id="my" class="carousel slide" data-ride="carousel">
    <!-- Indicators -->
    <!-- 小圆点 -->
    <ol class="carousel-indicators">
        <li data-target="#my" data-slide-to="0" class="active"></li>
        <li data-target="#my" data-slide-to="1"></li>
        <li data-target="#my" data-slide-to="2"></li>
        <li data-target="#my" data-slide-to="3"></li>
    </ol>

    <!-- Wrapper for slides -->
    <!-- item: 轮播图的每个页面 -->
    <div class="carousel-inner" role="listbox">
        <div class="item active">
            <img src="../day06/img/1.jpg" alt="...">
            <div class="carousel-caption">
                内容1
            </div>
        </div>
        <div class="item">
            <img src="../day06/img/2.jpg" alt="...">
            <div class="carousel-caption">
                内容2
            </div>
        </div>
        <div class="item">
            <img src="../day06/img/3.jpg" alt="...">
            <div class="carousel-caption">
                内容3
            </div>
        </div>
        <div class="item">
            <img src="../day06/img/4.jpg" alt="...">
            <div class="carousel-caption">
                内容4
            </div>
        </div>
    </div>

    <!-- Controls -->
    <!-- 左右箭头 -->
    <a class="left carousel-control" href="#my" role="button" data-slide="prev">
        <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
        <span class="sr-only">Previous</span>
    </a>
    <a class="right carousel-control" href="#my" role="button" data-slide="next">
        <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
        <span class="sr-only">Next</span>
    </a>
</div>

方法

$('#id').carousel();

interval: 轮播时间

pause: 划上是否停止 hover:停止 null:不停止

wrap: 是否循环播放 true: 循环 false: 不循环

$('#my').carousel({
    interval: 2000, // 每隔2s切换下一张
    pause: 'hover', // 划上是否停止
    // wrap: false // 是否循环播放
});

// 停止轮播图
$('.newWrap').mouseenter(function () {
    $('#my').carousel('pause');
});

// 开始轮播
$('.newWrap').mouseleave(function () {
    $('#my').carousel('cycle');
});

// 切换上一张
$('button').eq(0).click(function () {
    $('#my').carousel('prev');
});

// 切换下一张
$('button').eq(1).click(function () {
    $('#my').carousel('next');
});

// 切换到对应下标的轮播图
$('.num').click(function () {
    console.log($(this).index() - 2);
    $('#my').carousel($(this).index() - 2);
});

事件

// 事件
$('#my').on('slide.bs.carousel', function () {
    // do something…
    console.log('已切换');
});

$('#my').on('slid.bs.carousel', function () {
    // do something…
    console.log('已切换1');
});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值