Vue 中 $set的使用

本文详细介绍了在Vue.js开发中如何正确使用$set方法来处理实例创建后新增属性的问题,避免视图更新失败的情况。

vue.$set:设置的属性对象 可以是Object或者数组
设置的key值可以 string或者number类型
设置的值可以是任意值
在这里插入图片描述
在这里插入图片描述

vue进行开发的过程中,可能会遇到一种情况:当生成vue实例后,当再次给数据赋值时,有时候并不会自动更新到视图上去;
Vue文档有这么一句话:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新.,代码示例如下:

<div id="app">
  <ul>
    <li>{{obj.name}}</li>	
    	<li>{{obj.age}}</li>		
    	<li>{{obj.sex}}</li>		
    	<li>{{obj.info.content}}</li>
  </ul>
</div>
<script>
  let vm = new Vue({
    el:'#app',
    data() {
      return {
        obj:{name: "SMlZ",age: '3', info: {content: 'my name is smlz'}}
        }
    },
    mounted(){
      this.obj.sex = 'female' // 可以设置成功因为值设置成功了,但值没有属性,
      //如果后续更改这个值,比如在button上点击事件视图是不会更新的
      console.log(this.obj)
      this.$set(this.obj.info,'content', 'who is my girlfriend?')// 能设置成功
    }
  });
</script>

在实例创建前this.obj.sex = 'female' 你能看到视图有sex这一项,打印出来obj你会发现sex少了其他属性所共有的东西
在这里插入图片描述
所以 如果在实例创建之后添加新的属性或者更改这个sex属性到实例上,它不会触发视图更新。比如我们页面新加一个button 附带个点击事件:

<div id="app">
  <ul>
    <li>{{obj.name}}</li>
    <li>{{obj.age}}</li>
    <li>{{obj.sex}}</li>
    <li>{{obj.info.content}}</li>
    </li>
  </ul>
</div>
<button @click="showSex">显示性别</button>
<script>
let vm = new Vue({
  el:'#app',
  data() {
    return {
      obj:{
        name: "SMlZ",
        age: '3',
        info: {
          content: 'my name is smlz'
        }
      }
    }
  },
  methods:{
    showSex(){
      this.obj.sex = 'female' // Vue.set(this.obj,'sex', '女')//this.$set(this.obj,'sex', '女女');
    }
  },
  mounted(){
    this.obj.sex = 'female' // 可以设置成功因为值设置成功了,但值没有属性,
    //如果后续更改这个值,比如在button上点击事件视图是不会更新的。
    console.log(this.obj)
    this.$set(this.obj.info,'content', 'who is my girlfriend?');
  }
});
</script>

点击button 无论怎么更改是不会更新的,因为在创建实例的时候 缺少了vue 监听的 set、get属性
所以要在mounted里把初始值this.obj.sex = ‘female’ 去掉
或者直接在页面实例未创建完成前,用$set方法添加进去),这样在实例创建后 想更改或者添加新属性,用Vue.set()' 或者 this.$set()便成功了

完整代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>vue $set</title>
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
  <ul>
    <li>{{obj.name}}</li>
    <li>{{obj.age}}</li>
    <li>{{obj.sex}}</li>
    <li>{{obj.info.content}}</li>
    </li>
  </ul>
  <button @click="showSex">显示性别</button>
</div>
<script>
let vm = new Vue({
  el:'#app',
  data() {
    return {
      obj:{
        name: "SMlZ",
        age: '3',
        info: {
          content: 'my name is smlz'
        }
      }
    }
  },
  methods:{
    showSex(){
      Vue.set(this.obj,'sex', '女')//this.$set(this.obj,'sex', '女女');
    }
  },
  mounted(){
    this.$set(this.obj.info,'content', 'who is my girlfriend?');
  }
});
</script>
</body>
</html>
### 在 UniApp Vue3 中正确使用 set 方法 在 Vue3 和 UniApp 中,`Vue.set` 方法已被移除,因为 Vue3 使用了基于 Proxy 的响应式系统,能够自动追踪对象属性的变化。因此,在大多数情况下,无需显式调用 `Vue.set` 来设置对象的属性[^3]。 然而,在某些特殊场景下(例如动态添加新属性到响应式对象中),仍然需要确保属性是响应式的。以下是几种常见情况及其解决方案: --- #### 动态添加对象属性 如果需要动态添加一个新属性到响应式对象中,可以直接赋值即可触发响应式更新。代码示例如下: ```javascript import { reactive } from 'vue'; const state = reactive({ name: 'UniApp' }); // 动态添加属性 state.age = 3; // 这里会自动触发响应式更新 ``` 上述代码中,直接为 `state` 对象添加了一个新的 `age` 属性,并且该属性会被 Vue 自动追踪并触发视图更新。 --- #### 替代 Vue2 中的 Vue.set 方法 在 Vue2 中,`Vue.set` 常用于以下两种场景: 1. 向响应式对象中添加新属性。 2. 更新数组中的某个索引值。 在 Vue3 中,这两种场景都可以通过直接操作数据来实现。 **向对象添加新属性:** ```javascript import { reactive } from 'vue'; const state = reactive({ userInfo: { name: 'User' } }); // 动态添加 level 属性 state.userInfo.level = 1; // 直接赋值即可触发响应式更新 ``` **更新数组中的某个索引值:** ```javascript import { reactive } from 'vue'; const state = reactive({ list: [1, 2, 3] }); // 更新数组中的某个元素 state.list[1] = 10; // 直接修改数组元素即可触发响应式更新 ``` 在 Vue3 中,由于 Proxy 的强大功能,上述操作均能正常触发响应式更新,而无需额外调用类似 `Vue.set` 的方法[^3]。 --- #### 在 UniApp 中使用 Vuex 的 commit 方法 如果是在 Vuex 中使用 `set` 方法,可以通过 `commit` 提交 mutation 来修改状态。代码示例如下: **定义 mutation:** ```javascript export default { state: { flag: 0, userInfo: { level: 0 } }, mutations: { setFlag(state, value) { state.flag = value; // 修改 flag }, setUserInfoLevel(state, level) { state.userInfo.level = level; // 修改 userInfo.level } } }; ``` **提交 mutation:** ```javascript this.$store.commit('setFlag', 1); this.$store.commit('setUserInfoLevel', 1); ``` 通过上述方式,可以在 Vuex 中动态修改状态,而无需显式调用 `Vue.set`[^1]。 --- #### 注意事项 - 如果需要动态添加深层嵌套的对象属性,建议逐步创建中间对象以确保每一层都是响应式的。例如: ```javascript import { reactive } from 'vue'; const state = reactive({}); // 创建嵌套对象 state.user = {}; state.user.info = {}; state.user.info.name = 'Test'; // 确保每一层都是响应式的 ``` - 在 Vue3 中,Proxy 的性能开销可能略高于 Vue2 的 Object.defineProperty。因此,在大规模动态添加属性时,需注意性能优化[^3]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值