17_Vue底层&深浅拷贝

一、vue响应式使用的底层方法

vue框架

  • vue2.0 : Object.defineProperty()

  • vue3.0 : Proxy

  • 他们的目的都是为了实现响应式

  • 什么是响应式?

    • 我们只需要操作数据,这个框架帮我们操作dom,不推荐我们使用dom操作
    • 响应式:数据的更新会导致视图的更新

二、Object.defineProperty

  • 在对象上定义一个新属性,或修改现有属性
  • 语法:Object.defineProperty(obj, prop, descriptor)
  • obj:要定义属性的对象
  • prop:要定义或修改的属性的名称
  • descriptor:要定义或修改的属性描述符
    • configurable: 属性描述符是否可以改变以及属性是否可以删除, 默认 false
    • enumerable: 属性是否可以for…in循环出来(遍历/枚举),默认false
    • value: 该属性对应的值, 默认 undefined。
    • writable: 属性的值是否可以修改,默认为 false
    • get:默认undefined,需要设置一个函数,当访问该属性时,会调用此函数,不能传参,该函数的返回值会被用作属性的值。 默认为 undefined
    • set:默认undefined,当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined。
configurableenumerablevaluewritablegetset
数据描述符可以可以可以可以不可以
存取描述符可以可以不可以不可以可以
  • 返回值: 被传递给函数的对象

三、实现简单响应式

<body>
  <span></span>
  <script>
    // 需求:实现数据的变化导致界面的更新
    
    // 要监控数据的变化,这个数据必须是对象的属性值
    let data = {};  // data对象里面专门定义和界面有关的属性

    // text属性是和span这个标签相关的属性
    // 只要text属性值变化,span的内容也变化
    Object.defineProperty(data,'text',{
      set:function(val){
        // 发现你在设置data的text属性
        // 我就把你设置的值,用来更新span的内容
        let sp = document.querySelector('span');
        sp.innerHTML = val;
      }
    })

    // 写一个计数器,每一秒,更新span里面的数字
    let num = 0;
    setInterval(()=>{
      num++;
      // 要更新span的界面,其实只要更新data的text属性值
      data.text = num;
    },1000)
  </script>
</body>

四、实现简单双向数据绑定

<body>
  <input type="text" value="sz2209">
  <h3>hello world</h3>
  <script>
    /* 
      双向数据绑定
        == 数据的更新会导致界面的更新
        == 界面的更新会导致数据的更新
    */


    // 双向数据绑定 => 要能监控数据的变化和界面的更新

    // 1 数据的更新会导致界面的更新
    let data = {} ;// data里面记录和界面有关的属性值
    // input的value,h3的innerHTML都受data的banji属性控制
    Object.defineProperty(data,'banji',{
      set:(val)=>{
        // 获取到你要设置的值,赋值给input的value,h3的innerHTML
        document.querySelector('input').value = val;
        document.querySelector('h3').innerHTML = val;
      }
    })

    // 更新数据
    data.banji = 'sz2303'


    // 2 界面的更新会导致数据的更新
    // 通过 input事件和value 监控文本框里面内容的变化
    document.querySelector('input').oninput  = function(){
      // 界面更新,获取界面的表单的value赋值给data.banji
      data.banji = this.value;
      // 事件处理函数中的this就是事件源
    }
  </script>
</body>

五、Proxy 创建对象代理

  • Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)
  • 语法:const p = new Proxy(target, handler)
  • 参数
    • target:使用 Proxy 包装的目标对象
    • handler:是一个成员值是函数的对象,定义各种操作对象属性时调用的函数,常见有:
      • has:in 操作符的捕捉器
      • get:属性读取操作的捕捉器
        • 第一个参数:目标对象
        • 第二个参数:要操作的属性名
      • set:属性设置操作的捕捉器
        • 第一个参数:目标对象
        • 第二个参数:要操作的属性名
        • 第三个参数:要设置额属性值
      • deleteProperty:delete 操作符的捕捉器
      • construct:new 操作符的捕捉器
      • apply:函数调用操作的捕捉器
        • 第一个参数:目标函数
        • 第二个参数: 函数中的this
        • 第三个参数:函数的实参集合

六、hasOwnproperty识别自身属性

class Person{
  constructor(){
    this.name = "lucy";
    this.age = 12
  }
  sayHi(){
    console.log('hello world')
  }
}

let p1 = new Person()
// in运算符(属性名 in 对象)
// 情况1:对象自身属性
"age" in p1//true

// 情况2:对象继承的属性
"sayHi" in p1 //true
// 总结:in运算符 不仅能识别对象自身的属性 也能识别继承的属性

// hasOwnProperty 只能识别对象自身的属性
p1.hasOwnProperty("age")//true
p1.hasOwnProperty("sayHi")//  false,p1 本身没有toString属性

七、深拷贝和浅拷贝

浅拷贝

  • 创建一个新对象,这个对象有着原始独享属性的一份精确拷贝,如果属性是基本数据类型,拷贝的就是基本数据类型的值,如果属性是引用数据类型,拷贝的 就是内存地址

深拷贝

  • 将一个对象从内存中完整的拷贝一份出来,从对堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值