vue2响应式原理,数据劫持,数据代理,Object.defineProperty()方法

数据代理、数据劫持概念

数据劫持

data中数据通过各种逻辑和封装变成_data,从而去监测data数据的变化,一旦发现data中数据变化了,_data就去修改页面,这个过程通过Object.defineProperty实现,叫数据劫持

数据代理

_data中数据拿出放在vm身上,就可以直接通过vm.name,不需要vm._data.name 通过Object.defineProperty()实现,这个过程叫数据代理

Object.defineProperty()方法

  • es5新增的一个方法
  • 作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

语法:

js 复制代码
 Object.defineProperty(obj,prop,desc)
// obj:在哪个对象身上添加或者修改属性
// prop:添加或修改的属性名
// desc:配置项,一般是一个对象
/* 
  desc 配置项还有6个配置属性
  value: "jack",  给属性添加指定属性值
  writable: true, 默认false不可以修改,true属性可以被修改
  enumerable: true, 默认false不可以遍历,true可以被遍历
  configurable: true, 默认false不能删除,true可以被删除
  get(){}, 当读取属性值的时候,getter就会被调用,函数的返回值会作为该属性的值
  set(){}, 当修改属性值的时候,getter就会被调用,该方法将接受唯一参数,即该属性新的参数值
*/

注意:

  1. 当使用了 getter 或 setter 方法,不允许使用 writable 和 value这两个属性
  2. 不要在 gette r中再次获取该属性值,也不要在 setter 中再次设置该属性,否则会栈溢出

示例:

js 复制代码
  let  person = {
  name:"码农",
  age: 18
     }
     Object.defineProperty(person,'sex',{
         value:"男",  //设置属性值
         enumerable:true, //控制属性是否可以枚举,默认值是false
         writable:true, //控制属性是否可以被修改,默认值是false
         configurable:true //控制属性是否可以被删除,默认值是false
      })
    console.log(person)

数据代理

数据代理的概念

数据代理(Data Proxy):

  • 通过访问代理对象的属性,来间接访问目标对象的属性
  • 在 Vue 中,将data 对象中的属性代理到 Vue 的实例上
  • 这样一来,我们可以通过直接访问 Vue 实例来访问和修改其data对象的属性(这就是为什么直接Vue的实例 . 就可以访问到属性以及方法的底层原理)
  • 更加方便的操作data中的数据

Vue数据代理对属性名的要求

  • data对象的属性名不可以以 " _ "或 " $ " 开头,
  • 因为Vue的实例上的属性名以 " _ " 或 " $ " 开头,会产生冲突

数据劫持

数据劫持(Data Interception):

  • 数据劫持是指在访问或修改对象的属性时,对这些操作进行拦截和监视,以便在属性发生变化时能够触发相关的操作。
  • 在 Vue 中,数据劫持用于监听数据的变化,以实现双向绑定和响应式更新
  • Vue 通过在数据对象的属性上使用 Object.defineProperty 来实现数据劫持
  • 每当访问属性或修改属性时,Vue 会触发相应的 getset 拦截器,从而实现对数据变化的监听
  • 通过数据劫持,Vue 能够在属性发生变化时自动触发视图的更新,从而实现了响应式的特性

Vue数据代理、数据劫持底层实现

html 代码部分

html 复制代码
  <script src='./myVue.js'></script>
  <div id ="root"></div>
  <script>
   let vm = new MyVue({
    el: '#root',
    data(){
       return{
        name: '张三',
        age:18
       }
      },
     methods: {
       fn(){
        console.log('我是方法');
       }
     }
   });
  </script>

js 代码部分

js 复制代码
class MyVue {
  //简单实现数据代理
  constructor(options) {
    Object.keys(options.data()).forEach((item, index) => {
      Object.defineProperty(this, item, {
        get() {
          console.log('读取了数据',item);
          return options.data()[item]
        },
        set(value) {
          console.log('修改了数据',item,value);
          options.data()[item] = value
        }
      })
    })
    // 简单实现methods
    Object.keys(options.methods).forEach(item =>{
      this[item] = options.methods[item]
    })
  }
}
相关推荐
Pedantic26 分钟前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘42 分钟前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆1 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师2 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆2 小时前
VSCode自动格式化三要素
前端
爱勇宝3 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen3 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518136 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode6 小时前
Redis 在生产项目的使用
前端·后端