一起来看看Vue的核心原理剖析

目录
  • 前言:
  • 学习目标:
  • Object.defineProperty
  • get、set
  • 数据反应到视图
  • 视图的变化反映到数据
    • M -> V
    • V -> M
      • 优化工作:
  • 总结

前言:

  • 相信大家阅读过很多关于Vue2的文章,我也阅读过很多,但是大部分文章介绍的都是如何在项目中进行应用,技术点如果使用,功能如何实现;
  • 今天小编为大家带来这篇Vue2的核心原理剖析就是为大家介绍我们常用的Vue2他是如何实现的核心内容,我们简单代码的背后究竟他做了哪些,让大家能够 知其然,知其所以然

学习目标:

  • 了解Object.defineProperty原理
  • 了解set、get关联使用
  • 了解数据反应到识图的过程
  • 了解视图更换如何影响数据
  • 掌握MVVM

Object.defineProperty

 <script>
    // 1. 字面量定义
    let data = {
      name: 'aa'
    }
    data.name = 'bb' // 这种情况下我们并不能知道name属性发生了变化

    // 2. Object.defineProperty
    let data1 = {}
    Object.defineProperty(data1, 'name', {
      // 当我们访问data1的name属性的时候自动调用的方法
      // 并且get函数的返回值就是你拿到的值
      get() {
        console.log('你访问了data1的name属性')
        return 'aa'
      },
      // 当我们设置修改name属性的时候自动调用的函数
      // 并且属性最新的值会被当成实参传入进来
      set(newValue) {
        console.log('你修改了data1的name属性最新的值为', newValue)
        // 这个位置 只要你修改了name属性就会得到执行
        // 所以如果你想要在name变化的时候 完成一些自己的事情
        // 都可以放到这里来执行
        // 1. ajax()
        // 2. 操作一块dom区域
      }
    })
    // 以上是js中对象定义的另外一种方案,可以在访问属性和设置属性的时候自动调用对应的函数
    // 访问属性:data.name  data['name']
    // 设置属性:data.name = 'bb'  data['name'] = 'bb'
  </script>

响应式的核心API

get、set

 <script>
    // let data = {
    //   name: 'aa'
    // }
    let data = {}
    let _name = 'aa'
    Object.defineProperty(data, 'name', {
      get() {
        console.log('你访问了data1的name属性')
        return _name
      },

      set(newValue) {
        console.log('你修改了data1的name属性最新的值为', newValue)
        _name = newValue
      }
    })
    // 问题产生的原因:get中直接返回了一个固定的值,并且set函数中新值拿到了但是没有做任何事情
    // 解决方案:通过声明一个中间变量,让get函数中return出去这个变量
    // 并且在set函数中把最新的值设置到这个中间变量身上,起到一个set和get操作的一个
    // 数据的效果
  </script>

数据反应到视图

数据的变化可以引起视图的变化(通过操作dom把数据放到对应的位置上去 如果数据变化之后就用数据最新的值再重新放一次)

方案一:命令式操作

1.document.querySelector(’#app’).innerText = data.name

2.set函数中重新执行一下document.querySelector(’#app’).innerText = data.name

方案二:声明式渲染

v-text指令的实现

 <p v-text="name"></p>

核心逻辑:通过‘模板编译’找到标记了v-text的元素,然后把对应的数据通过操作domapi放上去

 <div id="app">
   <p v-text="name"></p>
   <p></p>
 </app>

1.通过app根元素找到所有的子节点 (元素节点,文本节点…) -> dom.nodeChilds

2.通过节点类型筛选出元素节点 (p) -> nodeType 1元素节点 3文本节点

3.通过v-text找到需要设置的具体的节点 <p v-text></p>4.找到绑定了v-text标记的元素 拿到它身上所有的属性 id class v-text=“name”

5.通过v-text=“name” 拿到指令类型 ‘v-text’ 拿到需要绑定的数据的属性名 ‘name’

6.判断当前是v-text指令 然后通过操作domapi 把name属性对应的值放上去 node.innerText = data[name]

以上整个过程可以称作‘模板编译’

视图的变化反映到数据

input元素 v-model双向绑定
M -> V
V -> M

M -> V

1.通过app根元素找到所有的子节点 (元素节点,文本节点…) -> dom.nodeChilds

2.通过节点类型筛选出元素节点 (p) -> nodeType 1元素节点 3文本节点

3.通过v-text找到需要设置的具体的节点 <p v-text></p>4.找到绑定了v-text标记的元素 拿到它身上所有的属性 id class v-text=“name”

5.通过v-model=“name” 拿到指令类型 ‘v-model’ 拿到需要绑定的数据的属性名 ‘name’

6.判断当前是v-model指令 然后通过操作domapi 把name属性对应的值放上去node.value = data[name]

v-model和v-text除了指令类型不一致,使用的dom api不一致 其它的步骤是完全一致的

V -> M

本质:事件监听在回调函数中拿到input中输入的最新的值然后赋值给绑定的属性

 node.addEventListener('input',(e)=>{
   data[name] = e.target.value
 })

以上总结:

1.数据的响应式

2.数据变化影响视图

3.视图变化影响数据

4.指令是如何实现的(常规实现逻辑)

优化工作:

1.通用的数据响应式处理

   data(){
       return {
          name:'cp',
          age:28
      }
   }

基于现成的数据,然后都处理成响应式

 Object.keys(data) // 由所有的对象的key组成的数组
    Object.keys(data).forEach(key=>{
      // key 属性名
      // data[key]  属性值
      // data 原对象
      // 将所有的key都转成get和set的形式
      defineReactive(data,key,data[key])
    })
    function defineReactive(data,key,value){
      Oject.defineProperty(data, key, {
        get(){
          return value
        },
        set(newValue){
          value = newValue
        }
      })
    }

2.发布订阅模式

问题:

  <div>
      <p v-text="name"></p>
      <p v-text="name"></p>
      <div  v-text="age"></div>
    </div>

name发生变化之后 我需要做的事情是更新俩个p标签,而现在不管你更新了哪个数据,所有的标签都会被重新操作赋值,无法做到精准更新

解决问题的思路:

1.数据发生变化之后最关键的代码是什么?

 node.innerText = data[name]

2.设计一个存储结构

每一个响应式数据可能被多个标签绑定 是一个‘一对多’的关系

 {
        name: [()=>{ node(p1).innerText = data[name]},()=>{ node(p2).innerText = data[name]}...]
      }

发布订阅(自定义事件) 解决的问题就是 ‘1对多’的问题

实现简单的发布订阅模式:

浏览器的事件模型

dom.addEventLister(‘click’,()=>{})

只要调用click事件,所有绑定的回调函数都会执行 显然是一个1对多的关系

  const Dep = {
      map:{},
      collect(eventName,fn){
        // 如果从来没有收集过当前事件就先初始化成数组
        if(!this.map[eventName]){
          this.map[eventName] = []
        }
        // 已经初始化好了就直接往里面push添加
        this.map[eventName].push(fn)
      },
      trigger(eventName){
        this.map[eventName].forEach(fn=>fn())
      }
    }

使用发布订阅模式优化现存问题

先前的写法 不管是哪个数据发生变化我们都是粗暴的执行一下compile函数即可

现在的写法 我们在compile函数初次执行的时候 完成更新函数的收集 然后在数据变化的时候

通过数据的key找到相对应的更新函数 依次执行 达到精准更新的效果

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 详解Vue3的响应式原理解析

    目录 Vue2响应式原理回顾 Vue3响应式原理剖析 嵌套对象响应式 避免重复代理 总结 Vue2响应式原理回顾 // 1.对象响应化:遍历每个key,定义getter.setter // 2.数组响应化:覆盖数组原型方法,额外增加通知逻辑 const originalProto = Array.prototype const arrayProto = Object.create(originalProto) ;['push', 'pop', 'shift', 'unshift', 'splic

  • Vue响应式原理的示例详解

    Vue 最独特的特性之一,是非侵入式的响应系统.数据模型仅仅是普通的 JavaScript 对象.而当你修改它们时,视图会进行更新.聊到 Vue 响应式实现原理,众多开发者都知道实现的关键在于利用 Object.defineProperty , 但具体又是如何实现的呢,今天我们来一探究竟. 为了通俗易懂,我们还是从一个小的示例开始: <body> <div id="app"> {{ message }} </div> <script> v

  • Vue的底层原理你了解多少

    Observer (数据劫持) 核心是通过Obeject.defineProperty()来监听数据的变动,这个函数内部可以定义setter和getter.每当数据发生变化,就会触发setter().这时候 Observer 就要通过 Dep 通知 Watcher 订阅者. Dep (发布者) 有 addWatcher() 和 notify() 两个方法,(收集 Watcher 依赖,并通知依赖变更). Dep 保存多个 atcher,当 Dep 发现 Observer 有更新时,Dep 会调用

  • 详解VUE响应式原理

    目录 1.响应式原理基础 2.核心对象:Dep与Watcher 3.收集依赖与更新依赖 3.1 收集依赖 3.2 更新依赖 4.源码调试 4.1 测试的页面代码 1.对象说明 2.Dep与Watcher的关系 3.最终的关系结果 4.2  源码调试 1.收集依赖的入口函数:initState(页面初始化时执行); 2.初始化computed和watch时,生成Watcher实例化对象 总结 1.响应式原理基础 响应式基本原理是基于Object.defineProperty(obj, prop,

  • Vue响应式系统的原理详解

    目录 vue响应式系统的基本原理 1.回顾一下Object.defineProperty的用法 2.实战1:使用 Object.defineProperty 对 person的age属性 进行监听 3.数据代理 4.vue中实现响应式思路 总结 1.Vue中的数据代理: 2.Vue中数据代理的好处: 3.基本原理: 4.vue中实现响应式思路 vue响应式系统的基本原理 我们使用vue时,对数据进行操作,就能影响对应的视图.那么这种机制是怎么实现的呢? 思考一下,是不是就好像我们对数据的操作 被

  • 一起来看看Vue的核心原理剖析

    目录 前言: 学习目标: Object.defineProperty get.set 数据反应到视图 视图的变化反映到数据 M -> V V -> M 优化工作: 总结 前言: 相信大家阅读过很多关于Vue2的文章,我也阅读过很多,但是大部分文章介绍的都是如何在项目中进行应用,技术点如果使用,功能如何实现: 今天小编为大家带来这篇Vue2的核心原理剖析就是为大家介绍我们常用的Vue2他是如何实现的核心内容,我们简单代码的背后究竟他做了哪些,让大家能够 知其然,知其所以然 学习目标: 了解Obj

  • Java并发编程之JUC并发核心AQS同步队列原理剖析

    目录 一.AQS介绍 二.AQS中的队列 1.同步等待队列 2.条件等待队列 3.AQS队列节点Node 三.同步队列源码分析 1.同步队列分析 2.同步队列--独占模式源码分析 3.同步队列--共享模式源码分析 一.AQS介绍 队列同步器AbstractQueuedSynchronizer(简称AQS),AQS定义了一套多线程访问共享资源的同步器框架,是用来构建锁或者其他同步组件的基础框架,是一个依赖状态(state)的同步器.Java并发编程的核心在java.util.concurrent(

  • vue原生input输入框原理剖析

    目录 正文 v-model 正文 首先我们来看一段代码: <input value="value"> 这里是一个原生的input输入框,每一个原生的输入框都会有一个value的属性来用于存储用于输入的最新的数据. 如果我们想要获取到这个值我们可以通过input.target.value或者通过$event.target.value来获取这个存储的值. 只要用户输入了数据,那么此时input标签就会将输入的数据放到这个value中(新数据会覆盖旧数据,所以我们获取到的都是最新

  • Vue底层实现原理总结

    前言 最近在研究 剖析Vue原理&实现双向绑定MVVM 这篇文章,一边学习一边总结一下自己的思考. Vue是一个典型的MVVM框架,模型(Model)只是普通的JavaScript对象,修改它则视图(View)会自动更新.这种设计让状态管理变得非常简单而直观.那么Vue是如何把模型和视图建立起关联的呢? 实现原理概述 这是前言提到的文章里的代码,一段典型的体现了Vue特点的代码: <div id="mvvm-app"> <input type="te

  • Vue响应式原理Observer、Dep、Watcher理解

    开篇 最近在学习Vue的源码,看了网上一些大神的博客,看起来感觉还是蛮吃力的.自己记录一下学习的理解,希望能够达到简单易懂,不看源码也能理解的效果

  • 详细分析vue响应式原理

    前言 响应式原理作为 Vue 的核心,使用数据劫持实现数据驱动视图.在面试中是经常考查的知识点,也是面试加分项. 本文将会循序渐进的解析响应式原理的工作流程,主要以下面结构进行: 分析主要成员,了解它们有助于理解流程 将流程拆分,理解其中的作用 结合以上的点,理解整体流程 文章稍长,但大部分是代码实现,还请耐心观看.为了方便理解原理,文中的代码会进行简化,如果可以请对照源码学习. 主要成员 响应式原理中,Observe.Watcher.Dep这三个类是构成完整原理的主要成员. Observe,响

  • vue响应式原理与双向数据的深入解析

    了解object.defineProperty 实现响应式 清楚 observe/watcher/dep 具体指的是什么 了解 发布订阅模式 以及其解决的具体问题 在Javascript里实现数据响应式一般有俩种方案,分别对应着vue2.x 和 vue3.x使用的方式,他们分别是: 对象属性拦截 (vue2.x) Object.defineProperty 对象整体代理 (vue3.x) Proxy 提示:以下是本篇文章正文内容,下面案例可供参考 vue-响应式是什么? Vue 最独特的特性之一

  • 通过Spring Security魔幻山谷讲解获取认证机制核心原理

    本文基于Springboot+Vue+Spring Security框架而写的原创学习笔记,demo代码参考<Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统>一书. 这是一个古老的传说. 在神秘的Web系统世界里,有一座名为SpringSecurity的山谷,它高耸入云,蔓延千里,鸟飞不过,兽攀不了.这座山谷只有一条逼仄的道路可通.然而,若要通过这条道路前往另一头的世界,就必须先拿到一块名为token的令牌,只有这样,道路上戍守关口

  • 分析Vue指令实现原理

    目录 一.基本使用 二.指令工作原理 2.1.初始化 2.2.模板编译 2.3.生成渲染方法 2.4.生成VNode 2.5.生成真实DOM 三.注意事项 四.小结 一.基本使用 官网案例: <div id='app'> <input type="text" v-model="inputValue" v-focus> </div> <script> Vue.directive('focus', { // 第一次绑定元素

  • Vue指令工作原理实现方法

    Vue简介 现在的大前端时代,是一个动荡纷争的时代,江湖中已经分成了很多门派,主要以Vue,React还有Angular为首,形成前端框架三足鼎立的局势.Vue在前端框架中的地位就像曾经的jQuery,由于其简单易懂.开发效率高,已经成为了前端工程师必不可少的技能之一. Vue是一种渐进式JavaScript框架,完美融合了第三方插件和UI组件库,它和jQuery最大的区别在于,Vue无需开发人员直接操作DOM节点,就可以改变页面渲染内容,在应用开发者具有一定的HTML.CSS.JavaScri

随机推荐