vue2-响应式-简说

前言

本文旨在让小白大概了解一下怎么实现响应式(即:双向绑定 v-model),像源码中核心部分的观察者模式,模板渲染注册观察者等操作统统略过,大佬看到这就可以忽略此文了。

文章分两部分来讲,基础补充(Object.defineProperty)和代码的简单实现。

1、响应式核心 – Object.defineProperty

可能很多小白不知道这个原生的js方法,这是正常的,这里作者希望小白们在将来研究任何源码之前,先认真学习一下JavaScript,这是现在普遍的现象,一毕业出来实习,你可能JavaScript都没有学多少,公司 ‘啪’的一下扔一个Vue框架给你开发,对,确实Vue很好用,但是如果你局限于使用,你会在工作中越走越难。
推荐一个学习JavaScript的网站:https://zh.javascript.info/ 比MDN好在知识没有那么杂乱。

回归正题

Vue.js实现响应式的核心时利用了ES5的Object.defineProperty,这也是为什么 Vue.js 不能兼容 IE8 及以下浏览器的原因.

**Object.defineProperty()**方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。

configurableenumerablevaluewritablegetset
数据描述符可以可以可以可以不可以不可以
存取描述符可以可以不可以不可以可以可以

​ 而Vue的响应式利用的正是该方法的存取描述符中的get/set,来实现的.

代码演示:

let user = {
  name: "YC",
  surname: "Z"
};

// 在User对象中新增一个fullName的key
Object.defineProperty(user, 'fullName', {
  get() {
    return `${this.name} ${this.surname}`;
  },

  set(value) {
    [this.name, this.surname] = value.split(" ");
  }
});

alert(user.fullName); // 取值调用get方法: YC Z

for(let key in user) alert(key); // name, surname 遍历默认不不可见,可看上文表格中

user.fullName ="L LL"; // 赋值调用set方法

console.log(user.name); // LL
console.log(user.surname); // L

2、Demo – 我的垃圾响应式代码

我们现在知道了Object.defineProperty的基本使用,那么来一步步写一个简单的响应式demo

Html部分

我们以一个input输入框来做触发条件,来控制div中的内容双向绑定显示

<div id="app">
        <input id="input1" oninput="model()" />
        <div id="text"></div>
</div>

JavaScript部分

<script>
// 1:获取id为app的div
var app = document.getElementById("app");

// 2:初始化被监听的对象data
var data = {
	'message':''
};

// 3:使用Object.defineProperty设置监听数据message
Object.defineProperty(data, 'changeMessage', {
            enumerable: true,
            configurable: true,
            get() {
                console.log('message属性被读取了');
                return
            },
            set(newVal) {
                console.log('message属性被修改了');
                this.message= newVal;
                render();
            }
		}
)

// 4:获取input的值赋值给监听数据
function change() {
	var input = document.querySelector('#input1');
	// 触发set事件
    data.changeMessage = input.value
}

// 5:重写div内容的方法
function render() {
	// 获取显示内容的div
	var testDiv = document.querySelector('#text');
	// 置空内容
    testDiv.innerHTML = "";
    // 创建 p 标签
    var ele = document.createElement('p');
    // 给 p 标签赋值
    ele.innerText = data.message;
    // 把 p 标签加入div中
    testDiv.appendChild(ele);
}
</script>

到这里我想思路清晰的人肯定会有疑问为什么不把change方法和render方法合并起来,让input标签触发呢,如下:

function change(){
	var input = document.querySelector('#input1');
	var testDiv = document.querySelector('#text');
    testDiv.innerHTML = "";
    var ele = document.createElement('p');
    ele.innerText = input.value;
    testDiv.appendChild(ele);
}

我们可以思考一下,现在我们只是一个div绑定了值,但是在实际代码中,我们data里面的值可能被七八个地方绑定到,如果是不同的标签呢?

其实不用纠结,因为Vue实现中不止是只有一个双向绑定,还有虚拟dom,diff算法,template解析等等,相互配合,不用纠结于一个地方,这里只是单独拿出一个小点来讲,所以才会引发这些思考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值