当前位置: 首页 > news >正文

Vue:添加响应式数据

Vue:添加响应式数据

1. 什么是响应式?

修改 data 后,页面自动改变/刷新,这就是响应式。就像我们在使用 Excel 的时候,修改一个单元格中的数据,其它单元格的数据会联动更新,这也是响应式。在前端开发中,响应式是一种非常重要的特性,它使得页面能够根据数据的变化自动更新,提升了用户体验和开发效率。

2. Vue 的响应式是如何实现的?

数据劫持:Vue 底层使用了 Object.defineProperty,将 data 中的数据放到了 _data 中,在 _data 中配置了 setter 方法,当去修改属性值时,setter 方法则被自动调用,setter 方法中不仅修改了属性值,而且还做了其他的事情,例如:重新渲染页面。setter 方法就像半路劫持一样,所以称为数据劫持。

不过,在 Vue 3 中,响应式系统采用了 Proxy 对象来替代 Object.definePropertyProxy 提供了更强大和灵活的元编程能力,可以直接监听对象的属性变化,而不需要像 Object.defineProperty 那样逐个属性进行劫持,这在处理嵌套对象和数组时更加高效。

// Vue 3 响应式示例
import { reactive } from 'vue';

const state = reactive({
  message: 'Hello, Vue 3!'
});

// 修改属性,自动触发响应式更新
state.message = 'New message';

3. Vue 会给 data 中所有的属性,以及属性中的属性,都会添加响应式。

Vue 在初始化时,会递归地遍历 data 对象的所有属性,使用 Object.defineProperty(Vue 2)或 Proxy(Vue 3)为每个属性添加响应式。这意味着无论是直接的属性还是嵌套的属性,只要在 data 中定义,都能实现响应式更新。

4. 后期添加的属性,不会有响应式,怎么处理?

Vue.set(目标对象, ‘属性名’, 值)
vm.$set(目标对象, ‘属性名’, 值)

<body>
  <div id="app">
    <h1>{{msg}}</h1>
    <div>姓名:{{name}}</div>
    <div>年龄:{{age}}岁</div>
    <div>数字:{{a.b.c.e}}</div>
    <div>邮箱:{{a.email}}</div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  <script>
    const vm = new Vue({
      el: "#app",
      data: {
        msg: "响应式与数据劫持",
        name: "jackson",
        age: 20,
        a: {
          b: {
            c: {
              e: 1,
            },
          },
        },
      },
    });

    // 1、测试:后期给 Vue 实例动态的追加的一些属性,会添加响应式处理吗?
    //vm.$data.a.email = 'jack@126.com'
    // 通过这种直接方式后期给 vm 追加的属性并没有添加响应式处理。

    //2、 如果你想给后期追加的属性添加响应式处理的话,调用以下两个方法都可以:
    // Vue.set() 、 vm.$set()
    //Vue.set(目标对象, 属性名, 属性值)
    //Vue.set(vm.$data.a, 'email', 'jack@126.com')
    //Vue.set(vm.a, 'email', 'jack@123.com')
    vm.$set(vm.a, "email", "jack@456.com");

    //3、 避免在运行时向 Vue 实例或其根 $data 添加响应式
    // 不能直接给 vm / vm.$data 追加响应式属性。只能在声明时提前定义好。
    //Vue.set(vm, 'x', '1')
    //Vue.set(vm.$data, 'x', '1')
  </script>
</body>

在 Vue 3 中,由于使用了 Proxy,可以直接通过 reactive 创建的对象添加属性,它会自动具备响应式。

import { reactive } from 'vue';

const state = reactive({
  name: 'John'
});

// 直接添加属性,自动具备响应式
state.age = 30;

5. Vue 没有给数组下标 0,1,2,3… 添加响应式,怎么处理?

① 调用 Vue 提供的 7 个 API:
push()
pop()
reverse()
splice()
shift()
unshift()
sort()
或者使用:
Vue.set(数组对象, ‘index’, 值)
vm.$set(数组对象, ‘index’, 值)

<body>
  <!-- 
      1. 通过数组的下标去修改数组中的元素,默认情况下是没有添加响应式处理的。怎么解决?
           可以通过控制台去修改数组元素
      
      2. 第一种方案:
          vm.$set(数组对象, 下标, 值)  vm.$set(vm.users,0,'杰克')
          Vue.set(数组对象, 下标, 值)  vm.set(vm.users,0,'杰克')

      3. 第二种方案:
          push()    在数组 尾部逐个添加 元素,返回结果数组的长度,能接收任意数量参数,push() 修改了原数组。
          pop()  移除数组最后一项,返回的是被移除项。修改原数组
          reverse() 可将数组进行倒序,此方法会改变原数组。
          splice() 通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
          shift() 删除数组的第一项元素,返回被删除的元素, 修改原数组
          unshift() 向数组的头部添加元素,返回的是结果数组的长度,修改原数组
          sort() 可将数组项灵活地进行升序或降序排列,此方法会改变原数组。

          在 Vue 当中,通过以上的 7 个方法来给数组添加响应式处理。
   -->
  <div id="app">
    <h1>{{msg}}</h1>
    <ul>
      <li v-for="user in users">{{user}}</li>
    </ul>
    <ul>
      <li v-for="vip in vips" :key="vip.id">{{vip.name}}</li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  <script>
    const vm = new Vue({
      el: "#app",
      data: {
        msg: "数组的响应式处理",
        users: ["jack", "lucy", "james"],
        vips: [
          { id: "111", name: "zhangsan" },
          { id: "222", name: "lisi" },
        ],
      },
      methods: {
        update() {
          // this.users[0]='tom'
          // this.users.reverse()
          console.log(this.users);
        }
      }
    });
  </script>
</body>

在 Vue 3 中,使用 reactive 创建的数组也能自动处理数组元素的响应式更新,直接通过下标修改元素也会触发页面更新。

import { reactive } from 'vue';

const state = reactive({
  numbers: [1, 2, 3]
});

// 直接修改数组元素,自动触发响应式更新
state.numbers[0] = 10;

相关文章:

  • Mysql中创建表时的约束条件
  • 使用Dependency Walker和Beyond Compare快速排查dll动态库损坏或被篡改的问题
  • JavaScript如何做类型转换
  • Python文字识别OCR
  • 麒麟服务器操作系统QT系列软件工具手册
  • 双指针算法-day11(双序列双指针)
  • 用hexo初始化博客执行hexo init时碰到的问题
  • 【即插即用涨点模块】EGA边缘引导注意力:有效保留高频边缘信息,提升分割精度,助力高效涨点【附源码+注释】
  • 告别硬编码:优雅管理状态常量与响应码
  • Ansible Facts变量
  • 相对论之光速
  • IP地址分配
  • Python 中用T = TypeVar(“T“)这个语法定义一个“类型变量”,属于类型提示系统的一部分
  • Java学习打卡-Day18-ArrayList、Vector、LinkedList
  • Ajax原理笔记
  • JDBC数据库连接池技术详解——从传统连接方式到高效连接管理
  • 零拷贝分析
  • LeetCode热题100JS(49/100)第九天|199|114|105|437|236
  • undo log ,redo log 和binlog的区别?
  • 使用 yum 命令安装 MariaDB 指南
  • 中巡组在行动丨①震慑:这些地区有官员落马
  • 外交部:正确认识和对待历史是检验日本能否恪守和平发展承诺的重要标准
  • 科普|“小”耳洞也会引发“大”疙瘩,如何治疗和预防?
  • 巫蛊:文化的历史暗流
  • 《单身情歌》制作人韩贤光去世,林志炫发文悼念
  • 普京:俄中关系是国家间关系的真正典范