做一个简单的笔记 把思路写下来 未来忘了可以回来看看
目录
怎么封装
增
删
改
查
一、怎么封装
什么是封装
- 把复杂的DOM代码,装到函数里,调用的时候用简单的代码就能实现其功能
什么是接口
- 被封装的函数,暴露出来的功能给外部
什么是库
- 把提供给他人用的工具代码叫做库
什么叫API
- 库暴露出来的函数或属性叫API(应用编程接口)
什么是框架
- 当库变得很大,并且需要系统的学习才能看懂时,那么这个库就叫框架,比如Vue/react
怎么封装
-
用命名空间的风格进行封装
-
window.dom是我们提供的全局对象
二、增
1、 dom.create(`<div>hi</div>`) 用于创建节点
dom.create = function (string) { //新建标签元素
// return document.createElement(tagName); //这样不太复合使用要求
const container = document.createElement('template') // 新HTML标签 可以容纳任何元素
container.innerHTML = string.trim(); // trim函数 去掉字符串两边的空格
return container.content.firstChild; // 如果要显示td等元素 必须要这样拿才拿得到
};
2、 dom.after(node,node2) 用于新增弟弟元素
dom.after = function (node, node2) { //新增一个弟弟
node.parentNode.insertBefore(node2, node.nextSibling) //在下一个元素的前面新增一个元素 因为DOM没有这个API,所以反人类式写法
}
3、dom.before(node,node2) 用于新增哥哥元素
dom.before = function (node, node2) { // 新增一个哥哥
node.parentNode.insertBefore(node2, node) // 在node前面新增一个node2元素
}
4、dom.append(parent,child) 用于新增子元素
dom.append = function (parent, node) { // 新增一个儿子
parent.appendChild(node) //给parent元素新增一个儿子
}
5、dom.wrap(`<div></div>`) 用于新增父元素
dom.wrap = function (node, parent) { // 给node元素新增一个父亲
dom.before(node, parent) //先在node前面新增一个哥哥
dom.append(parent, node) //把node元素移动到哥哥里面变成它的儿子
}
三、删
1、dom.remove(node) 用于删除节点
dom.remove = function (node) { // 删除这个元素
node.parentNode.removeChild(node) // 选中node的父亲删除node
return node //返回被删除的node
}
2、dom.empty(parent) 用于删除所有后代
dom.empty = function (node) { // 删除node的所有儿子
// const childNodes = node.childNodes 简写成下面
const {
childNodes
} = node //把node先装进一个变量,因为要遍历
const array = []; // 声明一个空数组因为要返回
/*for (let i = 0; i < childNodes.length; i++) { childNodes.length实时变换要用while循环
dom.remove(childNodes[i]) 删除每一个遍历到的元素
array.push(childNodes[i]) 把每个遍历到的元素添加到空数组里
}*/
let x = node.firstChild
while (x) {
array.push(dom.remove(node.firstChild)) // 删掉第一个儿子,然后把删除的结果添加到空数组
x = node.firstChild // 删完后 第二个儿子变第一个儿子 我们把x再指向第一个儿子
}
return array //返回这个数组
}
四、改
1、dom.attr(node,'title',?) 用于读写属性
dom.attr = function (node, name, value) { //改或者读属性值 {重载}
if (arguments.length === 3) {
node.setAttribute(name, value) // arguments长度等于3 就代表想改
} else if (arguments.length === 2) {
return node.getAttribute(name) // arguments长度等于2 就代表想读,返回这个值就行
}
}
2、dom.text(node,?) 用于读写文本内容
dom.text = function (node, string) { //改或查看文本内容 {适配}
if (arguments.length === 2) {
if ('innerText' in node) {
node.innerText = string // ie
} else {
node.textContent = string // firefox chrome
}
} else if (arguments.length === 1) {
if ('innerText' in node) {
return node.innerText
} else {
return node.textContent
}
}
}
3、dom.html(node,?) 用于读写HTML的内容
dom.html = function (node, string) { //改或查看HTML标签
if (arguments.length === 2) {
node.innerHTML = string
} else if (arguments.length === 1) {
return node.innerHTML
}
}
4、dom.style(node,{color:'red'}) 修改标签的style
dom.style = function (node, name, value) { //添加或查看style属性
if (arguments.length === 3) {
// dom.style(div,'color','red')
node.style[name] = value //把value赋值给name
} else if (arguments.length === 2) {
if (typeof name === 'string') { //如果第二个参数是字符串
// dom.style(div,'color')
return node.style[name] //就返回这个属性名内的属性
} else if (name instanceof Object) { // 如果第二个参数是对象
// dom.style(div,{name: 'value'})
const object = name
for (let key in object) { //遍历这个对象
// key:border / color
// node.style.border = ...
// node.style.color = ...
node.style[key] = object[key] //把参数的属性值添加进去
}
}
}
}
5、dom.class 对标签的class进行操作
dom.class = { // 添加删除查看类名
add(node, className) { //add属性 添加类名
node.classList.add(className)
},
remove(node, className) { // remove属性 删除类名
node.classList.remove(className)
},
has(node, className) { // has属性 查看类名
return node.classList.contains(className) // 记住要有返回值 不然就看了个寂寞
}
}
6、dom.on(node,'click',fn) 用于添加事件监听
dom.on = function (node, eventName, fn) { //添加事件监听
node.addEventListener(eventName, fn)
}
7、dom.off(node,'click',fn) 用于删除事件监听
dom.off = function (node, evertName, fn) { //删除事件监听
node.removeEventListener(evertName, fn)
}
五、查
1、dom.find(选择器,范围) 用于获取标签,或标签们
dom.find = function (selector, scope) { //在一个范围通过选择器找它的儿子
return (scope || document).querySelectorAll(selector)
}
2、dom.parent(node) 用于获取标签的父元素
dom.parent = function (node) {
return node.parentNode
}
3、dom.children(node) 用于获取子元素
dom.children = function (node) {
return node.children
}
4、dom.sibling(node) 用于获取兄弟元素
dom.siblings = function (node) { // 获取兄弟元素
return Array.from(node.parentNode.children).filter(n => n !== node) // 把获取到的父元素的子元素转化为真数组
// 然后调用数组的filter属性筛选出不等于n的其他元素
}
5、dom.next(node) 用于获取弟弟元素
dom.next = function (node) { // 获取下一个兄弟元素
let x = node.nextSibling
while (x && x.nodeType === 3) { // 节点类型等于3 就是文本节点,如果x为文本节点就继续向下寻找直到找到下一个元素节点
x = x.nextSibling
}
return x
}
6、dom.previous(node) 用于获取哥哥
dom.previous = function (node) { // 获取上一个哥哥元素
let x = node.previousSibling
while (x && x.nodeType === 3) { // 思路同上
x = x.previousSibling
}
return x
}
7、dom.each(node,fn) 用于遍历所有节点
dom.each = function (nodeList, fn) { // 遍历一个元素的所有子元素
for (let i = 0; i < nodeList.length; i++) { // for循环遍历
fn.call(null, nodeList[i]) // 手写forEach 遍历每一个nodeList元素
}
}
8、dom.index(node) 用于获取元素在父级元素中的排行
dom.index = function (node) { // 获取node在父元素中排行第几
const list = dom.children(node.parentNode) // 因为直接用node父亲的所有儿子会导致不包含node 所以要用它父元素的所有儿子
let i // 要把let写在for循环外面才能拿到i的值
for (i = 0; i < list.length; i++) { // 遍历node元素的所有儿子
if (list[i] === node) { // 找到自己就退出循环
break
}
}
return i //
}