vue:双向数据绑定

监听变化

Vue实例中的数据保存在该实例的data属性中,当数据对象传入data中时,Vue会遍历该对象所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter,在属性被访问(get)时调用getter获取属性值。

Vue实例中每个组件都有对应的watcher对象,在组件渲染的过程中watcher对象把组件中的属性记录为依赖,当依赖的属性修改(set)时调用setter通知watcher对象,从而触发re-render重新计算组件进而更新virtual DOM树。

data

注意事项

Vue 实例是在初始化(create)阶段将属性转化为getter/setter的(在mount阶段为组件添加watcher),只有在初始化之前已经存在于data对象的属性才能被Vue转化并实现响应,初始化之后添加和删除的对象属性无法被检测到。

var vm = new Vue({
    data:{
        a:1
    }
})
// vm.a 追踪变化
vm.b = 2
// vm.b 不追踪变化

Vue无法在data对象中添加响应属性,如果有需要添加的响应属性必须在data对象声明,即使是空值。

如果在html中使用了未声明的数据属性,Vue会抛出错误,视图中 {{ }} 会视该属性为空 ,v-if v-show会判断为fasle。 

var vm = new Vue({
    data: {
        a:1,
        b:'',
    }
})
vm.b = 2// 追踪变化

Vue实例中data对象内部可以添加响应属性。

Vue提供了Vue.set(object, key, value) 方法用来添加要响应属性到data对象内部。

vm.a.a = 1
//vm.a.a 为1 不追踪变化

Vue.set(vm.a, 'b', 2)
//vm.a.b 为2 追踪变化 

this.$set(this.a,'b',2)
//vm.a.b 为2 追踪变化

区别:vm.$set为实例方法, Vue.set为全局方法。

使用 Object.assign()方法来添加到对象上的新属性由于没有转化getter/setter,故同样不会触发更新。

可以通过创建一个包含原对象属性和新属性的新对象,并赋值给原对象来实现添加响应属性。

//Object.assign(this.a, { c: 1, d: 2 })
//vm.a.c 为1 vm.a.d 为2 不会追踪变化

this.a = Object.assign({}, this.a, { c: 1, d: 2 })
//vm.a.c 为1 vm.a.d 为2 追踪变化

这里相当于利用了data对象对data内部属性的监听响应来实现data内部属性的更新,由于a是data对象的属性且a可以追踪变化,所以当a被重新赋值,其内部所有属性都会转化getter/setter,故可以被追踪变化。

DOM更新

Vue 使用异步方式执行 DOM 更新。只要观察到数据变化,Vue会将处在当前事件循环中发生的所有数据改变缓存起来,并开启一个队列,如果同一个 watcher 被多次触发,只会被推入到队列中一次,从而实现去除重复数据,避免不必要的计算和 DOM 操作。在下一个事件循环“tick”中,Vue 刷新队列并执行(已去重的) 工作。

Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。

鉴于Vue对DOM异步更新的特性,在数据改变之后立刻进行DOM操作则该DOM元素会处于未更新状态,如果要在Vue 完成DOM更新之后进行DOM操作,则要在数据变化之后立即使用 Vue.nextTick(callback) 方法,callback回调函数将在在 DOM 更新完成后调用。

var vm = new Vue({
    el: '#ele',
    data: {
        a: 1
    }
})
vm.a = 2 // 更改数据

vm.$el.textContent === 2 // false

Vue.nextTick(function () {
    vm.$el.textContent === 2 // true
})

在组件内使用 vm.$nextTick() 回调函数中的 this 将自动绑定到当前的 Vue 实例上

Vue.component('tpl', {
    template: '<span>{{ a }}</span>',
    data: function () {
        return {a:1}
    },
    methods: {
        tplUpdateData: function () {
            this.a = 2
            console.log(this.$el.textContent) // => '没有更新'
            this.$nextTick(function () {
                console.log(this.$el.textContent) // => '更新完成'
            })
        }
    }
})

区别:vm.$nextTick为实例方法, Vue.nextTick为全局方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值