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重新计算,从而致使它关联的组件得以更新。

变化检测

受现代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' // false

Vue.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) // => '更新完成'

})

}

}

})

vueweb端响应式布局_vue响应式原理图文详解相关推荐

  1. html响应式布局ipad,响应式布局(Responsive design)

    意在实现不同屏幕分辨率的终端上浏览网页的不同展示方式.通过响应式设计能使网站在手机和平板电脑上有更好的浏览阅读体验. 步骤 1.布局及设置meta标签 当创建一个响应式网站,或者非响应式网站变成响应式 ...

  2. html响应式布局效果图,响应式网页布局的实现方法原理

    昨天我在马海祥博客上跟大家详细的介绍过<什么是响应式网页设计?>,我觉的响应式网页设计不仅仅是一种趋势,还更是一个新的设计解决方案!它有助于解决不同的分辨率和设备(台式电脑,笔记本电脑,平 ...

  3. 流式布局与响应式布局

    常见的面试题会让你聊一聊流式布局与响应式布局,我还没遇到过直接问他俩区别的面试官,都是根据我的项目(里面有用到流式布局+响应式布局). 围绕这两点感觉网上大部分博客都长得差不多,那我就用自己粗浅的理解 ...

  4. 什么是响应式布局?响应式布局有几种方法?

    目录 什么是响应式布局? 响应式布局的4种方法 媒体查询 百分比 vw/vh rem 什么是响应式布局? 响应式布局是同一页面在不同的屏幕上有不同的布局,即只需要一套代码使页面适应不同的屏幕 响应式布 ...

  5. css三种定位都脱离文档流了吗,CSS布局之脱离文档流详解——浮动、绝对定位脱离文档流的区别...

    1.代码 (1)示例代码1 CSS布局之脱离文档流详解--浮动.绝对定位脱离文档流的区别 .left { width: 300px; height: 500px; background: red; f ...

  6. 七、Oracle11g R2服务端卸载图文详解过程

    Oracle11g R2服务端卸载图文详解过程 注:由于Oracle 11g R2服务端安装的时候已经包含了客户端,所以服务端的卸载方案跟客户端的一样,也就是说,客户端卸载按照以下步骤同样适用. 一. ...

  7. 静态布局、自适应布局、流式布局、响应式布局、弹性布局简析、BFC

    静态布局:给页面元素设置固定的宽度和高度,单位用px,当窗口缩小,会出现滚动条,拉动滚动条显示被遮挡内容.针对不同分辨率的手机端,分别写不同的样式文件.例如:浏览器窗口是1000px,那么最小的宽度是 ...

  8. 响应式布局(响应式网页的构成bootstrap框架)

    一.响应式布局 1.概念 响应式又叫自适应网页,可以根据网页窗口的调整而自动布局,不会导致页面效果的错乱,主要是针对移动端浏览器:通过响应式布局,可以使一套代码同时兼容多个尺寸的屏幕 2.响应式网页的 ...

  9. html响应式布局平移,响应式网页设计、响应式布局的实现原理

    概念 响应式网页设计最初是由 Ethan Marcotte 提出的一个概念:为什么一定要为每个用户群各自打造一套设计和开发方案?Web设计应该做到根据不同设备环境自动响应及调整.当然响应式Web设计不 ...

最新文章

  1. C# Winform 启动和停止进程
  2. 《强化学习周刊》第25期:DeepMind提出无模型风险敏感强化学习、谷歌发布 RLDS数据集生态系统...
  3. 分享Silverlight/WPF/Windows Phone一周学习导读(07月25日-07月31日)
  4. Haskell / GHC中的“ forall”关键字有什么作用?
  5. java query类是什么类_java – 从包生成QueryDsl Q类
  6. android webservices 返回多行多列数据,Pandas: 如何将一列中的文本拆分为多行?
  7. camuda流程引擎如此简单「五」
  8. linux mint图标大小,Cinnamon:LinuxMint 15桌面设置小技巧
  9. eShopOnContainers 知多少[7]:Basket microservice
  10. POJ 2590 Steps (ZOJ 1871)
  11. oracle model类型,Oracle SQL高级编程——Model子句全解析-Oracle
  12. Codeforces Round #342 (Div. 2) D. Finals in arithmetic(想法题/构造题)
  13. php PHP-FPM进程数的设定
  14. 数据抓取的艺术(一~三):Selenium+Phantomjs数据抓取环境配置
  15. win7 专业版 破解教程
  16. Php 生成随机字符串函数集成
  17. 白名单模板_亚马逊白名单申请流程全解析
  18. Wang Changyu
  19. JQData提供哪些数据
  20. 美团点评java开发面试问题

热门文章

  1. oracle中sysdate的变更,oracle – 使用sysdate的to_date函数
  2. 1/1+1/3+1/5+……+1/99的和
  3. 【转载】图解 Python 深拷贝和浅拷贝
  4. 两种生成对称正定矩阵的方法
  5. 【吐血推荐】B站最强最全的学习资源(人工智能,深度学习,机器学习,Python,C/C++)
  6. 【Alios-things笔记】EMW3060 Socket编程
  7. android 多个fragment切换,一个Activity中多个Fragment的切换
  8. Selenium知识
  9. 【渗透测试笔记】之【SQLMap】
  10. 嵌入式开发学习之--点亮LED灯(上)