Vue(原理分析)_准备篇

一、前言                                                             

  1、[].slice.call(lis)将伪数组转化为真数组

  2、node.nodeType: 得到节点类型

  3、Object.defineProperty(obj, propName, {}): 给对象添加修改属性

  4、Object.keys(obj)

  5、DocumentFragment: 文档碎片(高效批量更新多个节点)

二、主要内容                                                          

1、[].slice.call(lis)将伪数组转化为真数组

  (1)官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

  (2)例子:在页面中通过标签名获取到的元素并不是一个真正的数组,

    <ul id="fragment_test">
        <li>test1</li>
        <li>test2</li>
        <li>test3</li>
    </ul>
    <script type="text/javascript">
        //1.[].slice.call(this) 根据伪数组生成对应的真数组
        const lis = document.getElementsByTagName("li")
        console.log(lis)//是一个特别的对象,有下标,有长度
    </script>

  打印出结果如下:这只是一个对象,并且这个对象里面包含下标,长度,看起来很像一个数组

       

  (3)将伪数组转化为数组

        //1.[].slice.call(this) 根据伪数组生成对应的真数组
        const lis = document.getElementsByTagName("li")
        console.log(lis)//是一个特别的对象,有下标,有长度
        console.log(lis instanceof Object, lis instanceof Array)//true false
        //数组的slice()截取数组中指定部分的元素,生成一个新的数组,
        const lis2 = Array.prototype.slice.call(lis)
        console.log(lis2 instanceof Object, lis2 instanceof Array) //true  true

2、node.nodeType: 得到节点类型

  (1)官网:https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeType

  (2)

 //2. node.nodeType:得到节点类型
        const elementNode = document.getElementById('test')
        const attrNode = elementNode.getAttributeNode('id')  //得到属性
        const textNode = elementNode.firstChild //得到文本
        console.log(elementNode.nodeType, attrNode.nodeType, textNode.nodeType)

3、Object.defineProperty(obj, propName, {}): 给对象添加修改属性(vue的数据代理中用到了这个原理)

  (1)官网:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

  (2)defineProperty里面的存取描述符get()和set()函数用来监听和读取数据的变化。

    const obj = {
            firstName:'A',
            lastName:'B'
        }

        //给对象添加属性
        Object.defineProperty(obj, 'fullName', {
            //属性描述符
            /*configurable:false
              enumerable :false
              value:属性值
              writable:

            */
            //存取描述符:
            /*
            get:提供getter方法,
            set:监听属性值的改变

            */

            get(){//当读取此属性时自动调用,将函数返回值作为属性值
                return this.firstName +"-" + this.lastName
            },
            //当修改了对象的当前属性时自动调用,监视当前属性值的变化,修改相关属性
            set(value){
                const names = value.split('-')
                this.firstName = names[0]
                this.lastName = names[1]
            }

        })

        console.log(obj.fullName)//A-B
        obj.fullName='C-D' //修改属性值
        console.log(obj.firstName, obj.lastName) //监听到fullName属性发生变化,就会立即调用set方法

4、Object.keys(obj): 得到对象自身可枚举的属性名的数组(在数据代理的时候也有用到)

  (1)官网:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

 const obj = {
            firstName:'A',
            lastName:'B'
        }


        const names = Object.keys(obj)
        console.log(names)//[firstName, lastName]

5、DocumentFragment: 文档碎片(高效批量更新多个节点)

  (1)官网:https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment

  (2)举例:这个技术在vue中运用非常多,当我们需要比如下面我们需要将li标签里面的文字全部替换。按照传统的方式,需要获取到每个li标签,然后遍历每个li标签,最后操作每个li标签,如果页面中有无数个li, 用这种方式会频繁操作DOM,效率很低

  (3)用文档碎片:来避免页面多次更新。文档碎片相当于是存在内存中的一个虚拟的DOM容器, 更新每个li的时候先让页面先不动,页面所有li都更新完了,然后在一次性批量操作页面。

<body>
    
    <ul id="fragment_test">
        <li>test1</li>
        <li>test2</li>
        <li>test3</li>
    </ul>
    <script type="text/javascript">
        //1.创建fragment
        var ul = document.getElementById('fragment_test')
        var fragment = document.createDocumentFragment()
        //2.取出ul中的所有子节点保存到fragment中
        let child;
        while(child = ul.firstChild){
            
                fragment.appendChild(child)
            console.log(ul.firstChild)
        }
        //3.更新fragment中所有li的文本
        let lis = fragment.children;//得到的是一个伪数组
        let lis2 = Array.prototype.slice.call(lis)
        for(var i=0; i<lis2.length; i++){
            if(lis2[i].nodeType===1){//如果为元素节点
            lis2[i].textContent='hello'
            }
        }
        //4.将fragment插入ul
        ul.appendChild(fragment)


    </script>

三、总结                                                                 

虽然现在走得很慢,但不会一直这么慢
原文地址:https://www.cnblogs.com/xxm980617/p/10889516.html