vue data 响应式

vue data 响应式,第1张

概念理解

类型

Object | Function

限制

组件的定义只接受 function

详细

Vue 实例的数据对象。Vue 会递归地把 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对象,原型上的 property 会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。

一旦观察过,你就无法在根数据对象上添加响应式 property。因此推荐在创建实例之前,就声明所有的根级响应式 property。

实例创建之后,可以通过 vm.$data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的 property,因此访问 vm.a 等价于访问 vm.$data.a

以 _ 或 $ 开头的 property 不会被 Vue 实例代理,因为它们可能和 Vue 内置的 property、API 方法冲突。你可以使用例如 vm.$data._property 的方式访问这些 property。

当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。

如果需要,可以通过将 vm.$data 传入 JSON.parse(JSON.stringify(...)) 得到深拷贝的原始数据对象。

示例

var data = { a: 1 }

// 直接创建一个实例
var vm = new Vue({
  data: data
})
vm.a // => 1
vm.$data === data // => true

// Vue.extend() 中 data 必须是函数
var Component = Vue.extend({
  data: function () {
    return { a: 1 }
  }
})

注意:如果你为 data property 使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。

data: vm => ({ a: vm.myProp })

常用

常见问题 数组类型拦截

vue2通过改写数组原型,监听(改写)数组自身的方法来实现push、pop、shift、unshift、splice、reverse、sort 七种方法。当我们使用这些方法的时候会触发拦截器,监听到数据对象变化

data(){
	return {
		arr: [1,2,3,4]
	}
}
 
method: {
	changeArr(){

        // 都会触发 watch 监听
		this.arr.push(5);
        this.arr.pop();
        this.arr.shift(6);
        this.arr.unshift();
        this.arr.splice(1,1);
        this.arr.reverse();
        this.arr.sort((a,b)=> a-b);
	}
}

watch: {

    arr(cur, old){
        // ......
    }
    
}

vue2 使用defineProperty,虽然可以实现修改索引触发更新,但是,给数组的每一项都进行了数据劫持,这样是有性能问题的,而且数组的属性可能是各种各样的,比如: 函数、length。因此源码中没有采用这个方法,所以 修改数组的索引或者length也不会触发视图更新(直接arr[0]=xx不能被监控)

watch 监听失败

watch 不能监听深层对象的变化

例子一


data(){
	return {
		person:{
			name:"小虽",
            age: 0
		}
	}
}
 
method: {
	changeAge(){
		this.person.age = 24;
	}
}

watch: {

    // 调用changeAge 改变 person.age 无法被监听
    person(cur, old){
        //......
    },

    // 正确的 *** 作方式
    person: {
        handler(cur, pre){
            // ......
        },
        deep: true
    }
    
}

例子二

data(){
	return {
		person:{
			name:"小虽"
		}
	}
},

method:{
	changeAge(){
		this.person.age = 24;
	}
},

watch: {
    person: {
        handler(cur, pre){
            // ......
        },
        deep: true
    }
}

调用changeAge 函数之后 watch 不能监听到 person对象变化,原因是 person.age 不是一个响应式的,修改 data中初始化person的时候指明age属性。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/945923.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-18
下一篇 2022-05-18

发表评论

登录后才能评论

评论列表(0条)

保存