Vue响应式原理详细讲解

简介: Vue响应式原理详细讲解

面试官:请你简单的说说什么是Vue的响应式。


小明:mvvm就是视图模型模型视图,只有数据改变视图就会同时更新。


面试官:说的很好,回去等通知吧。


小明:....


Vue响应式原理


先看官方的说法


0ea6d5e0b3d14036ac6100da2e486d2b.png


简单理解就是实例data,Vue通过遍历data中所有对象通过Observer劫持监听所以属性,然后数据一旦发生变化,就通知编译解析变化,更新视图。


首先创建一个data,需要将data变成响应式数据,创建Observer 函数传值data,如果data不是一个对象或者是空就不用处理直接return

 <script>
        function Observer(targer){
            if(typeof targer !== 'object' || targer ===null){
                return targer
            }
        }
        const data = {
            name:'海海',
            age:18,
            info:{
                address:'广州'
            },
            fava:[1,2,3,4,5]
        }
        Observer(data)
    </script

其他的处理


这里只处理数组,其他


判断是否等于数组,如果等于,如果不等于就循环target,声明响应式函数 defineReactive


传值targer,循环的key和targer[key],然后在 defineReactive调用我们的 Object.defineProperty

 function Observer(targer){
            if(typeof targer !== 'object' || targer ===null){
                return targer
            }
            if(Array.isArray(targer)) {
                // 数组
            }else{
                for(let key in targer){
                    // 响应式数据的函数
                    defineReactive(targer,key,targer[key])
                }
            }
        }

Object.defineProperty


  (Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。)


传入我们的参数


拿到get set方法


get


初始值 直接return 我们的value


set


第一个参数是最新的值 newValue


判断如果我们传入的value和newValue不相等,那么就把newValue赋值给value

        function defineReactive(targer,key,value){
            Object.defineProperty(targer,key,{
                get(){
                    return value
                },
                set(newValue){
                    if(newValue !== value) {
                        value =newValue
                    }
                }
            })
        }

   

那么问题又来了,如果是一个对象需要监听,我们刚刚的操作只监听到了第一层,如果监听的内容是上面的info就相当于监听了整个对象,答案也很简单,我们只需要在调用defineReactive的时候在调用一次Observer在进入一次循环,当不是object就自动结束了

        function defineReactive(targer,key,value){
            Observer(value)
            Object.defineProperty(targer,key,{
                get(){
                    return value
                },
                set(newValue){
                    if(newValue !== value) {
                        value =newValue
                    }
                }
            })
        }

   

视图更新


我们这里在模仿一下视图更新 定义函数 updataView

        function updataView(){
            console.log('视图更新了')
        }

   

调用


727041968edf460ab1a40d03e03a6883.png


显示视图更新。


数组


先定义一个值 oldArrayProperty 然后将Array.prototype赋值给oldArrayProperty,


然后针对原型对象创建 Object.create()


定义一个 arrProto 来接收。


然后声明数组  ['push','pop','unshift','shift','reverse','sort','splice']  进行循环

   const oldArrayProperty =Array.prototype
   const arrProto = Object.create(oldArrayProperty)
   const fn = ['push','pop','unshift','shift','reverse','sort','splice']
        fn.forEach((method)=>{
            arrProto[method] = function(){
            } 
        })

然后调用更新视图 updataView  return 将oldArrayProperty对应的方法匹配上return出来

        const oldArrayProperty =Array.prototype
        const arrProto = Object.create(oldArrayProperty)
        const fn = ['push','pop','unshift','shift','reverse','sort','splice']
        fn.forEach((method)=>{
            arrProto[method] = function(){
                updataView()
                return oldArrayProperty[method].call(this,...arguments)
            } 
        })

 

然后回到Observer方法中,将arrProto赋值给 targer的__proto__原型链上,最后在将targer循环调用Observer,进行数据更新。

  if(Array.isArray(targer)) {
                // 数组
                targer.__proto__ =arrProto
                for(let i=0;i<targer.length;i++) {
                    Observer(targer[i])
                }
            }


测试


6a48386b5fc14b3aa6abd69ca6b503b8.png


到这里我们的监听数据变化并自动更新就完成了。


完整代码

    <script>
        function defineReactive(targer,key,value){
            Observer(value)
            Object.defineProperty(targer,key,{
                get(){
                    return value
                },
                set(newValue){
                    if(newValue !== value) {
                        value =newValue
                        updataView()
                    }
                }
            })
        }
        const oldArrayProperty =Array.prototype
        const arrProto = Object.create(oldArrayProperty)
        const fn = ['push','pop','unshift','shift','reverse','sort','splice']
        fn.forEach((method)=>{
            arrProto[method] = function(){
                updataView()
                return oldArrayProperty[method].call(this,...arguments)
            } 
        })
        function Observer(targer){
            if(typeof targer !== 'object' || targer ===null){
                return targer
            }
            if(Array.isArray(targer)) {
                // 数组
                targer.__proto__ =arrProto
                for(let i=0;i<targer.length;i++) {
                    Observer(targer[i])
                }
            }else{
                for(let key in targer){
                    // 响应式数据的函数
                    defineReactive(targer,key,targer[key])
                }
            }
        }
        function updataView(){
            console.log('视图更新了')
        }
        const data = {
            name:'海海',
            age:18,
            info:{
                address:'广州'
            },
            fava:[1,2,3,4,5]
        }
        Observer(data)
    </script>

 

相关实践学习
DataV Board用户界面概览
本实验带领用户熟悉DataV Board这款可视化产品的用户界面
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
1天前
|
JavaScript 前端开发 UED
vue2和vue3的响应式原理有何不同?
大家好,我是V哥。本文详细对比了Vue 2与Vue 3的响应式原理:Vue 2基于`Object.defineProperty()`,适合小型项目但存在性能瓶颈;Vue 3采用`Proxy`,大幅优化初始化、更新性能及内存占用,更高效稳定。此外,我建议前端开发者关注鸿蒙趋势,2025年将是国产化替代关键期,推荐《鸿蒙 HarmonyOS 开发之路》卷1助你入行。老项目用Vue 2?不妨升级到Vue 3,提升用户体验!关注V哥爱编程,全栈开发轻松上手。
|
4天前
|
数据采集 资源调度 JavaScript
极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
本文介绍了使用 Vue Flow 绘制流程图的方法与技巧。Vue Flow 是一个灵活强大的工具,适合自定义复杂的流程图。文章从环境要求(Node.js v20+ 和 Vue 3.3+)、基础入门案例、自定义功能(节点与连线的定制、事件处理)到实际案例全面解析其用法。重点强调了 Vue Flow 的高度灵活性,虽然预定义内容较少,但提供了丰富的 API 支持深度定制。同时,文中还分享了关于句柄(handles)的使用方法,以及如何解决官网复杂案例无法运行的问题。最后通过对比 mermaid,总结 Vue Flow 更适合需要高度自定义和复杂需求的场景,并附带多个相关技术博客链接供进一步学习。
|
14天前
|
JavaScript 前端开发 算法
vue渲染页面的原理
vue渲染页面的原理
|
4天前
|
存储 数据采集 供应链
属性描述符初探——Vue实现数据劫持的基础
属性描述符还有很多内容可以挖掘,比如defineProperty与Proxy的区别,比如vue2与vue3实现数据劫持的方式有什么不同,实现效果有哪些差异等,这篇博文只是入门,以后有时间再深挖。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
1月前
|
JavaScript 前端开发 开发者
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
|
3月前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
174 1
|
1月前
|
移动开发 JavaScript API
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
|
1月前
|
监控 JavaScript 前端开发
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
111 12
|
1月前
|
JavaScript 前端开发 数据安全/隐私保护
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。
|
2月前
|
JavaScript 安全 API
iframe嵌入页面实现免登录思路(以vue为例)
通过上述步骤,可以在Vue.js项目中通过 `iframe`实现不同应用间的免登录功能。利用Token传递和消息传递机制,可以确保安全、高效地在主应用和子应用间共享登录状态。这种方法在实际项目中具有广泛的应用前景,能够显著提升用户体验。
246 8

热门文章

最新文章