关闭

Vue的响应式原理

标签: vuejavascript对象响应式原理watcher
610人阅读 评论(0) 收藏 举报
分类:

下面的是一张来自Vue官网的图片:

追踪变化

如何追踪变化??

当把一个普通的JavaScript对象传递给Vue实例的data选项,Vue将遍历这个对象的所有属性,并且利用Object.defineProperty这些属性全部转换为getter/setter,当然由于兼容性问题,所以Vue不支持IE8及更低版本的浏览器

从上面的图可以看出,对于数据Data来说,它里面的getter与setter是对于外部是不可见的,但是在内部完全可以使用它们,在内部,通过Vue进行追踪依赖,当属性被修改或者访问时通知变化。每个组件的实例都会有相应的watcher实例对象,它会在组件渲染的过程中将属性记为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而让和它相关联的组件得以更新

变化的检测问题

受现代浏览器的限制(以及废弃的Object.observe),Vue不能检测到对象属性的添加或者删除,由于Vue在初始的时候就会对属性实行getter/setter转换过程,所以属性必须存在于data对象时才能让Vue转换它,这样它才是响应的,这段话的意思等同于下面的代码:

        //初始化之前写在data中的可以让Vue转换它,所以a是响应的
        var v = new Vue({
            data : {
                a : 1
            }
        });

        //初始化之后添加的属性b是非响应的
        v.b = 2;

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

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

也可以使用v.$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: '<div>{{ message }}</div>'
})
// 之后设置 `message` 
vm.message = 'Hello!'

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

这样的限制,消除了在依赖项跟踪系统的一类边界情况,也使Vue实例在类型检查系统的帮助下运行的更高效,而且在代码可维护性方面也有所考虑,data对象就像组件状态的概要,提前声明所有的响应式属性,可以让组件代码在以后阅读或开发人员阅读时更易于被理解

异步更新队列

Vue异步执行DOM更新,只要观察到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的数据改变,如果同一个watcher被多次触发,只会一次推入到队列中。这种缓冲时去除重复数据对于避免不必要的计算和DOM操作上非常重要,然后,在下一个的事件循环”tick”中,Vue刷新队列并执行实际(已去重的)工作。Vue在内部尝试对异步队列使用原生的promise.thenMutationObserver,如果执行环境不支持,会采用setTimeout(fn, 0)代替

例如,当你设置了vm.someData = 'new value',该组件不会立即重新渲染,当刷新队列时,组件会在事件循环队列清空的下一个”tick”更新,多数情况下我们不需要关心这个过程,但是如果你想在DOM状态更新后做点什么,这就可能会有点困难,为了使得数据变化之后等待Vue完成更新DOM,可以在数据变化之后立即使用Vue.nextTick(callback) 这样回掉函数在DOM更新后就会调用。

    <div id="example">{{message}}</div>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#example',
            data: {
                message: '123'
            }
        });
        vm.message = 'new message' // 更改数据
        console.log(vm.$el.textContent);   //123

        Vue.nextTick(function () {
            alert(2323);
            console.log(vm.$el.textContent);  //new message
        });
    </script>

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

        Vue.component('my-component', {
            template: '<span> {{message}}</span>',
            data : function() {
                return {
                    message: 'not update'
                }
            },
            methods : {
                updateMessage : function() {
                    this.message = 'update';
                    console.log(this.$el.textContent);  //'not update'
                    this.$nextTick(function() {
                       console.log(this.$el.textContent); //'update'
                    });
                }
            }
        });

参考:https://cn.vuejs.org/v2/guide/reactivity.html

0
0
查看评论

Vue.js内部响应式原理探究

深入vue响应式原理 大部分的基础内容我们已经讲到了,现在讲点底层内容。Vue.js 最显著的一个功能是响应系统 —— 模型只是普通对象,修改它则更新视图。这让状态管理非常简单且直观,不过理解它的原理也很重要,可以避免一些常见问题。下面我们开始深挖 Vue.js 响应系统的底层细节。 如何追踪变...
  • john1337
  • john1337
  • 2016-11-08 13:30
  • 2089

vue 深入响应式原理 注意事项

对vue.js 的响应式的原理的理解,有助于更加灵活的使用vue,和避开一些坑 所以了解其运行原理十分重要
  • wngzhem
  • wngzhem
  • 2016-12-13 17:19
  • 907

vue2.x响应式原理,vue与react响应式简单对比

实现的最终目标const demo = new Vue({ data: { text: "before", }, // 对应的template 为 <div><span>{{text}}</span></div>...
  • SirM2z
  • SirM2z
  • 2017-05-05 13:16
  • 2031

vue笔记-----深入响应式原理

模型层只是普通的JavaScript对象,修改它则更新时图。这会让状态管理变得非常 简单且直观,不过理解它的工作原理以避免一些常见的问题也是很重要的。 如何追踪变化 把一个普通的JavaScript对象传给Vue实例的data选项,Vue将遍历此对象的搜游属性 ,并使用Object....
  • qq_34530330
  • qq_34530330
  • 2017-03-14 15:16
  • 622

Vue.js深入响应式原理

原文地址:http://vuejs.org.cn/guide/reactivity.html 因工作需要用到Vue.js,所以看了一下相关知识。 深入响应式原理 大部分的基础内容我们已经讲到了,现在讲点底层内容。Vue.js 最显著的一个功能是响应系统 —— 模型只是普通对象,修改它则更新视...
  • tanga842428
  • tanga842428
  • 2016-10-29 11:02
  • 2130

Vue 响应式原理

将data与dom绑定的原理 首先引用官网的一张图 要将data与dom绑定,首先要满足一下几点 1、Vue实例内预先定义了data 2、使用Vue.set(object, key, value)或者vm.$set(object, key, value)方法设置了data因为Vue实例创建的...
  • qq_18837459
  • qq_18837459
  • 2017-07-20 15:23
  • 175

vue学习总结:响应式系统&vue实例

响应式系统vue是一个帮助用户构建界面的前端框架,它的核心是一个响应式的数据绑定系统,通过数据来驱动页面显示的更新,而不是像jquery那样通过操作DOM来改变页面的显示。vue通过ViewModal来实现数据和DOM的双向数据绑定。这是如何实现的呢? 当我们把一个普通的js对象传给Vue实例的d...
  • crystal6918
  • crystal6918
  • 2017-03-14 20:13
  • 1119

响应式学习----从VUE1 到 VUE2

最近比较喜欢一张非常喜感的图。 其实最初的前端很简单,就跟这位大爷的说法差不多,直接拿起键盘,搞个编辑器然后打开浏览器就可以了,我相信包括我在内的很多人也就是这么单纯地喜欢上前端的,记得宇豪也是说喜欢前端就是因为CSS。 起初的前端,标准混乱,浏览器性能差,随着ajax和node出现带来的两...
  • allenliu6
  • allenliu6
  • 2017-08-31 22:34
  • 434

amaze-vue —— 基于Vue.js和amazeui样式的响应式UI框架

amaze-vue —— 基于Vue.js和amazeui样式的响应式UI框架
  • cn7997forever
  • cn7997forever
  • 2017-12-06 07:50
  • 81

【学习笔记】Vue响应式原理

一、vue中的响应式属性Vue中的数据实现响应式绑定1、对象实现响应式: 是在初始化的时候利用definePrototype的定义set和get过滤器,在进行组件模板编译时实现water的监听搜集依赖项,当数据发生变化时在set中通过调用dep.notify进行发布通知,实现视图的更新。 2、数组实...
  • heshan1992
  • heshan1992
  • 2017-08-25 22:40
  • 94
    个人资料
    • 访问:131853次
    • 积分:2399
    • 等级:
    • 排名:第18264名
    • 原创:135篇
    • 转载:9篇
    • 译文:0篇
    • 评论:15条
    博客专栏
    最新评论