• 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>

    三、总结                                                                 

    虽然现在走得很慢,但不会一直这么慢
  • 相关阅读:
    js判断background颜色明暗色调,以设置白/黑字体颜色
    js, 树状菜单隐藏显示
    SQL联接 外联接 内联接 完全联接 交叉联接
    zend studio设置utf8
    ul,li设置inline-block缝隙
    Php DOMDocument 中的 formatOutput
    Mysql查询一个表的所有字段名
    将php数组存取到本地文件
    绑定方法和属性
    __slots__ 属性绑定
  • 原文地址:https://www.cnblogs.com/xxm980617/p/10889516.html
Copyright © 2020-2023  润新知