vue中的数据双向绑定与nextTick

在理解nextTick之前要先理解一下VUE中的双向数据绑定

vue的响应式对象,是利用了Object.defineProperty拦截数据,重新定义了对象获取属性值(get)和设置属性值(set)。

官网是这么写的:

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。在这里插入图片描述

当get时,打印出来get ${key}-${val}
当set时,则打印出来set ${key} - ${val} - ${newVal} - newVal is Object
数据劫持方法Object.defineProperty()是直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符。
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: () => {
      console.info(`get ${key}-${val}`)
      return val;
    },
    set: (newVal) => {
      // 如果 newVal 和 val 相等,则不做任何操作(不执行渲染逻辑)
      if (newVal === val) {
        return;
      }
      // 如果 newVal 和 val 不相等,且因为 newVal 为 Object, 所以先用 Observer迭代 newVal, 使之 reactive, 再用 newVal 替换掉 val, 再执行对应操作(渲染逻辑)
      else if (isObject(newVal)) {
        console.info(`set ${key} - ${val} - ${newVal} - newVal is Object`);
        new Observer(newVal);
        val = newVal;
      }
      // 如果 newVal 和 val 不相等,且因为 newVal 为基础类型, 所以用 newVal 替换掉 val, 再执行对应操作(渲染逻辑)
      else if (!isObject(newVal)) {
        console.info(`set ${key} - ${val} - ${newVal} - newVal is Basic Value`);
        val = newVal;
      }
    }
  })
}

这就是vue能够实现双向绑定的原因。
这里需要再提一下,vue的异步更新队列。vue的响应是异步的。
DOM树构成了WEB页面,树的本质是数据结构。虚拟DOM是为了能够解决浏览器的性能而设计出来的。

DIFF算法:
用来计算虚拟DOM中被改变的部分,针对这一部分进行原生DOM操作而不用渲染整个页面。
DIFF的三大策略:

  1. Tree Diff :DOM一层一层地比较
  2. Component Diff : 数据层面地差异比较
  3. Element Diff :真实DOM渲染

这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。

有时需要将所有数据加载完成后再更新DOM,则用到了nextTick

为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

在组件中使用nextTick
官网例子:

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '未更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '已更新'
      console.log(this.$el.textContent) // => '未更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '已更新'
      })
    }
  }
})

可以使用await语句来实现同样的操作

methods: {
  updateMessage: async function () {
    this.message = '已更新'
    console.log(this.$el.textContent) // => '未更新'
    await this.$nextTick()
    console.log(this.$el.textContent) // => '已更新'
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值