备案 控制台
开发者社区 开发与运维 文章 正文

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>

 

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
26fgfyxgmott4
目录
相关文章
凌寒ᨐ舞
|
1天前
|
JavaScript
vue强制刷新组件
vue强制刷新组件
凌寒ᨐ舞
10 0
肥晨
|
1天前
|
存储 JavaScript 前端开发
vue在页面使用Vue.prototype全局变量
【6月更文挑战第3天】Vue.prototype 是 Vue 实例的原型对象,用于添加全局属性和方法。通过修改 Vue.prototype,所有 Vue 实例都能访问这些属性和方法。例如,可在 mai
肥晨
5 1
肥晨
|
1天前
|
JavaScript 前端开发 开发者
vue3+ts配置跨域报错问题解决:> newpro2@0.1.0 serve > vue-cli-service serve ERROR Invalid options in vue.
【6月更文挑战第3天】在 Vue CLI 项目中遇到 &quot;ERROR Invalid options in vue.config.js: ‘server’ is not allowed&quot; 错误是因为尝试在 `vue.config.js` 中使用不被支持的 `server` 选项。正确配置开发服务器(如代理)应使用 `devServer` 对象,例如设置代理到 `http://xxx.com/`: ```javascript module.exports = { devServer: {
肥晨
13 1
凌寒ᨐ舞
|
1天前
|
缓存 JavaScript 前端开发
vue的笔记(2)
vue的笔记
凌寒ᨐ舞
10 1
凌寒ᨐ舞
|
1天前
|
JavaScript 算法 容器
vue的笔记(1)
vue的笔记
凌寒ᨐ舞
17 3
凌浩雨
|
JavaScript 测试技术 容器
Vue2+VueRouter2+webpack 构建项目
1). 安装Node环境和npm包管理工具 检测版本 node -v npm -v 图1.png 2). 安装vue-cli(vue脚手架) npm install -g vue-cli --registry=https://registry.
凌浩雨
998 0
她说她一如既往的爱我
|
1天前
|
JavaScript
Vue移动端登录页面
Vue移动端登录页面
她说她一如既往的爱我
11 3
她说她一如既往的爱我
|
1天前
|
JavaScript 前端开发 API
vue项目移动端商场
vue项目移动端商场
她说她一如既往的爱我
15 6
她说她一如既往的爱我
|
1天前
|
JavaScript
vue富文本层级高
vue富文本层级高
她说她一如既往的爱我
16 5
她说她一如既往的爱我
|
1天前
|
JavaScript
vue使用路由配置步骤?
vue使用路由配置步骤?
她说她一如既往的爱我
11 2

热门文章

最新文章

  • 1
    Vue+Django+MySQL搭建指南(个人全栈快速开发)
  • 2
    基于新版 Electron 的 Vue 脚手架
  • 3
    Vue2+VueRouter2+webpack 构建项目
  • 4
    [手把手系列之]Docker 部署 vue 项目(上)
  • 5
    VUE3(二十一)vue-router 在新窗口打开页面的功能
  • 6
    使用 Vue 2.0 实现服务端渲染的 HackerNews
  • 7
    Flask:使用SocketIO实现WebSocket与前端Vue进行实时推送(gevent-websocket、flask-socketio、flask不出现running on 127..问题)
  • 8
    vue 路由demo
  • 9
    vue里使用docx-preview预览docx文件
  • 10
    Vue.js 事件处理器 v-on
  • 1
    Vue数据双向绑定实现原理
    160
  • 2
    Vue入门指北——渲染函数和jsx
    91
  • 3
    Vue组合式函数(一)
    147
  • 4
    Vue组合式函数(二)封装一个请求
    154
  • 5
    vue项目中关闭eslint报错
    76
  • 6
    Vue 2|学习笔记
    117
  • 7
    Vue基于$attrs及$listeners实现隔代通信
    42
  • 8
    基于Vue实现多标签选择器
    181
  • 9
    CDN方式使用Vue组件通信
    134
  • 10
    Vue中 使用 iframe 嵌入本地 HTML 页面 并 相互通信
    1230
  • 相关课程

    更多
  • Spring Boot+Vue.js+FastDFS实现分布式图片服务器
  • Vue.js 入门与实战
  • Vue.js完全自学手册图文教程
  • React 入门与实战
  • React 入门教程开发文档
  • 相关电子书

    更多
  • Vue.js 在前端服务化上的探索与实践
  • 利用编译将 Vue 组件转成 React 组件
  • Vue.js在前端服务化上的实践与探索
  • 下一篇
    2024年阿里云免费云服务器及学生云服务器申请教程参考

    深圳SEO优化公司临沧优化哪家好濮阳企业网站设计哪家好西宁seo网站推广价格深圳关键词按天计费哪家好株洲seo网站优化推荐楚雄百度竞价价格广安关键词排名价格太原阿里店铺托管朝阳网站制作酒泉设计网站推荐黄山百姓网标王价格沈阳网站优化排名那曲网站制作设计公司白山百姓网标王推广公司韶关网页设计多少钱清徐seo网站优化哪家好天水网站推广方案价格巢湖网站推广系统苏州网站设计报价聊城百度网站优化玉树网站开发推荐聊城网站优化排名推荐延安英文网站建设推荐大运seo排名价格南昌seo网站优化木棉湾网站推广工具哪家好南通推广网站价格延边设计网站推荐中山企业网站设计报价武汉网站推广方案多少钱歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

    深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化