CSS优先级 link
- CSS 优先规则1: 最近的祖先样式比其他祖先样式优先级高。
- CSS 优先规则2:"直接样式"比"祖先样式"优先级高。
!important
- 提高指定样式规则的应用优先权(优先级)box{color:red !important;}。
- .class #id
!important > 内联样式 > ID 选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签选择器 = 伪元素选择器
就近原则
@import 导入 @import 语句必须出现在内部样式之前,否则文件引入无效
js操作DOM的方法整理
DOM (Document Object Model)文档对象模型
DOM为HTML提供了结构化表示方法,定义了访问和处理文档结构的方法规范。 HTML可以理解为是由DOM节点构成的集合,主要由元素节点、文本节点、属性节点三部分构成
js操作DOM的方法
js操作DOM主要是对于元素节点,文本节点和属性节点的增删改查
js 新增删除修改查找节点
var newNode = document.createElement('div')
// 创建一个新的元素节点
var newNode = document.createTextNode("hello world!")
// 创建一个文本节点
var mycloneNode = newNode.cloneNode(true)
// 克隆一个节点
document.createDocumentFragment();
// 创建文档对象变量,主要用来临时存储节点,大量操纵dom时性能有很大的提升
// 但是不太清楚为什么
var deleteNode = parentNode.removeChild(item)
// 删除指定的节点并且返回
// 修改节点
node.appendChild(newNode);// 在指定元素后面新增子节点
parentNode.insertBefore(newNode,node); //在parentNode的子节点newNode前面插入newNode节点
parentNode.replaceChild(newNode,oldNode);//用oldNode节点替换parentNode的子节点newNode
// 查找结点 指点id
var parentNode = document.getElementById('ids')
// 指定的class
var classNodes = document.getElementsByClassName('classes')
// 指定的tag
var tagNodes = document.getElementsByTagName('tags')
var Names = document.getElementsByTagName('name')
// selector
// 返回第一个带有指定id或者class的元素
var list = document.querySelector('#wrapper')
var lists = document.querySelectorAll('.wrapper')
通过节点之间的关系查找元素节点,dom节点的关系图以及操作方法如下 link
查找元素节点的方法
element.parentNode //返回该节点的父节点,每个节点都会有一个父节点,Element的父节点可能是Element,Document或DocumentFragment;
element.parentElement //返回父节点,只有父节点为元素节点时返回,否则返回null
element.children //返回所有元素子节点的集合,仅包含元素节点
element.childNodes //返回当前元素所有的子节点,包含元素节点,文本节点,属性节点。(注释、空格、换行等也会被当作一个节点)
element.firstChild //返回当前元素的第一个子节点,该子节点可以是任意节点,如果没有则返回null
element.firstElementChild //返回当前元素的第一个子节点,该子节点只可以是元素节点,如果没有则返回null
element.lastChild 第一个子元素节点(标签) //返回当前元素的最后一个子节点,该子节点可以是任意节点,如果没有则返回null
element.lastElementChild
(包括标签、空文档和换行节点)
//返回当前元素的最后一个子节点,该子节点只可以是元素节点,如果没有则返回null
element.previousSibling //返回该节点的前一个兄弟节点
element.previousElementSibling //返回该节点的前一个元素兄弟节点
element.nextSibling //返回该节点的后一个兄弟节点
element.nextElementSibling //返回该节点的后一个元素兄弟节点
修改元素属性
key: classList setAttribute node.style.color
var node =document.getElementById("list");
// classList方法操作元素的class属性
node.classList.add("test"); //给node节点添加一个class
node.classList.remove("test");//删除node节点名为test的class
node.classList.replace("old-class","new-class");//替换node节点的class
var hasClass = node.classList.contains("test");//node节点是否存在给定的class,如果存在则返回 true,否则返回 false。
node.classList.toggle("test")//如果节点已经存在给定的class则删除,如果没有则添加
node.setAttribute("id","123");//给node节点设置id=123
var id = node.getAttribute("id");//获取node节点的id属性值
var hasAttr =node.hasAttribute("id");//判断node节点是否存在id属性
// dataset方法获取元素的data- 属性值
var dataId=node.dataset.id; //获取node节点的data-id属性值
var dataName=node.dataset.userName;//类似data-user-name属性必须使用驼峰式来访问
'id' in node.dataset // 判断node节点是否有data-id属性
// style方法修改元素的样式
node.style.color = 'red'; //设置color样式
node.style.setProperty('font-size', '16px'); //设置font-size样式
node.style.removeProperty('color'); //移除color属性
获取元素类型
element.nodeType //返回元素的节点类型 1元素节点 2属性节点 3文本节点 4CDATA节点 5实体引用名称节点 6实体名称节点 7处理指令节点 8注释节点 9文档节点 10文档类型节点 11文档片段节点 12DTD声明节
获取当前节点的文本值
element.innerHtml //返回当前节点的所有文本包含html
element.innerText //返回当前节点及所有后代节点的文本值,不包含html
实例
比如寻找到
- 一方面我们可以使用querySelectorall
- 它竟然还支持链式写法,惊呆了
- 我猜它就支持因为符合逻辑
<!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>
</head>
<body>
<div class="box">111</div>
<div class="box">2222</div>
<div id="btn">
<!--标签+enter也算是标签里面有文本内容了-->
aaaa
<p>111</p>
bbb
<p>2222</p>
ccc
</div>
aaaaaaaaaaaaaaa
<div name="xxx"></div>
</body>
<script>
console.log(1)
var res7=document.getElementById("btn").firstChild
console.log(res7)
console.log(1)
var box3=document.getElementById("btn") //通过id找,推荐用(做js添加效果时的查找依据)
var res1=document.querySelectorAll("#btn p")
console.log(box3)
console.log(res1)
</script>
</html>
js的原型 设计模型 JS 封装多态以及继承
js的原型 设计模式
- 首先我们应该明白什么是设计模式,以及他与js原型的关系
- 设计模式 我听到了一时语塞,那不就是js的原型 new object.create() extends
组合继承
function Parent(value){
this.val = value
}
Parent.prototype.getValue = function(){
console.log(this.val)
}
function Child(value){
Parent.call(this,value)
}
Child.prototype = new Parent()
child = new Child(1)
child.getValue()
console.log(child instanceof Parent)
以上继承的核心就是在子类的构造函数中通过 Parent.call(this) 继承父类的属性,然后改变子类的原型为 new Parent() 来继承父类的函数
- 继承父类函数的时候调用了父类构造函数,导致子类的原型上多了不需要的父类属性,存在内存上的浪费
寄生组合继承
function Parent(value) {
this.val = value
}
Parent.prototype.getValue = function() {
console.log(this.val)
}
function Child(value) {
Parent.call(this, value)
}
Child.prototype = Object.create(Parent.prototype, {
constructor: {
value: Child,
enumerable: false,
writable: true,
configurable: true
}
})
const child = new Child(1)
child.getValue() // 1
child instanceof Parent // true
class继承
super 就是利用子类调用super继承父类的this对象,然后再加工。
class Parent {
constructor(value) {
this.val = value
}
getValue() {
console.log(this.val)
}
}
class Child extends Parent {
constructor(value) {
super(value)
this.val = value
}
}
let child = new Child(1)
child.getValue() // 1
child instanceof Parent // true
ES5,ES6继承的区别
ES6 继承的子类需要调用 super() 才能拿到子类,ES5 的话是通过 apply 这种绑定的方式
js设计模型 面向对象
继承,封装,多态,抽象
继承
深拷贝,浅拷贝,object.create,new
封装
对象的属性外部是可读可写的 如何实现封装
局部变量+变量
多态
其实不害怕你说错,但是害怕你不敢说
同一个父类继承出来的子类各有各的形态
js设计模式
- 工厂模式
- 单例模式
- 模块模式
- 代理模式
- 发布订阅模式
easy-demo
var list = {
arr: [],
subscribe: function(fn) {
this.arr.push(fn);
},
notify: function() {
this.arr.forEach(fn => fn());
}
};
var fn1 = function() {
console.log(1)
}
var fn2 = function() {
console.log(2)
}
list.subscribe(fn1);
list.subscribe(fn2);
list.notify();
js map forEach
我只能说之前答的跟是一样
我们首先来看一看MDN上对Map和ForEach的定义:
forEach(): 针对每一个元素执行提供的函数(executes a provided function once for each array element)。
map(): 创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来(creates a new array with the results of calling a provided function on every element in the calling array)。
到底有什么区别呢?forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
因为forEach()会改变原始的数组的值,而map()会返回一个全新的数组,原本的数组不受到影响。
forEach适合于你并不打算改变数据的时候,而只是想用数据做一些事情
map()适用于你要改变数据值的时候。不仅仅在于它更快,而且返回一个新的数组。这样的优点在于你可以使用复合(composition)(map(), filter(), reduce()等组合使用)来玩出更多的花样。
能用forEach()做到的,map()同样可以。反过来也是如此。
map()会分配内存空间存储新数组并返回,forEach()不会返回数据。
- foreach处理普通数组:把原数组拷贝一个后,再从中拿出每个元素,我们使用foreach对这些元素进行处理,并不是对原数组的处理,而只是对一个拷贝的处理,所以不管我们怎么改变其值,原数组的值是不会改变的。
js sort排序
sort 是数组的方法 ((a,b) => a-b)
vue的diff算法
一个DOM节点主要包含 标签名 属性名 子元素
Vue 使用JS对象构建virtual DOM的DOM副本。原因是我们使用JS直接操作DOM的计算成本很高
虚拟DOM是一个轻量级的JS对象,他由渲染函数创建。包含元素 具有的数据,propattr等属性 以及一个数组。数组放置的是该节点的子级。子级包含上述对象。同时具有子级。直至构建完整的DOM树
如果需要更新列表项,我们可以借助前面提到的响应性在 JavaScript 中进行。我们将更改应用至 JavaScript 副本、虚拟 DOM 中,然后在它们和实际 DOM 之间执行 diff
diff算法是通过调用patch函数来实现的。我们将节点分为VNode,oldVNode.同时只会在同层级进行比较
当数据改变时,notif通知所有订阅者。订阅者调用patch给真实DOM打补丁。VNode 和 OldVNode 节点进行比较。节点不同直接替代。相同的话比较子节点。oldVnode vnode 分别设置了头尾指针,通过四种方法进行比较。有key时,利用有key时: Diff算法就可以t通过唯一的标识key正确的识别此节点,复用key不变的节点,找到正确的位置区只插入需要更新的节点。
然后层层比较,直到更新完毕