Vue 2.x 子组件删除时使用setTimeout导致splice数组元素后视图没有正确更新的解决方案

在实际业务中,经常会有这样的场景:一堆消息卡片。比如:
在这里插入图片描述
对于这种情况,在Vue里,我们一般都会封装一个Card组件,然后在父组件中用v-for进行渲染。以下是一个随手写的例子(也可以在https://codesandbox.io/s/great-field-x95lw?fontsize=14&hidenavigation=1&theme=dark查看):

// App.vue
<template>
  <div id="app">
    <div v-for="(item, index) in arr"
         :key="index">
      <Card :title="item.name"
            @remove="arr.splice(index, 1)"/>
    </div>  
  </div>
</template>

<script>
export default {
  name: 'App',
  components: { Card },
  data () {
    return {
      arr: [
        { id: 1, name: 'foo' },
        { id: 2, name: 'bar' },
        { id: 3, name: 'baz' },
        { id: 4, nam
<think>嗯,用户想了解Vue.js中的set方法的使用教程和示例。首先,我需要回忆一下Vue的响应式系统原理。Vue 2.x是通过Object.defineProperty来实现数据劫持的,所以当直接给对象添加新属性或者通过索引修改数组Vue无法检测到变化,这候就需要用Vue.set或者实例的$set方法。 用户可能已经知道Vue的基本用法,但遇到了动态添加属性导致视图不更新的问题。需要解释为什么需要set方法,比如对象属性的添加或数组索引的直接设置。然后给出具体的用法,包括全局方法Vue.set和实例方法this.$set的区别,以及它们的参数说明。 接下来应该提供示例代码,比如给对象添加新属性和修改数组元素的例子。要注意代码的格式,使用正确的语法,比如在mounted钩子中使用setTimeout来模拟异步操作,展示如何正确触发视图更新。 还要注意引用用户提供的引用内容,特别是引用[1]和[3],里面提到了Vue.set的实现原理和应用场景。需要确保在回答中自然地插入这些引用,比如在解释为什么需要set方法的候,引用[3]提到“对象不能响应式更新”,所以这里需要强调set方法的作用。 另外,用户可能还想知道什么候需要使用set方法,比如在动态添加嵌套对象的属性或者处理数组。需要分点说明使用场景,可能包括对象属性添加、数组元素修改、嵌套对象处理等。 最后,按照用户的要求生成相关问题,比如set方法的原理、与直接赋值的区别、在Vue 3中的变化等。这些问题需要与主题相关,帮助用户进一步学习。 需要检查回答是否符合系统级指令,比如数学公式的格式是否正确,但这里可能用不上。主要确保使用中文,结构清晰,代码正确,引用标识正确添加。</think>### Vue.js 中 `set` 方法的使用教程与示例 `Vue.set`(或组件内的 `this.$set`)是 Vue.js 用于确保动态添加的响应式对象属性或数组元素能够触发视图更新的核心方法。以下是详细说明: --- #### **为什么需要 `set` 方法?** Vue.js 的响应式系统基于 `Object.defineProperty`(Vue 2.x),无法自动检测以下操作: 1. **对象属性的动态添加**:直接通过 `obj.newKey = value` 添加的属性不是响应式的[^3]。 2. **数组索引的直接修改**:例如 `arr[index] = newValue` 不会触发视图更新[^1]。 此使用 `Vue.set` 或 `this.$set` 强制更新响应式系统。 --- #### **`set` 方法的使用方式** 1. **全局方法 `Vue.set`** 语法:`Vue.set(target, propertyName/index, value)` - `target`:目标对象或数组 - `propertyName/index`:属性名或数组索引 - `value`:新值 2. **实例方法 `this.$set`** 在组件内部,可用 `this.$set` 替代 `Vue.set`,语法相同。 --- #### **示例代码** ##### 1. **动态添加对象属性** ```javascript new Vue({ data: { user: { name: "Alice" } }, mounted() { // ❌ 错误方式:视图不更新 // this.user.age = 25; // ✅ 正确方式 this.$set(this.user, 'age', 25); } }); ``` ##### 2. **修改数组元素** ```javascript new Vue({ data: { items: ['apple', 'banana'] }, mounted() { // ❌ 错误方式:视图不更新 // this.items[2] = 'orange'; // ✅ 正确方式 this.$set(this.items, 2, 'orange'); } }); ``` ##### 3. **结合异步操作(如接口请求)** ```javascript mounted() { setTimeout(() => { Vue.set(this.items, 3, 'grape'); // 引用示例中的用法 }, 1000); } ``` --- #### **适用场景** 1. **对象属性动态添加**:如表单动态增加字段。 2. **数组索引直接修改**:替代 `splice` 或使用变异方法(如 `push`)。 3. **嵌套对象处理**:对深层对象属性动态修改,需逐层使用 `set`。 --- #### **注意事项** - Vue 3.x 使用 `Proxy` 替代 `Object.defineProperty`,已支持动态属性检测,`set` 方法仅在兼容模式下保留。 - 对于数组,优先使用变异方法(如 `push`、`splice`),而非直接索引操作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值