Object.defineProperty在Vue2双向绑定中的核心原理及应用

目录

1.Object.defineProperty方法

(1)介绍

(2)语法

(3)descriptor属性描述符

2.Object.defineProperty在Vue2双向绑定的核心原理

3.Object.defineProperty在vue2中的应用

(1)v-model指令

(2)计算属性(Computed Properties)

(3)侦听器(Watchers)

4.Vue 3.x中的变化

(1)Object.defineProperty进行数据劫持的缺点

(2)Vue3的Proxy

总结:


本文主要讲解了Object.defineProperty方法的功能及在Vue中实现双向绑定的核心原理。强调了Object.defineProperty在Vue框架中用于数据劫持、属性定义和修改的重要性,以及如何通过这种方式实现数据与视图的自动同步更新。

1.Object.defineProperty方法

(1)介绍

Object.defineProperty() 方法是 JavaScript 中的一个非常重要的方法,它允许你精确地添加或修改对象的属性。与简单地使用赋值操作(如 obj.prop = value)不同,Object.defineProperty() 允许你设置属性的多种特性,如是否可枚举(enumerable)、是否可配置(configurable)、是否可写(writable),以及为属性指定一个 getter 或 setter 函数。

(2)语法

Object.defineProperty(obj, prop, descriptor)
  • obj:定义属性的对象。
  • prop:定义或修改的属性的名称。
  • descriptor:通常设置一个对象,去定义或修改的属性描述符。

(3)descriptor属性描述符

属性描述符对象具有以下属性:

  • value:属性默认值。
  • writable:设置属性是否能改修改(true|false)。
  • enumerable:是否可以枚举,即是否允许遍历(true|false)。
  • configurable:是否可以删除(true|false)。
  • get:作为该属性的获取getter 函数,如果没有 getter 则为 undefined当访问该属性时,会调用此函数,执行时不传入任何参数,并返回该属性的值。
  • set:作为该属性的设置setter 函数,如果没有 setter 则为 undefined当属性值被修改时,会调用此函数,该函数接受一个参数(被赋予的新值),并不返回任何值,使用 return 语句是无效的。

示例 1:简单使用

javascript代码

// 定义一个空对象
let obj = {};

// 定义一个属性并使用Object.defineProperty方法定义其特性
Object.defineProperty(obj, 'name', {
    value: 'John', // 属性的值
    writable: false, // 该属性的值是否可以被修改
    enumerable: true, // 该属性是否可以被枚举
    configurable: false // 该属性是否可以被删除或修改特性
});

// 尝试修改属性值
obj.name = 'Jane'; //设置无效

// 枚举属性
for (let key in obj) {
    console.log(key); // name
}

// 获取属性描述符
console.log(Object.getOwnPropertyDescriptor(obj, 'name')); // { value: 'John', writable: false, enumerable: true, configurable: false }

// 删除属性
delete obj.name; //删除无效
console.log(obj.name); // John
const obj1 = {};
Object.defineProperty(obj1, 'sex', {
    get:function() {
        console.log("正在获取属性");
    },
    set:function(value) { 
        console.log("正在设置属性");
    }
});

示例 2:使用get和set

const myObj = {
    __prop:'initial value'
};
Object.defineProperty(myObj,'prop',{
    get:function(){
        return this.__prop;
    },
    set:function(newValue){
        this.__prop = newValue;
    },
    enumerable: true,
    configurable: true, 
})
console.log(myObj.prop); //initial value
myObj.prop = "new value"; 
console.log(myObj.prop); //new value 

示例3:JS实现双向数据绑定原理

<body>
    <div id="demo"></div>
    <label for="inp">请输入文本:</label>  
    <input type="text" id="inp">
    <!-- Object.defineProperty是JavaScript 中用于定义或修改对象的属性的方法,可以控制属性的特性(如可枚举性、可配置性、可写性等)。 -->
    <!-- 语法: Object.defineProperty(obj,prop,descriptor)-->
    <script>
    // 实现双向数据绑定原理
    let obj2 = {};
    let demo = document.getElementById('demo');
    let inp = document.getElementById('inp');
    Object.defineProperty(obj2,"name",{
        get:function(){

        },
        set:function(newVal){
            console.log(newVal);
            demo.innerHTML = newVal;
        }
    })
    inp.addEventListener('input',function(e){
        obj2.name = e.target.value;
    })
    </script>
</body>

注意:默认情况下,使用 Object.defineProperty() 添加的属性是不可枚举的,即不会出现在 for...in 循环和 Object.keys() 方法中,除非明确将 enumerable 设置为 true

2.Object.defineProperty在Vue2双向绑定的核心原理

在Vue的双向绑定中,Object.defineProperty方法是核心。

Vue.js的Vue 2.x版本通过Object.defineProperty方法实现了数据的双向绑定。这一方法允许开发者直接在一个对象上定义新属性,或者修改一个对象的现有属性,并返回这个对象。具体到Vue的双向绑定中,Object.defineProperty被用来劫持或监听对象属性的getter和setter方法。

数据劫持:当Vue实例初始化时,它会对data选项中的每个属性使用Object.defineProperty方法进行数据劫持。当数据发生变化时,就会触发setter函数,通知依赖该属性的视图进行更新。

依赖收集:Vue内部维护了一个依赖收集系统,通常是通过Watcher对象实现的。当组件渲染时,会触发getter方法,Vue会将当前Watcher对象添加到该属性的依赖列表中。

更新视图:当数据变化时,setter方法被触发,Vue会遍历该属性的依赖列表,通知所有依赖的Watcher对象进行更新。Watcher对象随后会触发对应的视图更新。

3.Object.defineProperty在vue2中的应用

在Vue的双向绑定中,Object.defineProperty的应用主要体现在以下几个方面:

(1)v-model指令

v-model是Vue中实现双向绑定的主要指令。当在表单元素上使用v-model时,Vue会自动为该元素创建一个数据绑定,并监听其input事件来更新数据。这背后就是Object.defineProperty在起作用,它确保了数据模型(Model)和视图(View)之间的同步,非常方便。

注:CDN引入的vue2

示例:

<body>
    <div id="app">
        <p>{{name}}</p>
        <input type="text" v-model="name" placeholder="请输入名字">
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
    <script>
        // v-model实现双向数据绑定
        new Vue({
            el: '#app',
            data: {
                name: '哈哈'
            }
        })
    </script>
</body>

(2)计算属性(Computed Properties)

计算属性是基于它们的依赖进行缓存的响应式属性。Vue在内部也是通过Object.defineProperty来定义这些计算属性的getter和setter。尽管setter在大多数情况下是不必要的,因为计算属性通常是只读的。

示例:

<body>
    <div id="app">  
        <p>原始字符串: "{{ message }}"</p>  
        <p>处理后的: "{{ reversedMessage }}"</p>  
    </div>  
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
    <script>  
        new Vue({  
            el: '#app',  
            data: {  
                message: '123456'  
            },  
            computed: {  
                reversedMessage: function () {  
                    return this.message.split('').reverse();  
                }  
            }  
        })  
    </script>  
</body>

(3)侦听器(Watchers)

Vue允许开发者使用watch选项来观察和响应Vue实例上数据的变动。这同样依赖于Object.defineProperty来实现对数据的监听和响应。

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
    <div id="app">  
        <p>问题: {{ question }}</p>  
        <input v-model="answer" placeholder="输入答案">  
    </div>  
    <script>  
        var app = new Vue({  
            el: '#app',  
            data: {  
                question: '1 + 1 等于多少?',  
                answer: ''  
            },  
            watch: {  
                // 当answer发生变化时,这个匿名函数就会被调用  
                answer: function (newVal, oldVal) {  
                    console.log(`新答案: ${newVal}, 旧答案: ${oldVal}`);  
                    // 可以添加更复杂的逻辑,比如异步请求等  
                }  
            }  
        })  
    </script>  
</body>
</html>

4.Vue 3.x中的变化

(1)Object.defineProperty进行数据劫持的缺点

Object.defineProperty 主要是用来定义对象的属性,它不能拦截到数组的方法调用(如 pushpopshiftunshiftsplicesortreverse 等),这些方法会改变数组的内容但不会触发 Object.defineProperty 设置的 getter/setter。Vue.js 通过覆盖这些数组方法来解决这个问题,

(2)Vue3的Proxy

在Vue 3.x中,双向绑定的实现方式有所变化。Vue 3.x引入了Proxy对象来替代Object.defineProperty进行响应式系统的实现。Proxy提供了一种更强大的方式来拦截和定义对象上的基本操作(如属性查找、赋值、枚举、函数调用等),可以完美监听到任何方式的数据改变。

总结:

Object.defineProperty在Vue 2.x的双向绑定中起核心作用,它通过数据劫持和依赖收集/派发更新的机制实现了数据模型与视图之间的自动同步。而在Vue 3.x中,采用了不同的实现方式(Proxy),但双向绑定的核心原理仍然相同。

如果对你有帮助,给个赞行嘛~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端绘梦师

你的鼓励是我最大的动力!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值