源码分析需要知道的几个知识点
Vue源码分析
知识点准备
- 1.将为数组转为真数组 ( [].slice.call(this)
- 2.nodeType: 得到的节点类型 (获取属性,必须是元素节点才有) ---》 必须直到nodeType为1
-
- Object.defineProperty(obj, propertypeName, {}) 给对象属性添加属性
-
- Object.keys(obj) : 看到对象自身可枚举属性组成的数组 Vue不支持IE8 ----》IE8 不支持Object.defineProperty
-
- obj.hasOwnProperty(prop): 判断属性是否是自身的属性
-
- DocunmentFragment: 文档碎片化
<div id="test">森果科技</div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<ul id="fragment_test">
<li>test1</li>
<li>test2</li>
<li>test3</li>
<li>test4</li>
<li>test5</li>
</ul>
js部分
// 1.将为数组转为真数组 ( [].slice.call(this)
const lis = document.getElementsByTagName('li') // lis是为数组
console.log(lis instanceof Array, lis[1].innerHTML, lis.forEach)
// es5语法
// call 的作用,让函数成为指定元素的调用
// this只有在执行的时候才能确定
const lis2 = Array.prototype.slice.call(lis) // 可以转为真的数组,可以使用forEach去遍历数组
console.log(lis instanceof Array, lis[1].innerHTML, lis2.forEach)
// 2.nodeType: 得到的节点类型 (获取属性,必须是元素节点才有) ---》 必须直到nodeType为1
const elementNode = document.getElementById("test") // 元素节点
const atttNode = elementNode.getAttributeNode('id') // 属性节点
const textNode = elementNode.firstChild // 文本节点
console.log(elementNode.nodeType, atttNode.nodeType, textNode.nodeType)
// 3. Object.defineProperty(obj, propertypeName, {}) 给对象属性添加属性
const obj = {
firstName: 'A',
lastName: 'B'
}
// 给Obj添加fullName属性
/**
属性描述符: (数据描述符和访问描述符)
数据描述符
configurable: 是否可以重新定义
enumerable: 是否可以枚举
value: 初始值
writable: 是否可以修改属性值
访问描述符
get: 回调函数,初始其他属性动态计算得到的当前属性值
set: 回调函数,监视当前属性值的变化,更新其他属性
**/
Object.defineProperty(obj, 'fullname', {
get() {
return this.firstName + '-' + this.lastName
},
set(value) {
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
})
console.log(obj.fullname)
obj.firstName = 'C'
obj.lastName = 'D'
console.log(obj.fullname)
obj.fullname = 'E-F'
console.log(obj.firstName, obj.lastName)
Object.defineProperty(obj, 'fullname2', {
configurable: true,
enumerable: false, // 是否可枚举 false不可, true可行
value: 'G-H',
writable: true
})
console.log(obj.fullname2)
obj.fullname2 = 'J-K'
console.log(obj.fullname2) // 不能修改
// 不能重新定义
// Object.defineProperty(obj, 'fullname2', {
// configurable: false,
// enumerable: false,
// value: 'G-H',
// writable: true
// })
// 4. Object.keys(obj) : 看到对象自身可枚举属性组成的数组 Vue不支持IE8 ----》IE8 不支持Object.defineProperty
const objNames = Object.keys(obj)
console.log(objNames) // 这个根据enumerable这个值来判断是否枚举
// 5. obj.hasOwnProperty(prop): 判断属性是否是自身的属性
console.log(obj.hasOwnProperty('fullname'), obj.hasOwnProperty('toString')) // true, false
// 6. DocunmentFragment: 文档碎片化
/**
document: 对应显示的页面,包含n个element,一旦更新document内部的某个元素界面更新
documentFragment: 内存中保存n个element的容器对象(不与界面关联),如果更新fragment中的某个element,界面不会更新(不会变)
//
从多次更新到一次批量更新,做到减少更新界面的次数
<ul id="fragment_test"
<li>test1</li>
<li>test2</li>
<li>test3</li>
<li>test4</li>
<li>test5</li>
</ul>
*/
const ul = document.getElementById('fragment_test')
// 1.创建fragment
const fragment = document.createDocumentFragment()
// 2.取出ul中所有的子节点中所有的li文本 (有一个bug)
let child
while (chilid = ul.firstChild) { //1.先取出ul中的第一个孩子。 2,赋值给child。 3.在判断child是否为真。 4.只有到最后为空才是假的
// 先将child从ul中移除,然后给child添加子节点
fragment.appendChild(chilid) // 1. 将一个节点添加为字节点。2. (一个节点只有一个父亲)
}
// 3.更新fragment中所有li文本
// 得到一个为数组
Array.slice.call(fragment.childNodes.forEach( node => {
// 判断当前节点是否是元素节点 ,是元素节点li
if (node.nodeType === 1) {
node.textContent = '森果科技'
}
}))
// 将fragment插入ul中
ul.appendChild(fragment) // appendChild接收的是一个node类型,然而fragment就是一个node类型。
一份帮助文档,无论多么仔细,都不会帮助主人多敲一行代码!