day26Vue相关内容及深拷贝和浅拷贝

Vue相关内容

概述:

vue是前端的一个js库,是一个MVVM模式的框架

MVVM概述

 

 

Vue相关内容

双向数据绑定:视图变化数据也会变化,数据变化视图也会变化

通过v-model指令代码实现

   <script src="./myvue.js"></script>
</head>
<body>
    <div id="app">
    <!-- 视图渲染的地方 -->
         <input type="text" v-model="msg">
         <!-- 插值表达式 可以获取data里面的数据 -->
       {{msg}}
    </div>
    <script>
        //这个vue.js文件导出的是一个构造函数vue
        let vm=new Vue({
            el:'#app',//需要将视图挂载的位置
            data:{//放数据
              msg:'你好'
            }
        })
        console.log(vm);
    </script>
</body>
</html>

原生实现vue2的双向数据绑定

流程

获取所有的input框

过滤有属性v-model的input

遍历所有加了v-model属性的input

找v-model属性的属性值 对应data里面的数据值

给对应的input添加监听 监听input的value变化  设置给对应的data

使用Object.defineProperty的set来监听数据的变化

在数据变化的时候重新渲染对应的input的值

渲染应该解析对应{{}}  找到对应的属性名 进行替换

class Vue{
    constructor(option){
        this.el = document.querySelector(option.el) //找到对应渲染的元素
        this.data = option.data
        //用于Object.defineProperty的使用
        this.model = Object.assign({},option.data)
        //拿到传入的元素的里面显示的所有的内容
        this.template = document.querySelector(option.el).innerHTML
        this.render()
        this. _obServer()
    }
    //观察者 观察data的数据变化
    _obServer(){
        let _this = this
        //遍历所有的属性
        for(let key in this.data){
            Object.defineProperty(this.data,key,{
                get(){
                    return _this.model[key]
                },
                set(v){
                    _this.model[key] = v
                    //渲染
                    _this.render()
                }
            })
        }
    }
    //渲染的方法
    render(){
        let _this = this
        //找到所有的{{}} 括起来的内容 进行替换
        this.el.innerHTML = this.template.replace(/\{\{\w+\}\}/g,(str)=>{
            //str {{msg}}
            let propertyName = str.substring(2,str.length-2).trim() //msg
            return _this.data[propertyName]
        })
        //找到对应el里面的input框
        Array.from(this.el.querySelectorAll('input'))
        .filter((input)=>{
            //找到input中是否具备v-model属性
            return input.getAttribute('v-model')
        })
        .forEach((input)=>{
            let _this = this
            //遍历所有的input框 (都是有v-model属性的)
            //获取对应的v-model的属性值
            let propertyName = input.getAttribute('v-model').trim()
            //给这个input添加onchange事件或者是oninput
            input.oninput = function(){
                //获取他的value 设置给对应的data里面的属性
                _this.data[propertyName] = this.value
            }
            //将对应的input的value 进行设置(对应的data里面属性的数据)
            input.value = this.data[propertyName]
        })
    }
}

深拷贝和浅拷贝

浅拷贝 :只拷贝第一层的值 其他层拷贝的是地址 

实现浅拷贝的方式:

Object.assign

Array.prototype.concat (数组)

Array.prototype.slice(数组)

. . . 扩展运算符

 var obj = {
            name: 'haha',
            arr: [1, 2, 3, 4]
        }
        var copyObj = Object.assign({}, obj)
        console.log(copyObj == obj);
        console.log(copyObj.arr == obj.arr);
        console.log(copyObj.name == obj.name);
        copyObj.arr.push(5)
        console.log(obj.arr)
        //数组的浅拷贝arr
        var arr = [1, 2, 3]
        var copyArr1 = [].concat(arr)//连接
        console.log(copyArr1 == arr);
        console.log(copyArr1[0] == arr[0]);
        let arr1 = [
            {
                name: '11',
                 age: '18'
            }, 
            {
                name: '22', 
                age: '25'
            }

        ]
        let copyArr2=arr1.slice()//截取
        console.log(copyArr2==arr1);
        console.log(copyArr2[1]==arr1[1]);
        let copyArr3=[...arr1]//扩展运算符
        console.log(copyArr3==arr1);
        console.log(copyArr3[1]==arr1[1]);
        console.log(copyArr3);
        //函数实现浅拷贝
        function copy(obj) {
            let constructor=obj.constructor
            let copyObj=new constructor()
            for(let key in obj){
                copyObj[key]=obj[key]

            }
            return copyObj
        }
        var copyArr4=copy(arr1)
        console.log(copyArr4==arr1);
        console.log(copyArr4[0]==arr1[0]);
        //第三方插件lodash.js  (_.clone)

</script>

深拷贝:拷贝所有内容,值相同但是其他引用地址不一样,两者互不影响

序列化和反序列化 (JSON.stringify JSON.parse)

使用第三方工具 lodash.js (_.cloneDeep)

自定义函数实现深拷贝(递归实现)

//递归实现深拷贝
        function deepClone(obj) {
            if (!(typeof obj == 'object' && obj)) {
                return obj
            }

            let copyObj = obj instanceof Array ? [] : {}

            for (let key in obj) {
                copyObj[key] = deepClone(obj[key])
            }

            return copyObj
        }

Vue原理介绍

虚拟dom

虚拟的dom对象,存在内存中,虚拟dom的形成是抽取对应的实体dom,模仿实体don创建的对象,跟实体的dom对象没有直接关系,因为直接操作实体dom会造成大量的重绘和回流,导致页面渲染次数增加,渲染的速度变慢,所以为了解决这个问题,vue先操作对应的虚拟的dom,再通过虚拟dom渲染实体dom(只渲染一次)

 

diff算法

比对虚拟dom内容的改变,通过对应的节点进行比对(元素节点,属性节点,文本节点)

 

节点对比流程

节点对比流程先比key(下标不能作为key),比对对应的节点名、属性名、子节点,然后通过patch方法进行分类比较,然后进行渲染(模板引擎mustache)

 

相关优化

生命周期优化(预加载(挂载的时候)、缓存(组件销毁的时候)、回收资源(组件销毁的时候))
打包优化(webpack/glup(文件流))

posted @ 2022-11-04 20:06  xiaomingff  阅读(230)  评论(0)    收藏  举报