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

 更新时间:2022年08月12日 09:49:28   作者:A黄俊辉A  
这篇文章主要介绍了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)

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

相关文章

  • 浅谈vue 二级路由嵌套和二级路由高亮问题

    浅谈vue 二级路由嵌套和二级路由高亮问题

    这篇文章主要介绍了浅谈vue 二级路由嵌套和二级路由高亮问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Vue.js 2.0学习教程之从基础到组件详解

    Vue.js 2.0学习教程之从基础到组件详解

    这篇文章主要介绍了Vue.js 2.0从基础到组件的相关资料,文中介绍的非常详细,对大家学习或者使用vue.js具有一定的参考价值,需要的朋友可以参考学习,下面来一起看看吧。
    2017-04-04
  • vue.js父组件使用外部对象的方法示例

    vue.js父组件使用外部对象的方法示例

    在我们日常开发中经常因为思维定式,我们会犯一些奇怪的错误,有时候看似简单的问题却给出了复杂的解决方案。下面这篇文章主要介绍了vue.js父组件使用外部对象的方法,这个看似简单却绕了一些弯路的问题,有必要和大家分享下,需要的朋友可以参考学习,下面来看看吧。
    2017-04-04
  • 基于vue+canvas的excel-like组件实例详解

    基于vue+canvas的excel-like组件实例详解

    a vue component,基于vue的表格组件,主要解决大数据量的表格渲染性能问题,使用canvas绘制表格,同时支持类似excel的批量选中,复制黏贴删除,实时编辑等功能.这篇文章主要介绍了基于vue+canvas的excel-like组件,需要的朋友可以参考下
    2017-11-11
  • Vue2 Watch监听操作方法

    Vue2 Watch监听操作方法

    这篇文章主要介绍了Vue2 Watch监听,通过watch监听器,我们可以实时监控数据的变化,并且在数据发生改变时进行相应的操作,需要的朋友可以参考下
    2023-12-12
  • vue中实现点击按钮滚动到页面对应位置的方法(使用c3平滑属性实现)

    vue中实现点击按钮滚动到页面对应位置的方法(使用c3平滑属性实现)

    这篇文章主要介绍了vue中实现点击按钮滚动到页面对应位置的方法,这段代码主要使用c3平滑属性实现,需要的朋友可以参考下
    2019-12-12
  • vue实现滚动鼠标滚轮切换页面

    vue实现滚动鼠标滚轮切换页面

    这篇文章主要为大家详细介绍了vue实现滚动鼠标滚轮切换页面,类似于纵向走马灯,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • vue3如何使用element-plus的dialog

    vue3如何使用element-plus的dialog

    这篇文章主要介绍了vue3优雅的使用element-plus的dialog,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • vue实现计算器封装

    vue实现计算器封装

    这篇文章主要为大家详细介绍了vue实现计算器的封装,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • vue中使用file-saver导出文件的全过程记录

    vue中使用file-saver导出文件的全过程记录

    这篇文章主要给大家介绍了关于vue中使用file-saver导出文件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-02-02

最新评论