1. 程式人生 > 其它 >vue2 響應式的簡單實現

vue2 響應式的簡單實現

// 觸發更新檢視
function updateView() {
  console.log("檢視更新");
}

// 重新定義陣列原型
const oldArrayProperty = Array.prototype;
// 建立新物件,原型指向 oldArrayProperty ,再擴充套件新的方法不會影響原型
const arrProto = Object.create(oldArrayProperty);
["push", "pop", "shift", "unshift", "splice"].forEach((methodName) => {
  arrProto[methodName] 
= function () { updateView(); // 觸發檢視更新 oldArrayProperty[methodName].call(this, ...arguments); // Array.prototype.push.call(this, ...arguments) }; }); // 重新定義屬性,監聽起來 function defineReactive(target, key, value) { // 深度監聽 observer(value); // 核心 API Object.defineProperty(target, key, { get() {
return value; }, set(newValue) { if (newValue !== value) { // 深度監聽 observer(newValue); // 設定新值 // 注意,value 一直在閉包中,此處設定完之後,再 get 時也是會獲取最新的值 value = newValue; // 觸發更新檢視 updateView(); } }, }); } // 監聽物件屬性 function observer(target) {
if (typeof target !== "object" || target === null) { // 不是物件或陣列 return target; } if (Array.isArray(target)) { target.__proto__ = arrProto; } // 重新定義各個屬性(for in 也可以遍歷陣列) for (let key in target) { defineReactive(target, key, target[key]); } } // 準備資料 const data = { name: "liyi", age: 20, info: { address: "china", // 需要深度監聽 }, nums: [10, 20, 30], }; // 監聽資料 observer(data);
data.name = 'lisi' data.age = 21 data.x = '100' // 新增屬性,監聽不到 —— 所以有 Vue.set delete data.name // 刪除屬性,監聽不到 —— 所有已 Vue.delete data.info.address = '上海' // 深度監聽 data.nums.push(4); // 監聽陣列