深入理解vue响应式原理

深入理解vue响应式原理

Vue最显著的特性之一便是不太引人注意的响应式系统(reactivity system)。模型层(model)只是普通JS对象,修改它则更新视图(view)。这会让状态管理变得非常简单且直观,不过理解它的工作原理以避免一些常见的问题也是很重要的。

本文将详细介绍Vue响应式系统的底层细节。

追踪变化

把一个普通JS对象传给Vue实例的data选项,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter。

Object.defineProperty是仅ES5支持,且无法shim的特性,这也就是为什么Vue不支持IE8浏览器的原因。

立即学习“前端免费学习笔记(深入)”;

用户看不到getter/setter,但是在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化

每个组件实例都有相应的watcher实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

1.png

变化检测

受现代JS的限制(以及废弃 Object.observe),Vue不能检测到对象属性的添加或删除。由于Vue会在初始化实例时对属性执行 getter/setter转化过程,所以属性必须在data对象上存在才能让Vue转换它,这样才能让它是响应的。

var vm = new Vue({  data:{    a:1  }})// `vm.a` 是响应的vm.b = 2// `vm.b` 是非响应的

登录后复制

Vue不允许在已经创建的实例上动态添加新的根级响应式属性(root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上。

Vue.set(vm.someObject, 'b', 2)

登录后复制

也可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名。

this.$set(this.someObject,'b',2)

登录后复制

有时想向已有对象上添加一些属性,例如使用Object.assign()或 _.extend()方法来添加属性。但是,添加到对象上的新属性不会触发更新。在这种情况下可以创建一个新的对象,让它包含原对象的属性和新的属性。

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

登录后复制

声明响应式属性

由于Vue不允许动态添加根级响应式属性,所以必须在初始化实例前声明根级响应式属性,哪怕只是一个空值。

var vm = new Vue({  data: {    // 声明 message 为一个空值字符串    message: ''  },  template: '
{{ message }}
'})// 之后设置 `message` vm.message = 'Hello!'

登录后复制

如果在data选项中未声明 message,Vue将警告渲染函数在试图访问的属性不存在。

这样的限制在背后是有其技术原因的,它消除了在依赖项跟踪系统中的一类边界情况,也使Vue实例在类型检查系统的帮助下运行的更高效。

而且在代码可维护性方面也有一点重要的考虑:data 对象就像组件状态的概要,提前声明所有的响应式属性,可以让组件代码在以后重新阅读或其他开发人员阅读时更易于被理解。

异步更新队列

Vue异步执行DOM更新。只要观察到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个watcher被多次触发,只会一次推入到队列中。

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

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

例如,当设置vm.someData=’new value’,该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况不需要关心这个过程,但是如果想在DOM状态更新后做点什么,这就可能会有些棘手。

虽然Vue.js通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时确实要这么做。为了在数据变化之后等待Vue完成更新DOM ,可以在数据变化之后立即使用Vue.nextTick(callback) 。这样回调函数在DOM更新完成后就会调用。

{{message}}

登录后复制

var vm = new Vue({  el: '#example',  data: {    message: '123'  }})vm.message = 'new message' // 更改数据vm.$el.textContent === 'new message' // falseVue.nextTick(function () {  vm.$el.textContent === 'new message' // true})

登录后复制

在组件内使用vm.$nextTick()实例方法特别方便,因为它不需要全局Vue,并且回调函数中的this将自动绑定到当前的Vue实例上:

Vue.component('example', {  template: '{{ message }}',  data: function () {    return {      message: '没有更新'    }  },  methods: {    updateMessage: function () {      this.message = '更新完成'      console.log(this.$el.textContent) // => '没有更新'      this.$nextTick(function () {        console.log(this.$el.textContent) // => '更新完成'      })    }  }})

登录后复制

相关推荐:2020年前端vue面试题大汇总(附答案)vue教程推荐:2020最新的5个vue.js视频教程精选

更多编程相关知识,请访问:编程入门!!

以上就是深入理解vue响应式原理的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/3023179.html

(0)
上一篇 2025年3月13日 06:04:15
下一篇 2025年3月6日 06:44:05

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Vue.js 学习之二:数据驱动开发

    vue.js教程栏目介绍vue.js学习之二的数据驱动开发 。 –>    登录后复制 在这里,我主要做了如下修改: 首先,在标签中增加了一个v-show指令,该指令可用于绑定一个布尔类型的数据(即这里的isShow),以…

    2025年3月13日
    200
  • Vue中怎么对事件进行防抖和节流操作?

    有些浏览器事件可以在短时间内快速触发多次,比如调整窗口大小或向下滚动页面。例如,监听页面窗口滚动事件,并且用户持续快速地向下滚动页面,那么滚动事件可能在 3 秒内触发数千次,这可能会导致一些严重的性能问题。 如果在面试中讨论构建应用程序,出…

    2025年3月13日
    200
  • 深入了解vue.js中的diff算法

    本篇文章给大家详细了解一下vue.js中的diff算法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 前言 我的目标是写一个非常详细的关于diff的干货,所以本文有点长。也会用到大量的图片以及代码举例,目的让看这篇文章的…

    2025年3月13日 编程技术
    200
  • 浅谈vue.js中的Props(单向数据流)

    prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。 另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组…

    2025年3月13日
    200
  • 详解vue.js中watch的使用

    在vue中,使用watch来响应数据的变化。watch的用法大致有三种。下面代码是watch的一种简单的用法: 登录后复制登录后复制 new Vue({  el: ‘#root’,  data: {    cityName: ‘shangh…

    2025年3月13日
    200
  • 深入浅析With的使用

    with用于扩展一个语句的作用域链,但一般情况下不建议使用with语句,因为它可能是引起混淆错误和兼容性问题的根源。在Vue源码中有使用with语句的功能点,因此在这里将简介其功能,以助于阅读框架源码。 性能的利与弊 利 with语句可以在…

    2025年3月13日
    200
  • 浅谈Vue.use到底是什么?

    Vue.use到底是什么鬼、下面本篇文章就来给大家介绍一下Vue.use。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 我们在使用Vue做项目开发的时候,看到不少轮子都是通过Vue.use来进行使用,感觉甚是高大上。 不…

    2025年3月13日
    200
  • 浅谈Vue.js中双向绑定的原理及实现方法

    Vue最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的JavaScript对象。而当你修改它们时,视图会进行更新。vue通过双向绑定实现,本文就来为大家介绍一下vue双向绑定原理及实现方法。 本文主要介绍两大内容: 1. v…

    2025年3月13日 编程技术
    200
  • 详解vue.js中如何处理事件

    下面vue.js教程给大家介绍一下使用vue.js处理事件的方法,希望对大家有一定的帮助。 当您使用Vue构建动态网站时,您很可能希望它能够响应事件。 例如,如果用户单击按钮,提交表单,甚至只是移动鼠标,您可能希望您的Vue网站以某种方式做…

    2025年3月13日
    200
  • 实现带有进度条的Vue延迟加载

    下面vue.js栏目给大家介绍一下给vue的惰性加载添加进度条的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 简介 通常用 Vue.js 编写单页应用(SPA)时,当加载页面时,所有必需的资源(如 JavaScri…

    2025年3月13日
    200

发表回复

登录后才能评论