中高级前端应该必会,js实现事件委托代理、切换样式、元素获取相对于文档位置等
1、介绍
随着组件开发大流行,现在三大框架已经基本占领了整个前端。
这时候,我们要是引入一个 jq 是不是先得你的项目非常臃肿,jq 也很不适合。
这个时候,你就需要来增加你 js 的功底。
2、各种操作
1、事件委托
案例分析:
<ul id= "list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
如上面的页面机构,我们需要个每一个 li 添加同一个事件。
常规操作:
选择出所有的 li 标签,然后为所有的标签都添加这个事件。
var liList = document.querySelectorAll('#list li')
liList.foreach(function(item,index)=>{
item.addEventListener('click',doSomething)
})
很简单,也是非常好的。
但是当这里的 li 标签多了之后,那么你获取所有的 li 标签并绑定事件就会变慢,也就是说性能就会不好了。
这个时候该如何处理呢?
事件委托:
解释下事件委托吧,可能新手不知道。
就是把子元素想要绑定的事件,绑定到子元素的父元素上面。
然后当事件触发的时候,通过事件冒泡来获取到当前事件源对应的的元素。(事件冒泡和捕获如果不知道还是需要补习下的)
代码展示:
var liList = document.querySelectorAll('#list')
liList.addEventListener('click',function(e)=>{
if(e.target && e.target.nodeName.toUpperCase == 'LI'){
console.log('你点击了'+e.target.innerText )
}
})
给一个比较完整的例子,没有验证...
function delegate(element, eventName, name, func) {
element.addEventListener(eventName, function (e) {
var target = e.target, parent = target;
while (target && parent != element) {
if (parent.nodeName.toLowerCase() == name) {
e.target = parent
func.apply(parent,e);
break;
}
parent = parent.parentNode;
}
});
}
上面的例子,name 字段可以是 类命,id 的值,也可以是 标签。
自行修改,更灵活。。
总结:
事件代理委托主要是通过给父元素绑定事件。
通过事件的冒泡来确定当前的事件源。
确定事件源,并执行具柄。
2、es5 的元素获取、class 的操作
es5 的元素获取
在之前我一直都是使用的 es3 做元素获取的,如:
document.getElementById(id)
document.getElementsByClassName(class)
上面的相信是大家以前最熟悉的 js 获取方法。
但是在 es5 出来后,你会惊奇的觉得 Jquery 选择器可以被替代了
document.querySelector(selector)
document.querySelectorAll(selector)
// 例如
document.querySelector('.classs p') // 获取 class 类下面的 p 标签
// 可以看到和 jquery 选择器差不多,只是功能精简了
上面很清楚的可以知道:
querySelector 是获取单个元素
querySelectorAll 是获取多个匹配元素
最大的变化就是 selector。
它可以是 .className 、 #id 、也可以是多级选择 .className p
class 类的一些 es5 操作
Dom 的 classList 属性:
<div id = "test" class = "red big hot"></div>
获取样式类列表
document.querySelector('test').classList
这里会返回一个 TokenList 也就是是个类数组:
{
0:red,
1:big,
2:hot,
length:3,
value:'red big hot'
}
添加类名
document.querySelector('test').classList.add('good','new')
添加类 good , new 。如果类名已经存在,则不添加
移除某类
document.querySelector('test').classList.remove('good','new')
移除 good , new 类。移除不存在的类,会报错
切换类
document.querySelector('test').classList.toggle('good')
切换 good 类。如果 good 存在返回true,否则false
判断是否存在某类
document.querySelector('test').classList.contains('good')
返回 boolean 值。
3、获取元素在父元素中第几个
其实这个在现在的组件模式中很容易实现。
但是 js 中是如是实现的呢 ?
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
获取方法及其封装:
function index(parent,son) {
return [].indexOf.call(parent.children,son);
}
如上面:
parent 是父元素,son 很显然是子元素
4、元素相对于文档 / 窗口视图的位置
相对于文档的位置
在 jquery 中我们实现的方法是 $(s).offset() 来回去相对于文档的位置。
那 js 中如何实现的呢?
代码:
const getDocPosition = (element) => {
let eleCom = element;
if (typeof element === 'string') eleCom = document.querySelector(eleCom);
let x = eleCom.offsetLeft;
let y = eleCom.offsetTop;
let parent = eleCom.offsetParent;
while (parent) {
x += parent.offsetLeft;
y += parent.offsetTop;
parent = parent.offsetParent;
}
return {
x,
y,
};
};
代码很简单:
可以看出,通过不断的获取 offsetLeft / offsetTop ,并且与它的父元素相加。
直到相加到顶级元素为止。
相对于窗口视图位置
getBoundingClientRect用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性。

rectObject = object.getBoundingClientRect();
rectObject.top:元素上边到视窗上边的距离;
rectObject.right:元素右边到视窗左边的距离;
rectObject.bottom:元素下边到视窗上边的距离;
rectObject.left:元素左边到视窗左边的距离;
如果你看过 lazyImg 图片的懒加载,你们就会发现,他的实现原理就是这个。
当它图片出现在窗口的视图中,就会加载真的图片资源。
后续继续添加常用的、容易忘的一些 js 功能。
https://www.cnblogs.com/jiebba/p/9663268.html
我的博客 : XiaoLong's Blog
博客园小结巴巴: https://www.cnblogs.com/jiebba
中高级前端应该必会,js实现事件委托代理、切换样式、元素获取相对于文档位置等的更多相关文章
- Js数组里删除指定的元素(不是指定的位置)
转载自:http://my.oschina.net/zh119893/blog/265964 之前一直是做后端的,从来也没有写过js,但是却一直想学学,也只是基于兴趣而已!现在到了这个公司,确实大量的 ...
- Js数组里剔除指定的元素(不是指定的位置)
s数组里删除指定的元素(不是指定的位置)之前一直是做后端的,从来也没有写过js,但是却一直想学学,也只是基于兴趣而已!现在到了这个公司,确实大量的写js.但也一直都是没有系统的去看过js!都是搞什么查 ...
- js兼容方法:通过样式名获取元素,byClass
function byClass(oParent,className){ if(document.getElementsByClassName){ //if it is Firefox return ...
- js下载后台返回的docx(返回格式:文档流)文件
原文地址: https://www.jianshu.com/p/a81c68c15fbd PS需要指定responseType类型,不然文件内容会乱码哦 咦?文件名乱码?需要手动设置文件名哦↓ 呀,文 ...
- 模仿jquery--offset方法。原生JS获取任意元素到文档document顶部的距离
1.通过遍历目标节点.目标节点的父节点,依次溯源. 然后累加这些节点到其最近可定位的祖先节点的距离.向上直到document. 其中,需要使用到节点的offsetTop/offsetLeft属性,来获 ...
- 前端UI框架和JS类库
一.前端框架库: 1.Zepto.js 地址:http://www.css88.com/doc/zeptojs/ 描述:Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jqu ...
- js 停止事件冒泡 阻止浏览器的默认行为(阻止超连接 # )
在前端开发工作中,由于浏览器兼容性等问题,我们会经常用到“停止事件冒泡”和“阻止浏览器默认行为”. 1..停止事件冒泡 JavaScript代码 //如果提供了事件对象,则这是一个非IE浏览器if ( ...
- JS的事件汇总
一.前言 事件的绑定触发有很多种方法,我们如何选择呢? 很多时候,我们会使用鼠标事件,但是鼠标事件只能在PC设备上使用,当我们需要对不同设备兼容时怎么办呢? 二.正文 1. 事件的几个概念: 事件流: ...
- 前端(十五)—— JavaScript事件:绑定事件方式、事件的冒泡和默认事件、鼠标事件、键盘事件、表单 事件、文档事件、图片事件、页面事件
JS事件:绑定事件方式.事件的冒泡和默认事件.鼠标事件.键盘事件.表单 事件.文档事件.图片事件.页面事件 一.事件的两种绑定方式 1.on事件绑定方式 document.onclick = func ...
随机推荐
- 机器学习-随机梯度下降(Stochastic gradient descent)和 批量梯度下降(Batch gradient descent )
梯度下降(GD)是最小化风险函数.损失函数的一种常用方法,随机梯度下降和批量梯度下降是两种迭代求解思路,下面从公式和实现的角度对两者进行分析,如有哪个方面写的不对,希望网友纠正. 下面的h(x)是要拟 ...
- Android常规布局(网络异常布局、空数据布局,未登录布局等)切换工具类,Layout切换
本人已整理好发布到github,已优化. github地址:https://github.com/buhuiming/StatusLayoutManager 使用:compile 'com.bhm.s ...
- Ubuntu14.04环境下java web运行环境搭建
1.jdk安装 将下载好的安装包上传至/home目录解压 tar -zxvf jdk-8u71-linux-x64.tar.gz 执行 vim /etc/profile 在末尾添加java环境变量(J ...
- centos7 安装后,意外出现Please make your choice from above ['q' to quit | 'c' to continue | 'r' to refresh]
安装完成centos7后出现如下提示: Initial setup of CentOS Linux 7 (core) 1) [x] Creat user 2) [!] License informat ...
- 基于ant design form的二次封装
// standardForm.js import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; ...
- 第3节 mapreduce高级:12、mapreduce相关的参数调整
5.1 多job串联 一个稍复杂点的处理逻辑往往需要多个mapreduce程序串联处理,多job的串联可以借助mapreduce框架的JobControl实现 示例代码: ControlledJob ...
- 第2节 mapreduce深入学习:8、手机流量汇总求和
第2节 mapreduce深入学习:8.手机流量汇总求和 例子:MapReduce综合练习之上网流量统计. 数据格式参见资料夹 需求一:统计求和 统计每个手机号的上行流量总和,下行流量总和,上行总流量 ...
- python pandas读写excel
import pandas as pd import numpy as np df = pd.read_csv("result.csv") # csv # df = pd.read ...
- 三、spring中高级装配(1)
大概看了一下第三章的内容,我从项目中仔细寻找,始终没有发现哪里有这种配置,但是看完觉得spring还有这么牛B的功能啊,spring的厉害之处,这种设计程序的思想,很让我感慨... 一.环境与prof ...
- 计算几何——认识基本object:点、线、面 。
认识基本object:点.线.面 一.点 点用P(x, y)来表示:如: typedef pair<double, double> _pair; _pair point[MAXN]; 二 ...