一、 事件流
事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程也叫做DOM事件流
也就是说:
当咱们绑定了一个事件并执行后,这个事件并没有随着执行完毕而消失,会在节点之间进行传播
只有相同的事件之间才会进行传播
事件传播一般只发生在祖先元素和后代元素之间
完整的事件流阶段
1、捕获阶段:事件从外面往里面进行传播,在大的元素上面触发,再给小的传播
2、当前目标阶段
3、冒泡阶段:事件会从里面往外面进行传播,在小的元素里面触发,再给大的传播
阻止冒泡
e.stopPropagation()
二、事件委派
事件委托(委托):可以把事件绑定在共同的祖先元素上面,然后利于事件冒泡的原理进行事件传播的,这样就可以让所有的元素都有一个相同的事件,并且事件只绑定了一次
事件目标对象:e.target || e.srcElement
三、典型的例子(购物车)
这里只写了购物车的商品数量加减部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
table{
margin: 50px auto;
}
input{
width: 20px;
}
</style>
</head>
<body>
<table border="1" width="100" height="50">
<tr>
<td><button class="sub">-</button></td>
<td><input type="text" value="1"></td>
<td><button class="add">+</button></td>
</tr>
<tr>
<td><button class="sub">-</button></td>
<td><input type="text" value="1"></td>
<td><button class="add">+</button></td>
</tr>
<tr>
<td><button class="sub">-</button></td>
<td><input type="text" value="1"></td>
<td><button class="add">+</button></td>
</tr>
</table>
<script>
var cart = document.querySelector('table')
cart.onclick = function(e){
var target = e.target
if(target.className == 'add'){
// 表示让文本框value属性里面的数值自增
target.parentNode.previousElementSibling.children[0].value++
}
if(target.className == 'sub'){
// 表示让文本框value属性里面的数值自减
target.parentNode.nextElementSibling.children[0].value--
}
}
</script>
</body>
</html>
四、浏览器的默认行为
指的是浏览器默认自带的一些东西
右键菜单、默认选中文字、超链接点击会跳转、表单点击提交、当鼠标拖拽过快的时候出现禁止图标、在文本框里面输入内容.....
阻止默认行为方案
return false 推荐使用
e.preventDefault()
e.returnValue = false 低版本的IE浏览器(在测试的过程中发现现在的浏览器版本升级了后,这个也可以使用了)
五、事件监听
事件绑定分为两种类型
1.事件绑定:简单易用,被所有的浏览器所支持,兼容性更好
只有冒泡阶段(从小到大),没有捕获阶段(从大到小)
相同的事件不能重复绑定
2.事件监听:是一个方法,使用起来稍微复杂
冒泡阶段和捕获阶段同时存在
可以绑定相同的事件
兼容性没有事件绑定那么好
事件监听的语法:
ele.addEventListener()
参数1表示的是事件名称,不需要加on,字符串类型
参数2表示的是回调函数,里面写具体的业务代码
参数3表示的是冒泡(false,默认)还是捕获(true)
ele.removeEventListener()
var btn = document.querySelector('button')
//事件绑定
btn.onclick = function(){
console.log(1)
}
btn.onclick = function(){
console.log(2)
}
// 只执行一次,因为后面的会把前面的覆盖掉
//事件监听
btn.addEventListener('click', function(){
console.log(1)
},false)
btn.addEventListener('click', function(){
console.log(2)
},false)
// 两个都能生效
六、some()和every()
some(): 方法用于检测数组中的元素是否满足指定条件(函数提供)。如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。否则返回false
//some的应用,把商品添加购物车时要判断购物车里是不是已经存在这个商品,若存在就把数量加一就是
var cart = [{id: 1, title: '小米14', cart_number: 1}, {id: 2, title: '小米13', cart_number: 1}]
var res = cart.some(function(item){return item.id == 1})
if(res){
var index = cart.findIndex(function(item){return item.id == 1})
cart[index].cart_number += 1
}
every(): 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。如果有一个不符合就返回false
//every的用法:购物车里面的全选键
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
input{
display: block;
margin: 10px;
}
</style>
</head>
<body>
<div class="all">
<input type="checkbox">
</div>
<hr/>
<div class="select">
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">
</div>
<script>
var all = document.querySelector('.all>input')
var select = document.querySelectorAll('.select>input')
all.onclick = function(){
var state = all.checked
select.forEach(function(item){
item.checked = state
})
}
select.forEach(function(item){
item.onclick = function(){
var res = Array.from(select).every(function(item){
return item.checked == true
})
if(res){
all.checked = true
}else{
all.checked = false
}
}
})
// ES6提供了Array.from()可以把伪数组转成真正的数组
</script>
</body>
</html>
七、reduce()和reduceRight()
reduce():累加器,可以把数组里面的每一项数组元素进行相加或者拼接
函数参数:回调函数和默认选项(你可以设置初始值)
回调函数参数:参数1表示第一次计算的结果
参数2表示的是后面需要进行计算的数组元素(每一次都是变化的)
//reduce应用1:求数组的元素和
var arr = [10, 20, 30, 50, 80]
var sum = arr.reduce(function(first, item){
return first+item
},0)
console.log(sum) // 190
//reduce应用2:计算购物车的总价格
var cart = [{id: 1, title: '小米14', cart_number: 2, price: 299}, {id: 2, title: '小米13', cart_number: 1, price: 399}]
var total = cart.reduce(function(first,item){
return first.price * first.cart_number + item.price * item.cart_number
},0)
//reduce应用3:展开二维数组
var arr = ['蔡徐坤', ['a', 'b'], [10, 20, 30]]
var res = arr.reduce(function(first, item){
return first.concat(item)
},[])
reduceRight()与reduce()参数相同,作用也相同,不同的是reduce是从左到右的加,而reduceRight是从右到左的加
八、ES6变量声明方式
声明变量方式
var ES5之前的(包含ES5版本)
let ES6新增的
const ES6新增的
三者的区别:
var存在变量声明提升,可以重复声明相同的变量
let不存在变量声明提升,不能重复声明相同的变量,存在块级作用域
const声明常量(不能修改的),不存在变量声明提升,不能重复声明相同的变量,存在块级作用域
块级作用域:以前只有函数有作用域,现在块级作用域指的是以一个代码块({}、())为标准成为一个独立的作用域
for(let i=0; i<aBtn.length; i++){
// 作用域:可以把这个区域给你锁死,变量存储在这里了
aBtn[i].onclick = function(){
// 作用域,先在当前的作用域查找有没有i,没有找到就去上一级作用域进行查找
console.log(i)
}
}
九、箭头函数
箭头函数是对普通函数的一种简化
语法:const fn = ()=>{}
说明:
箭头函数只能通过变量表达式方式声明
箭头函数只有一个参数的时候可以省略小括号不写
箭头函数的花括号如果省略,那么表示你把函数的返回值也省略不写
注意点:
如果省略了箭头函数的花括号,返回的是基本数据类型,直接返回不了引用数据类型,如果要返回使用小括号包裹
箭头函数没有自己的this,如果里面写了this,那么this指向的是上一级代码的this
//普通的箭头函数
const fn=()=>{
console.log(1)
}
fn()
//带一个参数的箭头函数
const fn= a=>{
console.log(a)
}
//带两个参数的箭头函数
const fn=(a,b)=>{
return a+b
}
//注意点:如果省略了箭头函数的花括号,返回的是基本数据类型,
//直接返回不了引用数据类型,如果要返回使用小括号包裹
const fn = (a, b)=> ({name: '王成'})
const fn = (a, b)=> [1, 2, 3]
十、扩展运算符
扩展运算符:...
功能:展开、合并、复制
//展开
var arr = [10, 20, 30]
function fn(a, b, c){
console.log(a, b, c)
}
fn(...arr)
// 数组展开(把二维数组展开一位数组)
var arr = ['a', ...[10, 20]]
// 合并
function fn(...a){
console.log(a)
}
fn(10,20,30)
// 复制
const obj = {
name: '王成',
age: 18,
like: ['篮球', 'rap', '唱跳']
}
const obj2 = {
...obj
}
console.log(obj2)
十一、flat
flat() 可以把多维数组展开为指定的维数的数组
arr.flat(3) //把arr展开为三维数组
var res = arr.flat(Infinity) //把arr全部展开