我的编程空间,编程开发者的网络收藏夹
学习永远不晚

vue中Vue.set()的使用以及对其进行深入解析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

vue中Vue.set()的使用以及对其进行深入解析

Vue.set()使用

vue 在实例上添加新的属性的时候,该属性,并不是响应式的。同样删除某一属性的时候,也不会实时渲染到页面上。

比如:

 <p> 年龄:{{obj.age? obj.age: "无"}}</p>

        ···········      

 data() {

            return {        

                obj:{ name:"Lena", id:1 },

            }

          }

页面上 显示的是  年龄:无   现在需要添加一个响应式的属性 age 。

<template>
<div class="app">
      <ul>
        <li> 年龄:{{obj.age? obj.age: "无"}}</li>
      </ul>
      <button @click="add()">添加年龄属性</button>
      <button @click="show()">打印</button>
</div>
</template>
 
<script>
import Vue from 'vue'
export default {
  component:{},
  data() {
    return {
        obj:{ name:"Lena", id:1 },
    }
  },
  methods: {
    add(){
      this.obj.age= 20
    },
    show(){
      console.log('obj',this.obj)
    }
  }
}
</script>

效果:

通过 this.obj.age= 20 ,控制台打印已经有了该属性,并没有渲染到页面上。 可见,这种方式添加的属性 age 并不是响应式的。

使用Vue.set() ,更改add()方法:

add(){
      Vue.set(this.obj,'age', '20')
    },

效果:

因为vue不能检测到对象属性的添加或者删除,只有在data对象上存在的属性是响应式的,所以要使用Vue.set()方法将响应式属性添加到对象上。同样的道理,删除对象 Vue.delete也是如此。

Vue.delete()的使用

<template>
<div class="app">
      <ul>
        <li> 年龄:{{obj.age? obj.age: "无"}}</li>
      </ul>
      <button @click="add()">添加年龄属性</button>
      <button @click="del()">删除年龄属性</button>
      <button @click="show()">打印</button>
</div>
</template>
<script>
import Vue from 'vue'
export default {
  component:{
 
  },
  data() {
    return {
        obj:{ name:"Lena", id:1 },
    }
  },
  methods: {
    add(){
      Vue.set(this.obj,'age', '20')
    },
    del(){
      Vue.delete(this.obj,'age')
    },
    show(){
      console.log('obj',this.obj)
    }
  }
}
</script>

效果:

del() 方法如果是下面两种,同样不是响应式的。

del(){

      delete this.obj.age

    },

或者:

del(){

      this.obj = { name:"Lena", id:1 }

    },

Vue.set()方法原理解析

我们找到封装set方法的地方:.........\node_modules\vue\class="lazy" data-src\core\observer\index.js

 找到封装的set方法:

export function set (target: Array<any> | Object, key: any, val: any): any {
  if (process.env.NODE_ENV !== 'production' &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
  }
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== 'production' && warn(
      'Avoid adding reactive properties to a Vue instance or its root $data ' +
      'at runtime - declare it upfront in the data option.'
    )
    return val
  }
  if (!ob) {
    target[key] = val
    return val
  }
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

对象调用:Vue.set( target ,'age', 20 ) 

数组调用Vue.set( array , 0,  20 )  //数组对象,索引,值

首先是判断是否是开发环境并且 对象是否被定义isUndef(target)或者是否是基础类型isPrimitive(target),否则会报错:

`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`

if (process.env.NODE_ENV !== 'production' &&

    (isUndef(target) || isPrimitive(target))

  )

如果是数组的话,调用重写的splice()方法,可以更新视图。

isValidArrayIndex(key)方法用来验证是否是一个有效的数组索引, 其实就是验证是否是一个非无穷大的正整数。

if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }

如果对象本身就有所要添加的属性,那只需要直接赋值就可以。

if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }

 如果是Vue实例,或者是根数据data的时候,就会报错。

如果本身就不是响应式的,只需要直接赋值即可。

const ob = (target: any).__ob__
  //如果是Vue实例,或者是根数据data的时候,就会报错。
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== 'production' && warn(
      'Avoid adding reactive properties to a Vue instance or its root $data '+
      'at runtime - declare it upfront in the data option.'
    )
    return val
  }
 
  //如果本身就不是响应式的,只需要直接赋值即可。
  if (!ob) {
    target[key] = val
    return val
  }
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val

排除各种不合适的,最后给当前对象定义一个属性:defineReactive(ob.value, key, val) 相当于用了 Object.defineProperty 重新定义了一下。

最后,手动通知视图更新:ob.dep.notify()

总结

这个 set方法,对于数组来说,调用的就是splice,对于对象来说,使用的就是defineReactive,再添加了一个手动的视图更新。这就是set的原理。

到此这篇关于vue中Vue.set()的使用以及对其进行深入解析的文章就介绍到这了,更多相关vue Vue.set()的使用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

vue中Vue.set()的使用以及对其进行深入解析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

vue中Vue.set()的使用以及对其进行深入解析

vue不允许在已经创建的实例上动态添加新的根级响应式属性,不过可以使用Vue.set()方法将响应式属性添加到嵌套的对象上,下面这篇文章主要给大家介绍了关于vue中Vue.set()的使用以及对其进行深入解析的相关资料,需要的朋友可以参考下
2023-01-04

对Go语言中数组的定义和使用进行深入剖析

Go语言中数组的定义与用法探析数组定义Go语言中的数组是一种有序的固定长度的数据结构,可以存储相同类型的数据元素。数组的元素可以通过索引来访问,索引从0开始。数组的定义语法如下:var arrayName [arrayLength]e
对Go语言中数组的定义和使用进行深入剖析
2024-02-01

深入解析复杂SQL查询及其在C#中的应用

复杂SQL查询是数据库应用中的强大工具,能够处理复杂的数据检索和分析任务。通过在C#中合理地执行这些查询,我们可以构建出功能强大且高效的数据驱动应用程序。

深入学习Golang的打包实战指南: 探索使用Golang进行打包及解决常见问题的方法

Golang打包实战指南:利用golang进行打包并解决常见问题引言:Golang是一门流行的编程语言,其强大的并发性和高效的编译器使其成为很多开发者的首选。在开发过程中,我们经常需要将我们的代码打包成可执行文件或库,以便在其他环境中部署和
深入学习Golang的打包实战指南: 探索使用Golang进行打包及解决常见问题的方法
2023-12-29

编程热搜

目录