返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Vue源码学习defineProperty响应式数据原理实现
  • 788
分享到

Vue源码学习defineProperty响应式数据原理实现

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

目录准备工作第一步 对对象进行劫持第二步 修改取值方法第三步 深度属性劫持准备工作 接上文数据初始化完成之后,就可以对数据进行劫持。Vue2中对数据进行劫持采用了一个api叫Obje

准备工作

接上文数据初始化完成之后,就可以对数据进行劫持。Vue2中对数据进行劫持采用了一个apiObject.defineProperty()

在这里需要提供一个方法去观测data变化,这个方法是一个核心模块(响应式模块),我们单独建一个文件夹来存放在/src/observe/index.js

// src/state.js
import { observe } from "./observe/index"
export function initState(vm){
    // 对数据需要进行劫持
    const opts = vm.$options //获取所有选项
    if (opts.data){
        initData(vm)
    }
}
function initData(vm){
    // 对数据进行代理
    let data = vm.$options.data
    // data可以是函数或者对象,根实例可以是对象,组件data必须是函数
    data = typeof data === 'function' ? data.call(vm) : data
    // 对数据进行劫持 Vue2采用的一个api object.defineproperty
    observe(data)
}
// src/observe/index.js
export  function observe(data){
  debugger
  console.log(data);
}

执行/dist/index.html,当控制台出可以输出{name: 'i东东', age: 18}说明前面的代码没有问题,接下来就可以开始下面的操作了。

第一步 对对象进行劫持

当拿到了data,就可以对data数据进行劫持,如果说他不是对象就不用劫持,所以还需要进行一个判断。

// src/observe/index.js
export  function observe(data){   // 对这个对象进行劫持
  if(typeof data !=='object'|| data == null){
    return // 只对对象进行劫持
  }
}

那么紧接着如何劫持这个对象呢?

如果一个对象被劫持过了,那么就不需要再次被劫持了(要判断一个对象是否被劫持过,可以增添一个实例,来判断是否被劫持过),所以在内部创造了一个类去观测数据,如果数据被观测过那他的实例就是这个类。

// src/observe/index.js
class Observer{
  constructor(data){ //所有数据
    this.walk(data) // 因为data是一个对象,所以就需要对data进行比遍历
  }
  walk(data){ // 循环对象 对属性依次劫持
     Object.keys(data).forEach(key=>defineReactive(data,key,data[key])) //重新定义属性
  }
}
export function defineReactive(target,key,value){ // 闭包  属性劫持
Object.defineProperty(target,key,{
  get(){ //取值的时候会执行get
    return value
  },
  set(newValue){ // 修改的时候执行set
    if(newValue === value) return
    value = newValue
  }
})
}
export  function observe(data){   // 对这个对象进行劫持
  if(typeof data !=='object'|| data == null){
    return // 只对对象进行劫持
  }
  return new Observer(data); // 对这个数据进行观测
}

因为要对每个属性进行劫持,但是Objece.defineProperty()只能劫持已经存在的属性,后增加的或者删除的是不知道的,(Vue2里面会为此单独写一些api 比如:setset setdelete),所以需要对data进行遍历 this.walk()对属性依次劫持,重新定义属性(性能会差,vue3中proxy就会好很多),就可以调用defineReactive,因为这个方法可以单独去使用,所以直接导出。

完成之后执行index.html中console.log(vm),会发现vm上只有用户的选项,并没有刚才劫持过的属性,是因为在state.js中我们只是data传入了observe函数,所以就考虑,在vm上增加一个属性,叫_data,这样就相当于把_data对象放在了实例vm上,并且又把这个对象进行了观测,观测的时候依旧回去循环这个对象。

// src/state.js
function initData(vm){
    let data = vm.$options.data
    data = typeof data === 'function' ? data.call(vm) : data
    vm._data = data // 新增这一句
    observe(data)
}

这样再次输出,会发现控制台输出了_data,并且给age,name都增加上来get和set方法,现在说明这个事情就成了。

这个时候就可以通过vm._data.name进行取值

// dist/index.html
const vm = new Vue({
  data(){
    return {
      name:'i东东',
      age:18
    }
  }
})
vm._data.name = 'i东东修改'
console.log(vm._data.name); 
// 用户设置值了
// index.js:15 用户取值了
// index.html:29 i东东修改

第二步 修改取值方法

紧接着就会发现正常我们取值都是vm.name,但是上面的访问还是vm._data.name,所以下面需要将取值的方法进行一下优化。需要在state.js中将vm._data用vm代理。

// state.js
function proxy(vm,target,key){
    Object.defineProperty(vm,key,{
        get(){
            return vm[target][key]  // vm._data.name
        },
        set(newValue){
            vm[target][key] = newValue
        }
    })
}
function initData(vm){
    // 对数据进行代理
    let data = vm.$options.data
    data = typeof data === 'function' ? data.call(vm) : data
    vm._data = data
    observe(data)
    // 新增 将vm._data用vm代理
    for(let key in data){
        proxy(vm,'_data',key)
    }
}

这样在index.html中我们就可以用过vm.name重钢访问到数据,也可以通过vm.name = 'i东东修改'去设置值,虽然这样性能是不太好的,但是他用起来会很方便的。所以在这里面相当于代理了两次第一次把用户的数据进行了属性劫持,第二次就是proxy当取值和设置值的时候代理到某个人身上。

第三步 深度属性劫持

// index.html
const vm = new Vue({
  data(){
    return {
      name:'i东东',
      age:18,
      say:{
        hobby:'学习'
      }
    }
  }
})
console.log(vm);

假如说我再增加一个对象say,输出vm会发现hobby并没有被劫持,原因是因为我们只劫持了name、age、say三个属性,如果属性是个对象的话,我们就需要再次劫持。这样我们只需要在defineReactive()里面再次调用observe再次建立劫持,形成递归这样就可以完成对对象的深度属性劫持。

// src/observe/index.js
export function defineReactive(target,key,value){ // 闭包  属性劫持
  observe(value) // 新增 对所有的对象都进行属性接触
  Object.defineProperty(target,key,{
  get(){ //取值的时候会执行get
    console.log('用户取值了');
    return value
  },
  set(newValue){ // 修改的时候执行set
    console.log('用户设置值了');
    if(newValue === value) return
    value = newValue
  }
})
}

以上就是Vue源码学习defineProperty响应式数据原理实现的详细内容,更多关于Vue defineProperty响应式数据的资料请关注编程网其它相关文章!

--结束END--

本文标题: Vue源码学习defineProperty响应式数据原理实现

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

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

猜你喜欢
  • Vue源码学习defineProperty响应式数据原理实现
    目录准备工作第一步 对对象进行劫持第二步 修改取值方法第三步 深度属性劫持准备工作 接上文数据初始化完成之后,就可以对数据进行劫持。Vue2中对数据进行劫持采用了一个Api叫Obje...
    99+
    2024-04-02
  • Vue源码学习之响应式是如何实现的
    目录前言一、一个响应式系统的关键要素1、如何监听数据变化2、如何进行依赖收集——实现 Dep 类3、数据变化时如何更新——实现 Watcher 类二、虚拟 DOM 和 diff1、虚...
    99+
    2024-04-02
  • Vue数据响应式原理实例代码分析
    本文小编为大家详细介绍“Vue数据响应式原理实例代码分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue数据响应式原理实例代码分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。改造数据我们先来尝试写一个函数...
    99+
    2023-07-04
  • Vue解读之响应式原理源码剖析
    目录初始化initState()initProps()initData()observe()ObserverdefineReactive()依赖收集DepWatcher依赖收集过程移...
    99+
    2024-04-02
  • Vue数据响应式原理是什么
    本文小编为大家详细介绍“Vue数据响应式原理是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue数据响应式原理是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。响应式是什么简而言之就是数据变页面变如何实...
    99+
    2023-06-30
  • VUE响应式原理的实现详解
    目录总结前言 相信vue学习者都会发现,vue使用起来上手非常方便,例如双向绑定机制,让我们实现视图、数据层的快速同步,但双向绑定机制实现的核心数据响应的原理是怎么样的呢,接下来让我...
    99+
    2024-04-02
  • Vue响应式原理模拟实现原理探究
    目录前置知识数据驱动数据响应式的核心原理Vue 2.xVue 3.x发布订阅和观察者模式发布/订阅模式观察者模式Vue响应式原理模拟实现VueObserver对data中的属性进行监...
    99+
    2024-04-02
  • Vue深入讲解数据响应式原理
    目录响应式是什么如何实现数据响应式实现对象属性拦截通用的劫持方案总结响应式是什么 简而言之就是数据变页面变 如何实现数据响应式 在Javascript里实现数据响应式一般有俩种方案,...
    99+
    2024-04-02
  • 详解vue数据响应式原理之数组
    目录src/core/observer/index.jssrc/core/observer/array.js arrayMethods总结src/core/observer/inde...
    99+
    2024-04-02
  • Vue 中数据响应式的原理是什么
    Vue 中数据响应式的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。改造数据我们先来尝试写一个函数,用于改造对象:为什么要先写这个函...
    99+
    2024-04-02
  • Vue源码学习之数据初始化
    目录初始化数据创建Vue实例构造函数扩展方法初始化状态调用initData方法对数据进行代理初始化数据 环境搭建:菜鸟学Vue源码第一步之rollup环境搭建步 响应式数据的核心就是...
    99+
    2024-04-02
  • 深入理解Vue响应式原理及其实现方式
    目录Vue的响应式Vue2的响应式原理Vue3的响应式原理深入理解响应式1.数据初始化2.对象的数据劫持Vue的响应式 用过Vue这个框架的人应该都知道,数据驱动是Vue框架的核心,...
    99+
    2023-05-19
    Vue响应式原理 Vue响应式原理实现
  • Vue模拟响应式原理底层代码实现的示例
    目录1.Vue.js功能:2.Observer.js功能(数据劫持):3.Compiler.js功能:4.Dep.js功能:5.Watcher.js功能:整体分析Vue的基本结构如下...
    99+
    2024-04-02
  • Vue 3中响应式的实现原理是什么
    本篇文章给大家分享的是有关Vue 3中响应式的实现原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1. 实现响应式响应基本类型变量首先...
    99+
    2024-04-02
  • Vue响应式原理与虚拟DOM如何实现
    本篇内容介绍了“Vue响应式原理与虚拟DOM如何实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、什么是响应式系统在Vue中,我们可以使...
    99+
    2023-07-05
  • Vue中响应式系统实现原理是什么
    本篇内容介绍了“Vue中响应式系统实现原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!框架每个组件实例都会对应一个watcher实例...
    99+
    2023-07-05
  • Vue怎么实现响应式数据更新
    本文小编为大家详细介绍“Vue怎么实现响应式数据更新”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue怎么实现响应式数据更新”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。首先假设我们在祖辈时候传入进来是个动态...
    99+
    2023-07-04
  • vue数据响应式原理中数组的示例分析
    这篇文章主要介绍vue数据响应式原理中数组的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!src/core/observer/index.jssrc/core/observer/array.js arrayM...
    99+
    2023-06-29
  • vue.js数据响应式原理解析
    目录Object.defineProperty()定义 defineReactive 函数递归侦测对象的全部属性流程分析observe 函数Observer 类完善 defineRe...
    99+
    2022-11-13
    vue.js数据响应式原理 vue.js数据响应式
  • 一篇搞懂Vue2、Vue3响应式源码的原理
    目录前言Vue2响应式操作响应式函数的封装Depend类的封装监听对象的变化Vue3响应式操作Proxy、ReflectVue3响应式前言 我们在编写Vue2,Vue3代码的时候,经...
    99+
    2023-01-08
    Vue2响应式原理 Vue3响应式原理
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作