Vue不能检测到数据变化的几种情况说明

目录
  • Vue不能检测到数据变化的情况
    • 第一类:对于数组
    • 第二类:对于对象
  • Vue检测数据的原理
    • 总结一下

Vue不能检测到数据变化的情况

Vue 实现了数据的双向绑定,所以我们在更改数据时,页面就会实时的反映出修改的变化

但是由于javascript 的限制,有几种情况,vue是不能检测到数据变化的

第一类:对于数组

1. 当你利用索引直接设置一个项时,例如:

vm.items[indexOfItem] = newValue

2. 当你修改数组的长度时,例如:

vm.items.length = newLength

如下例

    new Vue({
        data(){
            return {
                arr:[
                    {id:1,name:"haha",age:18},
                    {id:2,name:"hehe",age:19}
                ]
            }
        }
    })
    ......
    methods:{
        change(){
            this.arr[0] = {id:1,name:"gege",age:30};  //这种写法vue是不能检测到的, 也就是说页面的数据不会改变
            this.arr[0].name = "gege";
            this.arr[0].age = 30;   //这种方式是可以检测到的, 这是更改的数组内部的对象的属性是可以检测到变化的
            //也可以使用 vue 提供的方法
            this.$set(this.arr,0,{id:1,name:"gege",age:30}) ; //这种方法也是可以的
            //还可以使用 vue 的变种函数
            this.arr.splice(0,1,{id:1,name:"gege",age:30});
            //这里的 splice方法其实已经不是 js 的 splice方法了, 它是被vue 改写过的方法
        }
    }

从上面我们可以看到,如果想要通过数组下标修改数组的话,vue 是检测不到数据的变化的,要么使用 $set , splice 等数组的方法,要么就再向组数内部走一级,直接修改内部对象的属性也是可以的

第二类:对于对象

vue 是可以检测到对象中数据发生的改动的,因为初始化的时候 对象的每一个属性 都生成好了 getter 和setter方法,但是我们如果在程序运行过程中 动态的给对象添加新的属性,删除属性,vue 是检测不到的

    new Vue({
        data(){
            return {
                a:{
                    b:"c"
                }
            }
        }
        ......
        mehtods:{
            changes(){
                this.a.bb = "bbbb"; //这种写法是在 a 对象上面添加了一个 bb 的属性, vue 是检测不到的
                //所以这种情况下, 我们要使用 $set 
                this.$set(this.a,"bb","bbbbb");  //这样就可以解决问题, 
            }
        }
    })

上面只写了添加对象属性时的情况,删除对象的属性时,1.也可使用 $set

有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:

Object.assign(vm.userProfile, {
age: 27,
favoriteColor: ‘Vue Green'
})

你应该这样做:

vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: ‘Vue Green'
})

Vue检测数据的原理

一个简单的例子,总结一下vue监测数据

<div id="app">
  <h1>学生信息</h1>
  <button @click="addSex">添加sex属性,默认值为男</button>
  <button @click="changeSex">修改sex属性</button>
  <button @click="unshiftFriend">在列表首位添加一个朋友</button>
  <button @click="changeFriendName">修改第一个朋友的名字为:张三</button>
  <button @click="addHobby">添加一个爱好</button>
  <button @click="changeHobby">修改第一个爱好为:开车</button>
  <h2>姓名:{{student.name}}</h2>
  <h2>性别:{{student.sex}}</h2>
  <h2>爱好:</h2>
  <ul>
    <li v-for="(h,index) in student.hobby" :key="index">{{h}}</li>
  </ul>
  <h2>朋友们:</h2>
  <ul>
    <li v-for="(f,index) in student.friends" :key="index">{{f.name}} -- {{f.age}}</li>
  </ul>
</div>
const app = new Vue({
  el: "#app",
  data: {
    student: {
      name: "AIpoem",
      hobby: ["抽烟","喝酒","烫头"],
      friends: [
        {name: "jerry",age: 18},
        {name: "Cici",age:19}
      ]
    }
  },
  methods: {
    addSex() {
      // this.student.sex = "男"  不是响应式
      this.$set(this.student,"sex","男");
    },
    changeSex() {
      // 直接改即可,因为上面添加的sex属性为响应式
      this.student.sex='女'
    },
    unshiftFriend() {
      this.student.friends.unshift({name:"newFriend",age:20});
    },
    changeFriendName() {
      // 这里直接改即可,name属性是响应式的
      this.student.friends[0].name = "张三";
    },
    addHobby() {
      this.student.hobby.push("新爱好");
    },
    changeHobby() {
      // this.student.hobby[0] = "开车" 不是响应式
      this.student.hobby.splice(0,1,"开车");
    }
  }
})

关于vue监视对象:

直接添加的sex属性,没有getter和setter,无法实现响应式

利用Vue.set()添加的sex属性,有getter和setter,可以实现响应式

另一种写法,和上面作用一样

关于vue监视数组:

比如这个例子,一开始页面是抽烟和喝酒,button绑定的点击事件中的语句是this.student.hobby[0] = "学习";,之后再输出app.student.hobby,可以发现数据确实已经改变,但是页面是没有相应变化的,因为这样通过数组下标来改变数据的方式,vue监测不到

正确写法:this.student.hobby.splice(0,1,"学习");

总结一下

1.vue会监视data中所有层次的数据

vue监视的数据都是响应式的

2.如何监测对象中的数据

通过setter实现监视,且要在new Vue时就传入要监测的数据

(1).对象中后追加的属性,Vue默认不做响应式处理

(2).如需给后添加的属性做响应式处理

Vue.set(target, propertyName/index, value) 

app.$set(target, propertyName/index, value)

3.如何监测数组中的数据?

通过包裹数组更新元素的方法实现,本质上就是做了两件事:

  • 1.调用原生对应的方法对数组进行更新(push()、pop()、、、)
  • 2.重新解析模版,进而更新页面

4.在Vue中修改数组中的某个元素一定要用如下方法:

  • 1.使用这些API: push()、pop()、shift()、unshift()、splice()、sort()、reverse() 注意:以上为变更方法,会变更调用了这些方法的原始数组。也有非变更方法,例如filter()、concat()和slice(),它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组直接替换旧数组
  • 2.Vue.set()或app.$set()

特别注意:Vue.set()和app.$set()不能给app或者app的根数据对象(app._data)添加属性

(target参数不可以是app或者app._data)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • ES6 Proxy实现Vue的变化检测问题

    Vue变化检测Object使用DefineProperty.数组使用方法拦截实现.最近,Vue3.0将采用ES6 Proxy的形式重新实现Vue的变化检测,在官方还没给出新方法之前,我们先实现一个基于Proxy的变化检测. 模块划分 参照之前Vue变化检测的代码,将Vue 变化检测的功能分为以下几个部分. Observer Dep Watcher Utils 首先,我们要确定的问题是,将Dep依赖搜集存在哪里.Vue 2.x里,Object的依赖收集放在defineRactive,Array的依

  • vue中遇到的坑之变化检测问题(数组相关)

    最近在项目中遇到了一个问题,不知道为什么,所以最后通过动手做demo实践.查文档的方式解决了,这里做一个总结. 例1 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="https://unpkg.com/vue@2.3.3/dist/vue.

  • 关于vue中watch检测到不到对象属性的变化的解决方法

    前言 在vue开发的过程中发现一个问题:改变vue.$data中对象的属性,watch是观测不到变化,但其实对象的属性是有变化的.这--,有点难以置信! 正文 <template> <div> <dl>name: {{option.name}}</dl> <dl>age: {{option.age}}</dl> <dl> <button @click="updateAgeTo25">upda

  • vue检测对象和数组的变化分析

    在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态.可以直接在子组件修改对象或数组,但是并不会数据改变就会引起变化. 检测对象变化 1.不能检测到对象属性的添加或删除 var vm = new Vue({ data:{ data111:{ a = 1 } } }) data111.a = 2;//这个可以引起变化 但data111.b = 2:和vm.b = 2这个不能检测到变化 需要用 Vue.set(o

  • Vue检测屏幕变化来改变不同的charts样式实例

    css中我们经常会通过媒体查询就可以完成对不同的屏幕展现不同的样式 在js中我们也可以通过检测屏幕的变化来展现不同的样式 在我的实例中:因为第一次打开也不知道到底是应该展示哪一个屏幕,所以会进行先判断一次,之后用addEventListener来是实现功能,暂时是通过这种方式实现的,以后有更好的方法再更新... mounted() { this.checkScreen() }, methods: { // 屏幕检测变化 checkScreen() { var _this = this if (d

  • vue watch自动检测数据变化实时渲染的方法

    本文介绍了vue watch自动检测数据变化实时渲染的方法,分享给大家,具体如下: 首先确认 watch是一个对象,一定要当成对象来用. 对象就有键,有值. 键:就是你要监控的那个家伙,比如说$route,这个就是要监控路由的变化.或者是data中的某个变量. 值可以是函数:就是当你监控的家伙变化时,需要执行的函数,这个函数有两个形参,第一个是当前值,第二个是变化后的值. 值也可以是函数名:不过这个函数名要用单引号来包裹. 第三种情况厉害了. 值是包括选项的对象:选项包括有三个. 第一个hand

  • Vue 检测变化的注意事项

    目录 深入响应式原理 如何追踪变化 检测变化的注意事项 对于对象 对于数组 声明响应式 property 异步更新队列 深入响应式原理 Vue 最独特的特性之一,是其非侵入性的响应式系统.数据模型仅仅是普通的 JavaScript 对象.而当你修改它们时,视图会进行更新.这使得状态管理非常简单直接,不过理解其工作原理同样重要,这样你可以避开一些常见的问题.在这个章节,我们将研究一下 Vue 响应式系统的底层的细节. 如何追踪变化 当你把一个普通的 JavaScript 对象传入 Vue 实例作为

  • Vue不能检测到数据变化的几种情况说明

    目录 Vue不能检测到数据变化的情况 第一类:对于数组 第二类:对于对象 Vue检测数据的原理 总结一下 Vue不能检测到数据变化的情况 Vue 实现了数据的双向绑定,所以我们在更改数据时,页面就会实时的反映出修改的变化 但是由于javascript 的限制,有几种情况,vue是不能检测到数据变化的 第一类:对于数组 1. 当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue 2. 当你修改数组的长度时,例如: vm.items.length =

  • vue select选择框数据变化监听方法

    1.使用v-model在select标签上进行数据双向绑定, 2.在data里边添加val:' ', 3.最后就是监听事件的写法,写在methods之外. 附加:(以下图片借鉴他人,非原创) 以上这篇vue select选择框数据变化监听方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • vue项目中的数据变化被watch监听并处理

    目录 vue数据变化被watch监听处理 监听当前vue文件数据 监听vuex中的数据 如何正确使用watch监听属性变化 基本用法 监听object 初始化变量触发监听回调 vue数据变化被watch监听处理 监听当前vue文件数据 例如,当前的vue文件的data中有如下属性: data() {     return {         dialogFormVisible: false,     } } 要监听dialogFormVisible变量的数据变化,则代码如下: watch: {

  • Vue实现动态响应数据变化

    Vue是MVVM模式,即Model-View-ViewModel,通过绑定数据即可以实时改变视图显示. 比如:使用v-blink动态绑定属性 <div v-blink:class="property"></div> 使用v-html来绑定带有标签的内容(会解析标签) <div v-blink:class="property" v-html="content"></div> 使用v-text来绑定纯文

  • 小程序使用watch监听数据变化的方法详解

    众所周知,Vue中,可以使用监听属性 watch来观察和响应 Vue 实例上的数据变化,那么小程序能不能实现这一点呢? 监听器的原理,是将data中需监听的数据写在watch对象中,并给其提供一个方法,当被监听的数据的值改变时,调用该方法.​​ 我们需要用到Javascript中的Object.defineProperty()方法,来手动劫持对象的getter/setter,从而实现给对象赋值时(调用setter),执行watch对象中相对应的函数,达到监听效果. Object.definePr

  • vue组件中的数据传递方法

    Vue 的组件作用域都是孤立的,不允许在子组件的模板内直接引用父组件的数据.必须使用特定的方法才能实现组件之间的数据传递.组件之间传递数据大致分为三种情况: 父组件向子组件传递数据,通过 props 传递数据. 子组件向父组件传递数据,通过 events 传递数据. 两个同级组件之间传递数据,通过 event bus 传递数据. 一.父组件向子组件传递数据 子组件部分: <template> <div class="child"> {{ msg }} </

  • vue中for循环更改数据的实例代码(数据变化但页面数据未变)

    废话不多说了,直接给大家贴代码了,具体代码如下所示: let that = this; for(let i = 0;i<that.tableData.length;i++){ this.tableData[i].zzzk = this.midForm.zzzk; console.log(this.tableData[i].zzzk) this.tableData[i].zhje = this.tableData[i].zzzk * this.tableData[i].dj * this.tabl

  • 详解Vue监听数据变化原理

    本人最近在学习Vue,从网上查询了很多关于Vue监听数据变化原理,稍微整理精简一下做下分享. 浅度监听 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>浅度监听</title> <meta name="viewport" content="width=device-wi

  • vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】

    本文实例讲述了vue自定义键盘信息.监听数据变化的方法.分享给大家供大家参考,具体如下: @keydown.up @keydown.enter @keydown.a/b/c.... 自定义键盘信息: Vue.directive('on').keyCodes.ctrl=17; Vue.directive('on').keyCodes.myenter=13; @keydown.a/b/c.... <input type="text" @keydown.c="show&quo

随机推荐