day26 Vue相关内容及深拷贝和浅拷贝

Vue相关内容

概述 :

Vue是前端的一个Js库 ( 诞生于2015年 , 兴起于2016年 , 尤雨溪写的(目前是阿里巴巴在维护) ) , vue是MVVM模式的框架 .

MVVM概述 :

  • model 数据

  • view 视图

  • viewmodel 视图模型 ( 管理 , 数据驱动视图 )

Vue的双向数据绑定

  • 视图变化 --- 数据也会变化

  • 数据变化 --- 视图也会变化

双向数据绑定 运用在表单标签 ( input )

代码实现 ( v-model指令 )
复制代码
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="./lib/vue.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>
复制代码

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

流程 :

  • 获取所有的input框

  • 过滤出有v-model属性的input框并返回

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

  • 找这个v-model属性的值 , 设置给data里面的msg

  • 给input添加监听 , 监听input的value变化 设置给data

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

  • 在数据变化的时候 , 重新渲染input的值

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

代码实现

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
    <div class="box">
    <input type="text" v-model="msg">
    {{msg}}
    </div>
    <script>
    class Vue {
        constructor(option) {
            //获取需要渲染的元素
            this.el = document.querySelector(option.el)
               //获取要渲染的数据
            this.data = option.data
            //拷贝一个渲染的数据,以便后续defineProerty的使用
            this.model = Object.assign({}, option.data)
            //拿到页面上的显示的内容,后面需要做替换
            this.template = this.el.innerHTML
            this.render()
            this._obServer()
        }
        //观察数据的变化
        _obServer() {
            let self = this
            //遍历所有数据的属性
            for (let key in this.data) {
                // 定义属性的get和set方法(需定义的对象,需定义对象的属性,处理方法)
                Object.defineProperty(this.data, key, {
                //获取就直接返回数据的属性
                get() {
                   return self.model[key]
                },
                //把数据的属性赋给传进来的对象
                set(v) {
                    self.model[key] = v
                    // 渲染
                    self.render()
                }
                 })
             }
         }
         // 渲染的方法
         render() {
             let self = this
             // 获得页面上的数据并进行替换({{msg}}换成msg),然后再渲染到页面上 
             this.el.innerHTML = this.template.replace(/\{\{\w+\}\}/g,(str)=> {
                 let property = str.substring(2, str.length - 2).trim()
                 return self.data[property]
             })
             // 获取页面上的input框,再过滤除带有v-model属性的input,并把它们返回出去
             Array.from(this.el.querySelectorAll('input')).filter((item) => {
                return item.getAttribute('v-model')
             }).forEach((item) => {
                    let self = this
                    //遍历带有v-model属性的input框,再给他们设置oninput事件
                    let attributeName = item.getAttribute('v-model')
                    item.oninput = function () {
                        //获取input的value并设置给data里面的属性msg
                        self.data[attributeName] = this.value
                    }
                    //将input的value设置给data的属性msg
                    item.value = this.data[attributeName]
                 })
              }
         }
         //调用vue方法
         new Vue({
            el: '.box',
            data: {
               msg: 'aloha'
            }
         })
    </script>
</body>
</html>
复制代码

深拷贝和浅拷贝

浅拷贝

概述 :

第一层拷贝它的值 , 第二层及之后拷贝的都是地址 , 相当于你拷贝的是一个快捷方式 , 这个快捷方式跟原本的不是一个 , 但里面的内容是一样的

  • Object.assign 实现浅拷贝

let obj = {name:'jack',list:[1,2,3],params:{'ok'}}
let copyObj = Object.assign({},obj)
console.log(obj == copyObj) //false
console.log(obj.list==copyObj.list)//true
  • Array.prototype.concat ( 数组的浅拷贝 )
//数组的浅拷贝 concat
let arr = [1, 3, 5, 7, { username: 'alex' }]
let copyArr = [].concat(arr)
console.log(arr == copyArr) //false
console.log(arr.username == copyArr.username) //true
  • Array.prototype.slice ( 数组的浅拷贝 )

 

// 3.数组的浅拷贝 slice
let copyArr1 = arr.slice() //截取全部
console.log(arr == copyArr1) //false
console.log(arr.username == copyArr1.username) //true
  • 扩展运算符
console.log('------扩展运算符--------');
let copyArr2 = [...arr]
console.log(arr == copyArr2) //false
console.log(arr.username == copyArr2.username) //true
  • 自定义函数实现浅拷贝
复制代码
console.log('------函数--------');
function copy(obj) {
    //先用一个变量接收obj的构造函数
    let constructor = obj.constructor
    //再拷贝一下这个变量
    let copyObj1 = new constructor()
    //变量传入的obj
    for (let key in obj) {
        //拷贝的obj1里的地址=传入的obj的地址
        copyObj1[key] = obj[key]
    }
    //返回拷贝的obj1
    return copyObj1
}
let copyArr4 = copy(arr)
console.log(arr == copyArr4) //false
console.log(arr.username == copyArr4.username) //true
let copyObj2 = copy(obj)
console.log(obj == copyObj2) //false
console.log(obj.family == copyObj2.family) //true
复制代码
  • _.clone () ( 第三方工具 ( lodash .js ) )
console.log('------lodash--------');
let copyArr3 = _.clone(arr)
console.log(arr == copyArr3) //false
console.log(arr.username == copyArr3.username) //true

深拷贝

概述 :

深拷贝是拷贝所有的内容 , 这两个内容相同的点只有值是一样的 , 引用地址都不一样

深拷贝的实现
  • 序列化和反序列化 ( JSON.stringify , JSON.parse )

复制代码
// 1.序列化和反序列化
let obj = {
    list: [{
        name: '西瓜'
    }, {
        name: '椪柑'
    }, {
        name: '猕猴桃'
    }],
    price: 20,
    user: {
        userName: '张三'
    }
}
let copyObj = JSON.parse(JSON.stringify(obj))
console.log('-------序列化和反序列化---------')
console.log(obj == copyObj)
console.log(obj.list == copyObj.list)
console.log(obj.price == copyObj.price)
console.log(obj.user == copyObj.user)
复制代码
  • _.cloneDeep ( 使用第三方工具 lodash.js )
复制代码
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script>
    let copyObj2 = _.cloneDeep(obj)
    console.log('-------lodash---------')
    console.log(obj == copyObj2)
    console.log(obj.list == copyObj2.list)
    console.log(obj.price == copyObj2.price)
    console.log(obj.user == copyObj2.user)
</script>
复制代码
  • 自定义函数实现深拷贝 ( 递归实现 )
复制代码
function cloneDeep(obj) {
    //判断传入的obj是否为对象或者空,不是就返回值
    if (!(typeof obj == 'object' && obj)) {
        return obj
    }
    // 判断传入的obj是对象还是数组
    let copyObj1 = obj instanceof Array ? [] : {}
    // 遍历
    for (let key in obj) {
        copyObj1[key] = cloneDeep(obj[key])
    }
    return copyObj1
}
let copyObj1 = cloneDeep(obj)
console.log(copyObj1)
console.log(obj == copyObj1) //false
console.log(obj.list == copyObj1.list) //false
console.log(obj.price == copyObj1.price) //true
console.log(obj.user == copyObj1.user) //false
复制代码

Vue原理介绍

虚拟dom

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

diff算法 ( 可用于性能优化 )

是用于比对的算法 , 它是比对虚拟dom内容的改变 , 然后通过这个改变来控制实体dom的内容变化

通过节点来进行对比的 ( 元素节点 , 属性节点 , 文本节点 )

节点比对流程

节点比对流程先比key ( 下标不能作为key ( 下标会变 ) ) , 然后比节点名 , 再比属性名 , 比对子节点

vue中有个patch的方法来帮助我们进行分类比较 , 比较完就进行渲染 ( 模板引擎mustache )

相关优化

生命周期优化 ( 预编译(挂载的时候) 、缓存(组件销毁的时候) 、回收资源 (组件销毁的时候))

打包优化 ( webpack / glup(核心 : 文件流))

posted @   邱你咋滴  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示