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]
    })
  }
}
相关推荐
Swift社区1 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
new出一个对象1 小时前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
没头脑的ht1 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht1 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20241 小时前
Swift 数组
开发语言
你挚爱的强哥2 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
stm 学习ing2 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
y先森3 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy3 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js