美文网首页web前端
vue源码分析(一):准备知识

vue源码分析(一):准备知识

作者: 姜治宇 | 来源:发表于2020-08-31 16:17 被阅读0次

1、节点类型

常用节点一共分为三种,分别是元素节点(element)、属性节点(attribute)、文本节点(text)。

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="test">

    </div>
</body>
</html>
<script>
    const elementNode = document.getElementById('test')
    const attrNode = elementNode.getAttributeNode('id')
    const textNode = elementNode.firstChild

    console.log(elementNode.nodeType) // 1 元素节点
    console.log(attrNode.nodeType) // 2 元素节点
    console.log(textNode.nodeType) // 3 文本节点
</script>

2、Object.defineProperty

给对象添加属性:
Object.defineProperty(obj,prop,{descriptor})
obj:要定义属性的对象
prop:要定义或修改的属性名称
descriptor:属性的描述信息

属性描述符:

1)configurable: (属性)是否可重新定义
2)enumerable: (属性)是否可枚举
3)value: (属性)对应的初始值
4)writable: (属性)是否可被修改

let obj = {
    firstName:'A',
    lastName:'B'

}
Object.defineProperty(obj,'fullName',{
    configurable: true, // 可以重新定义属性
    enumerable:false,// 不能枚举属性
    value:'G-H',
    writable:false // 不能修改属性
})
//writable
console.log(obj.fullName) //value G-H
obj.fullName = 'J-K'//修改了属性值
console.log(obj.fullName)//仍旧是G-H,不可修改

//configurable
Object.defineProperty(obj,'fullName',{
    enumerable:false,
    value:'M-N',
}) //如果configurable设置为false,则会抛异常-->TypeError: Cannot redefine property: fullName

//enumerable
const names = Object.keys(obj)
console.log(names) //[ 'firstName', 'lastName' ],fullName属性无法枚举出来

访问描述符:

5)get: 回调函数,根据其他相关的属性,动态计算得到当前属性值
6)set: 回调函数,监视当前属性值的变化,更新其他相关属性

    Object.defineProperty(obj,'fullName',{
        get(){
            return this.firstName + '-' + this.lastName
        },
        set(val){
            const names = val.split('-')
            this.firstName = names[0]
            this.lastName = names[1]
        }
    })
    //get
    console.log(obj.fullName) // A-B
    obj.firstName = 'C'
    obj.lastName = 'D'
    console.log(obj.fullName) // C-D get动态获取值
    //set
    obj.fullName = 'E-F'
    console.log(obj.firstName,obj.lastName) //E F

3、obj.hasOwnProperty(prop)

判断对象自身属性中,是否具有指定的属性

var obj = {
    firstName: 'A'
}
console.log(obj.hasOwnProperty('firstName')) // true
console.log(obj.hasOwnProperty('toString')) // false

4、文档碎片DocumentFragment

文档碎片的api可以参考这篇文档:
https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment
document和fragment的区别:
document:对应显示的页面,包含n个element,一旦更新了document内部的某个元素,整个界面都要更新;
fragment:内存中保存n个element的容器,不与界面关联,如果更新fragment中的某个element,界面不变。
有了文档碎片,我们就可以更为高效的批量更新多个节点了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <ul id="frag">
        <li>test1</li>
        <li>test2</li>
        <li>test3</li>
    </ul>
</div>
</body>
</html>
<script>
    //document:对应显示的页面,包含n个element,一旦更新了document内部的某个元素,整个界面都要更新
    //documentFragment:内存中保存n个element的容器,不与界面关联,如果更新fragment中的某个element,界面不变
    const ul = document.getElementById('frag')
    console.log(ul.innerHTML)
    //1.创建fragment
    const fragment = document.createDocumentFragment()
    //2.取出ul中所有子节点,(包含换行等文本子节点)
    let child = null
    while (child = ul.firstChild) { // 一个节点只有一个父亲(节点或隶属document,或隶属fragment,二选一)
        fragment.appendChild(child) // 先将child从document移除,然后放入fragment
    } //每迭代一次,ul中的节点出栈
    console.log(ul.innerHTML) // 空,已经将节点全部转移到fragment中了
    //3.更新fragment中的所有li的内容
    let nodes = [].slice.call(fragment.childNodes)
    nodes.forEach(node => {
        if (node.nodeType === 1) {
            node.textContent = 'hello'
        }
    })
    //4.将fragment插回ul
    ul.appendChild(fragment)
</script>

相关文章

网友评论

    本文标题:vue源码分析(一):准备知识

    本文链接:https://www.haomeiwen.com/subject/xmzusktx.html