您的位置:

uniapp $set使用指南

一、$set的作用和语法结构

$set是uniapp框架提供的一种方法,可以对data中的数据进行修改和更新。$set的语法结构如下:

Vue.set(object, key, value)或vm.$set(object, key, value)

其中object必填,是要修改的对象;key必填,是对象中要修改或更新的属性名;value必填,是属性的新值。

二、$set的常见应用场景

在vue.js的开发中,可以通过直接对data中的数据进行修改来实现对视图的更新,但当需要修改或更新对象中某个属性的时候,如果直接对属性进行修改,vue.js无法监测到数据的变化,也就无法触发视图更新。这时就需要使用$set方法来通知vue.js数据改变了,视图需要更新。下面是$set的常见应用场景。

1、通过数组下标更新数组数据

如果需要修改数组中的某个元素,可以通过数组下标来更新数组数据。例如,有一个tasks数组,需要将第一个任务的状态由未完成改为已完成,可以使用以下代码实现:

this.tasks[0].status = 'completed';

上面的代码可以更新数据,但是vue.js无法检测到数据的变化,这时就需要使用$set来通知vue.js更新数据。代码如下:

this.$set(this.tasks[0], 'status', 'completed');

这样vue.js就能检测到数据的变化,触发视图的更新。

2、通过对象属性名更新对象数据

如果需要修改对象中的某个属性,也可以使用$set来触发视图更新。例如,有一个person对象,需要将其年龄属性值改为20,可以使用以下代码实现:

this.person.age = 20;

同样,这样修改数据vue.js也无法检测到数据变化,需要使用$set方法来通知vue.js更新数据。代码如下:

this.$set(this.person, 'age', 20);

三、$set的高级操作——监听对象属性的新增与删除

除了可以对已有属性进行修改和更新,$set方法还支持监听对象属性的新增和删除。这一功能对于实现动态表单、涉及到属性的动态添加和删除的组件非常有用。

1、新增属性

如果需要给对象新增一个属性,并且希望vue.js能够监测到新增的属性,可以使用$set方法。例如,有一个person对象,需要新增一个地址属性,可以使用以下代码实现:

this.$set(this.person, 'address', '');

这样新增属性就可以被vue.js监测到,从而使得视图更新。

2、删除属性

如果需要删除对象中的某个属性,同样可以使用$set方法。例如,有一个person对象,需要删除其地址属性,可以使用以下代码实现:

this.$set(this.person, 'address', undefined);

这样操作会使得地址属性变为undefined,但是vue.js依然会监测到属性的删除,使得视图更新。

四、$set的注意事项

$set虽然非常实用,但是在使用过程中也需要注意一些问题,防止出现不必要的错误和问题。

1、避免在模板中使用$set

虽然$set方法可以帮助我们实现动态数据的更新,但是在模板中使用$set是非常不推荐的。在模板中可以直接使用data中的数据和方法,可以不必使用$set。如果需要在组件中进行动态数据更新,可以借助computed、watch和props等特性来实现。

2、避免在computed属性中使用$set

在computed计算属性中,如果使用$set方法进行数据更新,会导致无限循环的问题。因为computed属性的值是基于data中的其他属性计算的,如果在computed中使用$set方法,则会让computed属性的值发生变化,从而引起重新计算,这样就形成了循环调用。

3、$set无法监控属性名的变化

$set方法只能监听对象属性值的变化,无法监听属性名的变化。比如,如果一个对象中的属性名称发生了变化,$set方法是无法监测到这一变化,并且也无法触发组件的更新。所以在修改属性名时,需要手动删除原有属性并在对象中添加一个新的属性,从而实现属性名的修改和更新。

五、$set的实例应用

下面是一个$set的实例应用,代码中实现了一个待办事项的功能,支持添加任务、修改任务状态和删除任务。

1、模板中的代码

<template>
  <div class="task-list">
    <h3>待办事项</h3>
    <ul>
      <li v-for="(task, index) in tasks" :key="index">
        <input type="checkbox" v-model="task.status">
        <span :class="{ completed: task.status }" v-text="task.title"></span>
        <i class="iconfont icon-delete" @click="deleteTask(index)"></i>
      </li>
    </ul>
    <form @submit.prevent="addTask">
      <input type="text" v-model="newTaskContent">
      <button type="submit">添加任务</button>
    </form>
  </div>
</template>

2、script中的代码

<script>
export default {
  data () {
    return {
      tasks: [
        { title: '吃饭', status: true },
        { title: '睡觉', status: false },
        { title: '打豆豆', status: false }
      ],
      newTaskContent: ''
    }
  },
  methods: {
    addTask () {
      if (this.newTaskContent.trim() !== '') {
        this.tasks.push({
          title: this.newTaskContent,
          status: false
        })
        this.newTaskContent = ''
      }
    },
    deleteTask (index) {
      this.tasks.splice(index, 1)
    }
  }
}
</script>

3、style中的代码

<style scoped>
.task-list {
  margin: 20px auto;
  padding: 20px;
  box-shadow: 0 0 10px rgba(0,0,0,.1);
}
.task-list h3 {
  font-size: 24px;
  margin-bottom: 20px;
}
.task-list ul {
  list-style: none;
  padding: 0;
}
.task-list li {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  font-size: 18px;
}
.task-list input[type="checkbox"] {
  margin-right: 10px;
}
.task-list span.completed {
  text-decoration: line-through;
  color: #999;
}
.task-list i {
  margin-left: auto;
  cursor: pointer;
  font-size: 18px;
}
.task-list form {
  margin-top: 20px;
}
.task-list input[type="text"] {
  padding: 5px 10px;
  font-size: 18px;
  margin-right: 10px;
  border: none;
  border-bottom: 1px solid #999;
  outline: none;
}
.task-list button {
  padding: 5px 10px;
  font-size: 18px;
  background-color: #00bcd4;
  color: #fff;
  border: none;
  outline: none;
  cursor: pointer;
}
</style>

在这个例子中,我使用了$set方法来更新任务的状态,确保vue.js能够检测到数据变化从而更新视图。

this.$set(this.tasks[index], 'status', !this.tasks[index].status)