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
来源: https://www.cnblogs.com/jiebba/p/9663268.html