源码分析需要知道的几个知识点

Vue源码分析

知识点准备

  • 1.将为数组转为真数组 ( [].slice.call(this)
  • 2.nodeType: 得到的节点类型 (获取属性,必须是元素节点才有) ---》 必须直到nodeType为1
    1. Object.defineProperty(obj, propertypeName, {}) 给对象属性添加属性
    1. Object.keys(obj) : 看到对象自身可枚举属性组成的数组 Vue不支持IE8 ----》IE8 不支持Object.defineProperty
    1. obj.hasOwnProperty(prop): 判断属性是否是自身的属性
    1. 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类型。
原文地址:https://www.cnblogs.com/yaogengzhu/p/11148279.html