vue2 数据响应式Object.defineProperty

news/2024/7/10 2:21:50 标签: vue.js, 前端, javascript, vue

我们通常可以对进行输入框进行数据的监听,只需要用到了input 事件或 change事件,就可以实时监听到数据的改变,但是如果只是一个单独的数据呢?怎么去做监听,watch吗??哈哈。

所以 vue响应式就用到了object.defineProperty 中的 get 和 set 方法 ,如果对方法不了解可访问蓝色文字。简单来说 只要一访问就会触发get,设置就会触发set。

基本语法:

Object.defineProperty(对象,键,{
        get (   )   {   },
        set (val) {   }        
})

javascript"> let data = {
     name:'奥特曼'
 }

 Object.defineProperty(data,'name',{
       get(){
         console.log('访问了')
       },
       set(val){
        console.log('设置了,值是:',val)
      }
  })

1. 单个数据实现响应

实现效果:

为了和vue保持格式一致 我们先定义初始变量data ,并且一开始把值赋给类名为name的内容数据

<div class="name"></div>
<script>
     let data = {
       name:'奥特曼'
    }

   function setName() {
       document.querySelector('.name').innerHTML = username
    }

    setName() 
 </script>

接下来要对data.name进行实时的监听,就要用到了obj.defineProperty

javascript">     let username = "奥特曼";
      Object.defineProperty(data, "name", {
        get() {
          console.log("访问了");
          return username;
        },
        set(val) {
          console.log("设置了,值是:", val);
          username = val;
          setName();
        },
      });

这里注意 特意用了一个中间变量 username,如果不这么用你可能会想到,错误写法别抄哦

javascript">      get(){
              console.log('访问了');
              return data.name
           },

为什么不直接把data.username给返回出去,为什么要返回一个值一样的username?原因就是 我们返回着data.name 其实也是在访问他,然后呢每次访问每次进入get函数 就会进入一个死循环。

2.多个数据实现响应式

这里就不过多解释了 只需要把对象循环一下 利用Object.defineProperty监听每个属性,我相信你可以看懂的

<script>    
    let data = {
        username:'奥特曼',
        age:18,
    }

    function setData() {
        username.innerHTML = data.username
        age.innerHTML = data.age
    }

    function observe(data) {
        for (const key in data) {
            let value = data[key]
            Object.defineProperty(data,key,{
                get(){
                    return value 
                },
                set(val){
                    value = val
                    setData()
                }
            })
        }
    }

    observe(data)
    setData()

</script>

3. 监听复杂数据类型响应式

我们只需要判断当前的参数是否是对象 如果是对象利用一下递归。

<script>    

    let data = {
        username:'奥特曼',
        age:18,
        student:{
            name :'怪兽'
        }
    }

    function setData() {
        username.innerHTML = data.username
        age.innerHTML = data.age
        monster.innerHTML = data.student.name
    }

    function observe(data) {
        for (const key in data) {
            if(typeof data[key] == 'object') {
               observe(data[key])
            }
            let value = data[key]
            Object.defineProperty(data,key,{
                get(){
                    return value 
                },
                set(val){
                    value = val
                    setData()
                }
            })
        }
    }

    observe(data)
    setData()

</script>

4.新增对象属性和数组下标修改

vue中,我们是检测不到一个对象新增属性和直接修改数组某一项的变化,但是上面的代码中是能够对数组下标进行修改的,那为什么vue不可以呢?

 尤大大也说考虑到了性能和用户体验的问题 如果一个数组10000条数据 监听这每一项的数据变化 确实也有很大的性能问题,但vue也提供了解决方案 $set

贴一下 修改数组下标 及 修改不了新增的对象属性代码

<script>    
    let data = {
        username:'奥特曼',
        age:18,
        student:{
            name :'怪兽'
        },
        arr:[0,1,2,3]
    }

    function setData() {
        username.innerHTML = data.username
        age.innerHTML = data.age
        monster.innerHTML = data.student.name
        // 无法对新增的属性进行监听  原因就是observe  一开始就对原数据进行数据的监听  这也是object.defineproperty的本身缺陷
        monsterAge.innerHTML = data.student.age
        number.innerHTML = data.arr[0]
    }

    function observe(data) {
        for (const key in data) {
            if(typeof data[key] == 'object') {
                observe(data[key])
            }
            let value = data[key]
            Object.defineProperty(data,key,{
                get(){
                    return value 
                },
                set(val){
                    value = val
                    setData()
                }
            })
        }
    }

    observe(data)
    setData()

</script>

补充:但是有一点哈,有时候呢 你是可以修改数组某一项实现响应式的,什么时候呢看下面的例子

    <div>
        <div> {{arr[0]}}</div>
        {{ obj.a }}
        <button @click="editNumber">要修改了</button>
    </div>

<script>
export default {
  data () {
    return {
      arr: [0, 1, 2, 3, 4, 5],
      obj: { a: 1 }
    }
  },
  methods: {
    editNumber () {
      this.arr[0] = 999
      // 如果不加下面这一行代码,视图就不会更新
      // 更新的原因:下面的数据是响应式的数据他会去更新视图,一旦更新视图 数据是对整个组件进行更新的,所以arr[0] 会更新
      // 其实底层的object.defineProperty 可以对数组进行更新 但是尤大考虑到数组 的性能与用户体验不成正比 去掉了对数组的响应式 (获取涉及几万条数组非常的大)
      this.obj.a = 2
    }
  }
}
</script>


http://www.niftyadmin.cn/n/31448.html

相关文章

Linux之网络性能测试工具netperf实践

一、netperf简介 Netperf是一种网络性能的测量工具&#xff0c;主要针对基于TCP或UDP的传输。Netperf根据应用的不同&#xff0c;可以进行不同模式的网络性能测试&#xff0c;即批量数据传输&#xff08;bulk data transfer&#xff09;模式和请求/应答&#xff08;request/rep…

第九层(8):STL之set/multiset

文章目录前情回顾set/multiset概念区别构造函数赋值函数大小操作函数交换函数插入函数删除函数查找函数统计函数为什么set不可以插入重复数据pair数组pair数组创建怎么样去改变set容器的排序规则下一座石碑&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一…

C++Premier14.1节练习

练习14.1&#xff1a; 区别&#xff1a;一些运算符的重载版本无法保留内置运算符的短路求值属性&#xff0c;或者无法保留内置运算符的求值顺序规则。重载的运算符函数至少含有一个类类型的参数 一致&#xff1a;重载运算符函数的参数数量与该运算符内置版本作用的运算对象一…

Windows内核--任务、进程和线程(2.4)

图片来自: Windows内核原理与实现 Windows内核有"任务"概念吗? 从技术术语来说&#xff0c;Windows内核并没有"任务"。"任务"一般被认为是抽象的需要执行的事情。在不同操作系统上&#xff0c;"任务"所代表的官方名称有所差异。 Linu…

Win10下使用WSL2

打包 wsl --export Ubuntu-20.04 E:\Ubuntu\ubuntu.tar.gz 注销之前 wsl --unregister Ubuntu-20.04 导入 wsl --import Ubuntu-20.04 E:\Ubuntu\ E:\Ubuntu\ubuntu.tar.gz --version 2 设置默认登陆用户为安装时用户名 ubuntu2004.exe config --default-user dwb 更新清…

【Linux】编辑器——vim的使用

环境&#xff1a;centos7.6&#xff0c;腾讯云服务器Linux文章都放在了专栏&#xff1a;【Linux】欢迎支持订阅&#x1f339;vim的基本概念vim是什么&#xff1f;vim是一款多模式的编辑器&#xff0c;是vi的升级版本&#xff0c;在兼容vi指令的同时&#xff0c;还带有一些新的特…

洛谷入门篇的相关题解

CF616A Comparing Two Long Integers 思路&#xff1a; 因为数字可能含有前导零&#xff0c;所以先对两个数字进行去除前导零的操作&#xff0c;操作后的两个数字如果位数相同&#xff0c;再逐位比较&#xff0c;否则&#xff0c;位数多的那个数字大于位数少的那个数字. 参考代…

API自动化测试【postman生成报告】

PostMan生成测试报告有两种&#xff1a; 1、控制台的模式 2、HTML的测试报告 使用到一个工具newman Node.js是前端的一个组件&#xff0c;主要可以使用它来开发异步的程序。 一、控制台的模式 1、安装node.js 双击node.js进行安装&#xff0c;安装成功后在控制台输入node…