广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >怎么理解vue2.0响应式架构
  • 574
分享到

怎么理解vue2.0响应式架构

2024-04-02 19:04:59 574人浏览 八月长安
摘要

本篇内容主要讲解“怎么理解Vue2.0响应式架构”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解vue2.0响应式架构”吧!讲data 下面所有属性变为o

本篇内容主要讲解“怎么理解Vue2.0响应式架构”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解vue2.0响应式架构”吧!

讲data 下面所有属性变为observable

来来来先看代码吧

class Vue {       constructor(options) {         this.$options = options         this._data = options.data         observer(options.data, this._update)         this._update()       }       _update(){         this.$options.render()       }     }       function observer(value, cb){       Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))     }      function defineReactive(obj, key, val, cb) {       Object.defineProperty(obj, key, {         enumerable: true,         configurable: true,         get: ()=>{},         set:newVal=> {           cb()         }       })     }      var demo = new Vue({       el: '#demo',       data: {         text: 123,       },       render(){         console.log("我要render了")       }     })       setTimeout(function(){        demo._data.text = 444      }, 3000)

为了好演示我们只考虑最简单的情况,如果看了vue 源码分析之如何实现 observer 和  watcher可能就会很好理解,不过没关系,我们三言两语再说说,这段代码要实现的功能就是将

var demo = new Vue({      el: '#demo',      data: {        text: 123,      },      render(){        console.log("我要render了")      }    })

中data 里面所有的属性置于 observer,然后data里面的属性,比如 text  以改变,就引起_update()函数调用进而重新渲染,是怎样做到的呢,我们知道其实就是赋值的时候就要改变对吧,当我给data下面的text 赋值的时候 set  函数就会触发,这个时候 调用_update 就ok了,但是

setTimeout(function(){       demo._data.text = 444     }, 3000)

demo._data.text没有demo.text用着爽,没关系,我们加一个代理

_proxy(key) {       const self = this       Object.defineProperty(self, key, {         configurable: true,         enumerable: true,         get: function proxyGetter () {           return self._data[key]         },         set: function proxySetter (val) {           self._data[key] = val         }       })     }

然后在Vue的constructor加上下面这句

Object.keys(options.data).forEach(key => this._proxy(key))

***步先说到这里,我们会发现一个问题,data中任何一个属性的值改变,都会引起

_update的触发进而重新渲染,属性这显然不够精准啊

第二步,详细阐述***步为什么不够精准

比如考虑下面代码

new Vue({      template: `        <div>          <section>            <span>name:</span> {{name}}          </section>          <section>            <span>age:</span> {{age}}          </section>        <div>`,      data: {        name: 'js',        age: 24,        height: 180      }    })     setTimeout(function(){      demo.height = 181    }, 3000)

template里面只用到了data上的两个属性name和age,但是当我改变height的时候,用***步的代码,会不会触发重新渲染?会!,但其实不需要触发重新渲染,这就是问题所在!!

第三步,上述问题怎么解决

简单说说虚拟 DOM

首先,template***都是编译成render函数的(具体怎么做,就不展开说了,以后我会说的),然后render  函数执行完就会得到一个虚拟DOM,为了好理解我们写写最简单的虚拟DOM

function Vnode(tag, data, children, text) {       return {         tag: tag,         data: data,         children: children,         text: text       }     }      class Vue {       constructor(options) {         this.$options = options         const vdom = this._update()         console.log(vdom)       }       _update() {         return this._render.call(this)       }       _render() {         const vnode = this.$options.render.call(this)         return vnode       }       __h__(tag, attr, children) {         return VNode(tag, attr, children.map((child)=>{           if(typeof child === 'string'){             return VNode(undefined, undefined, undefined, child)           }else{             return child           }         }))       }       __toString__(val) {         return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);       }     }       var demo = new Vue({       el: '#demo',       data: {         text: "before",       },       render(){         return this.__h__('div', {}, [           this.__h__('span', {}, [this.__toString__(this.text)])         ])       }     })

我们运行一下,他会输出

{       tag: 'div',       data: {},       children:[         {           tag: 'span',           data: {},           children: [             {               children: undefined,               data: undefined,               tag: undefined,               text: '' // 正常情况为 字符串 before,因为我们为了演示就不写代理的代码,所以这里为空             }           ]         }       ]     }

这就是 虚拟最简单虚拟DOM,tag是html 标签名,data 是包含诸如 class 和 style  这些标签上的属性,childen就是子节点,关于虚拟DOM就不展开说了。

回到开始的问题,也就是说,我得知道,render 函数里面依赖了vue实例里面哪些变量(只考虑render 就可以,因为template  也会是帮你编译成render)。叙述有点拗口,还是看代码吧

var demo = new Vue({       el: '#demo',       data: {         text: "before",         name: "123",         age: 23       },       render(){         return this.__h__('div', {}, [           this.__h__('span', {}, [this.__toString__(this.text)])         ])       }     })

就像这段代码,render 函数里其实只依赖text,并没有依赖 name和 age,所以,我们只要text改变的时候

我们自动触发 render 函数  让它生成一个虚拟DOM就ok了(剩下的就是这个虚拟DOM和上个虚拟DOM做比对,然后操作真实DOM,只能以后再说了),那么我们正式考虑一下怎么做

第三步,'touch' 拿到依赖

回到最上面那张图,我们知道data上的属性设置defineReactive后,修改data 上的值会触发 set。

那么我们取data上值是会触发 get了。

对,我们可以在上面做做手脚,我们先执行一下render,我们看看data上哪些属性触发了get,我们岂不是就可以知道 render 会依赖data  上哪些变量了。

然后我么把这些变量做些手脚,每次这些变量变的时候,我们就触发render。

上面这些步骤简单用四个子概括就是 计算依赖。

(其实不仅是render,任何一个变量的改别,是因为别的变量改变引起,都可以用上述方法,也就是computed 和 watch  的原理,也是mobx的核心)

***步,

我们写一个依赖收集的类,每一个data 上的对象都有可能被render函数依赖,所以每个属性在defineReactive

时候就初始化它,简单来说就是这个样子的

class Dep {       constructor() {         this.subs = []       }       add(cb) {         this.subs.push(cb)       }       notify() {         console.log(this.subs);         this.subs.forEach((cb) => cb())       }     }     function defineReactive(obj, key, val, cb) {       const dep = new Dep()       Object.defineProperty(obj, key, {         // 省略       })     }

然后,当执行render 函数去'touch'依赖的时候,依赖到的变量get就会被执行,然后我们就可以把这个 render 函数加到 subs  里面去了。

当我们,set 的时候 我们就执行 notify 将所有的subs数组里的函数执行,其中就包含render 的执行。

至此就完成了整个图,好我们将所有的代码展示出来

function VNode(tag, data, children, text) {      return {        tag: tag,        data: data,        children: children,        text: text      }    }     class Vue {      constructor(options) {        this.$options = options        this._data = options.data        Object.keys(options.data).forEach(key => this._proxy(key))        observer(options.data)        const vdom = watch(this, this._render.bind(this), this._update.bind(this))        console.log(vdom)      }      _proxy(key) {        const self = this        Object.defineProperty(self, key, {          configurable: true,          enumerable: true,          get: function proxyGetter () {            return self._data[key]          },          set: function proxySetter (val) {            self._data.text = val          }        })      }      _update() {        console.log("我需要更新");        const vdom = this._render.call(this)        console.log(vdom);      }      _render() {        return this.$options.render.call(this)      }      __h__(tag, attr, children) {        return VNode(tag, attr, children.map((child)=>{          if(typeof child === 'string'){            return VNode(undefined, undefined, undefined, child)          }else{            return child          }        }))      }      __toString__(val) {        return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);      }    }     function observer(value, cb){      Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))    }     function defineReactive(obj, key, val, cb) {      const dep = new Dep()      Object.defineProperty(obj, key, {        enumerable: true,        configurable: true,        get: ()=>{          if(Dep.target){            dep.add(Dep.target)          }          return val        },        set: newVal => {          if(newVal === val)            return          val = newVal          dep.notify()        }      })    }    function watch(vm, exp, cb){      Dep.target = cb      return exp()    }     class Dep {      constructor() {        this.subs = []      }      add(cb) {        this.subs.push(cb)      }      notify() {        this.subs.forEach((cb) => cb())      }    }    Dep.target = null      var demo = new Vue({      el: '#demo',      data: {        text: "before",      },      render(){        return this.__h__('div', {}, [          this.__h__('span', {}, [this.__toString__(this.text)])        ])      }    })       setTimeout(function(){       demo.text = "after"     }, 3000)

我们看一下运行结果

怎么理解vue2.0响应式架构

好我们解释一下 Dep.target 因为我们得区分是,普通的get,还是在查找依赖的时候的get,

所有我们在查找依赖时候,我们将

function watch(vm, exp, cb){       Dep.target = cb       return exp()     }

Dep.target 赋值,相当于 flag 一下,然后 get 的时候

get: () => {           if (Dep.target) {             dep.add(Dep.target)           }           return val         },

到此,相信大家对“怎么理解vue2.0响应式架构”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 怎么理解vue2.0响应式架构

本文链接: https://www.lsjlt.com/news/86270.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么理解vue2.0响应式架构
    本篇内容主要讲解“怎么理解vue2.0响应式架构”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解vue2.0响应式架构”吧!讲data 下面所有属性变为o...
    99+
    2022-10-19
  • vue2.0/3.0中响应式的原理是什么
    本篇文章为大家展示了vue2.0/3.0中响应式的原理是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。vue是什么Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它大型框...
    99+
    2023-06-15
  • 深入了解Java和Django的响应式框架构建
    Java和Django都是非常流行的Web开发框架。它们都拥有自己的优点和特点,但是它们都可以使用响应式框架进行构建。在本文中,我们将深入了解Java和Django响应式框架的构建。 响应式编程是一种编程范式,它可以让我们更加灵活地处理异步...
    99+
    2023-09-07
    django 响应 框架
  • php中的分布式架构怎么理解
    这篇“php中的分布式架构怎么理解”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“php中的分布式架构怎么理解”文章吧。在PH...
    99+
    2023-06-29
  • 怎么理解Kubernetes架构
    本篇内容主要讲解“怎么理解Kubernetes架构”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解Kubernetes架构”吧!Kubernetes作为一...
    99+
    2022-10-19
  • MySQL架构怎么理解
    本篇内容主要讲解“MySQL架构怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL架构怎么理解”吧!MySQL物理架构配置文件auto.cnf&n...
    99+
    2023-03-14
    mysql
  • 详解Flutter 响应式状态管理框架GetX
    目录一、状态管理框架对比ProviderBLoCGetX二、基本使用2.1 安装与引用2.2 使用GetX改造Counter App2.3 GetX代码插件三、其他功能3.1 路由管...
    99+
    2022-11-13
  • Vue3 ref构建响应式变量失效怎么解决
    这篇“Vue3 ref构建响应式变量失效怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue3 ...
    99+
    2023-07-06
  • 怎么理解Vue 3.0的响应式系统
    这篇文章主要介绍“怎么理解Vue 3.0的响应式系统”,在日常操作中,相信很多人在怎么理解Vue 3.0的响应式系统问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Vu...
    99+
    2022-10-19
  • 怎么理解.NET三层架构应用中的十层框架
    这篇文章给大家介绍怎么理解.NET三层架构应用中的十层框架,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。凡是接触.net开发的,***要理解的就是三层架构的重要思想。关于三层架构的概述 我就不多说了,相信大家都早已明白...
    99+
    2023-06-17
  • LINQ查询架构怎么理解
    本篇内容主要讲解“LINQ查询架构怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“LINQ查询架构怎么理解”吧!LINQ(发音:Link)是Language Integrated Quer...
    99+
    2023-06-17
  • 怎么理解Oracle架构、原理、进程
    这篇文章主要讲解了“怎么理解Oracle架构、原理、进程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Oracle架构、原理、进程”吧!对于一个数据...
    99+
    2022-10-18
  • Laravel框架中怎么解决响应问题
    本篇内容主要讲解“Laravel框架中怎么解决响应问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Laravel框架中怎么解决响应问题”吧!Laravel中的响应在Laravel中,响应是服务...
    99+
    2023-07-06
  • 怎么理解Java事件响应
    这篇文章主要介绍“怎么理解Java事件响应”,在日常操作中,相信很多人在怎么理解Java事件响应问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Java事件响应”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-02
  • vue3结构赋值失去响应式引发的问题怎么解决
    这篇文章主要介绍“vue3结构赋值失去响应式引发的问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue3结构赋值失去响应式引发的问题怎么解决”文章能帮助大家解决问题。原始值的响应式系统的...
    99+
    2023-07-02
  • JS前端架构pnpm怎么构建Monorepo方式管理demo
    今天小编给大家分享一下JS前端架构pnpm怎么构建Monorepo方式管理demo的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下...
    99+
    2023-07-02
  • 怎么深入理解Linux高性能网络架构
    本篇文章为大家展示了怎么深入理解Linux高性能网络架构,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 1. 落寞的小黑上周北京很冷,周五晚上大白下班奔地铁站,收到了好基友小黑的微信:于是...
    99+
    2023-06-15
  • 怎么理解设计模式的结构型模式
    这篇文章主要讲解了“怎么理解设计模式的结构型模式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解设计模式的结构型模式”吧!认识结构型模式结构型模式所描...
    99+
    2022-10-19
  • Vue3中reactive丢失响应式问题怎么解决
    本篇内容主要讲解“Vue3中reactive丢失响应式问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue3中reactive丢失响应式问题怎么解决”吧!问题描述:使用 reacti...
    99+
    2023-07-05
  • 怎么理解Oracle响应时间分析报告
    本篇内容主要讲解“怎么理解Oracle响应时间分析报告”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解Oracle响应时间分析报告”吧!Oracle响应时...
    99+
    2022-10-18
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作