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>
### Vue3 中 `$set` 方法的使用Vue 3 中,由于引入了 Proxy 数据劫持机制替代了 Vue 2 中基于 `Object.defineProperty` 的实现方式,因此不再需要显式调用 `$set` 或 `Vue.set` 来手动设置响应式属性。Proxy 提供了更强大的功能来拦截对象和数组的操作,使得新增或删除属性能够自动被侦测并保持响应式特性。 尽管如此,在某些特定场景下(例如兼容旧代码或者处理复杂逻辑时),开发者仍然可以模拟 `$set` 的行为以满足需求。以下是关于如何在 Vue 3 中实现类似 `$set` 功能的内容: #### 响应式基础变化 在 Vue 3 中,通过 `reactive()` 创建的对象默认支持深层次的响应式能力,这意味着即使向嵌套对象添加新属性也无需额外操作即可触发视图更新[^1]。对于数组,则继续沿用了可变方法(如 push、pop 等)作为响应式的手段[^4]。 如果确实希望模仿 Vue 2 风格的手动设定过程,可以通过以下方式进行自定义封装: ```javascript function set(target, key, value) { if (Array.isArray(target)) { target.length = Math.max(key >= 0 ? key + 1 : target.length, target.length); target[key] = value; } else { Object.assign(target, { [key]: value }); } } ``` 此函数适用于简单情况下的动态赋值需求;但对于更加复杂的业务逻辑建议直接利用 Composition API 和 Reactive System 提供的功能完成开发工作流优化[^3]。 #### 示例代码展示 下面给出一段完整的例子说明如何在 Vue 3 组件里边运用上述思路解决问题: ```vue <template> <div>{{ state.obj.a }} - {{ state.obj.b }}</div> <!-- 初始只显示a --> </template> <script> import { reactive } from 'vue'; export default { setup() { const state = reactive({ obj: { a: 1 }, }); setTimeout(() => { // 模拟异步加载后增加 b 属性 state.obj['b'] = 2; }, 1000); return { state }; }, }; </script> ``` 在这个案例里面可以看到,即便是在延时之后才给 `obj` 添加了一个全新的键名 `b` ,页面依旧可以根据最新的状态做出相应调整而不需要任何特殊干预措施[^2]。 #### 总结 综上所述,虽然严格意义上讲 Vue3 并未保留独立的 `$set` 函数接口,但是凭借全新升级后的反应体系完全可以达到甚至超越原来的效果表现力。同时提醒各位同学注意区分不同版本之间的区别以及各自适用范围以便更好地开展项目实践!
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值