Недостатки Object.defineProperty и почему vue3 использует прокси

Vue.js

Это вопрос, который я задавал раньше, не думал о нем до того, как его спросили, очень невежественен, когда его спросили 😯 В этом Object.defineProperty используется двусторонняя привязка данных vue2, vue3 будет осуществлять перехват данных через прокси. Зачем этому vue3 это делать?

Принцип реализации двухсторонней привязки данных vue

Я уже много раз пытался описать эту проблему, но потому, что я думаю, что это недостаточно ясно. Vue — это двусторонняя привязка данных с использованием захвата данных в сочетании с режимом публикации-подписки. В реализации Vue есть четыре части:

  • mvvm используется для инициализации данных
  • Наблюдатель используется для добавления сеттеров и геттеров к исходным данным через Object.defineProperty, добавления объекта подписки (watcher) в массив при выборке данных (то есть вызове get) и знания данных при присвоении значений data (то есть вызывающий набор).В это время вызывается уведомление центра публикации и подписки, чтобы пройти текущий массив подписки этих данных, выполнить все наблюдатели в нем и уведомить об обновлении изменения.
  • Компилятор используется для компиляции данных в dom. Делится на три шага: 1. Сначала перемещаем реалдом во фрагмент в памяти, 2. Компилируем: извлекаем нужный элемент node v-model и текстовый node {{}}, 3. Помещаем скомпилированный фрагмент обратно на страницу. На втором этапе к данным, скомпилированным в dom, будет добавлен наблюдатель.При изменении данных здесь также может быть уведомлен и выполнен обратный вызов наблюдателя.
  • Наблюдатель — это мост связи между наблюдателем и компилятором.

Недостатки Object.defineProperty

1. Первый недостаток Object.defineProperty заключается в том, что он не может отслеживать изменения массива. Но во Vue можно следить за изменениями массива, так как же он это реализует? Были использованы следующие восемь методов:

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

Ссылка на пример реализации:

const aryMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
const arrayAugmentations = [];

aryMethods.forEach((method)=> {

    // 这里是原生Array的原型方法
    let original = Array.prototype[method];

   // 将push, pop等封装好的方法定义在对象arrayAugmentations的属性上
   // 注意:是属性而非原型属性
    arrayAugmentations[method] = function () {
        console.log('我被改变啦!');

        // 调用对应的原生方法并返回结果
        return original.apply(this, arguments);
    };

});

let list = ['a', 'b', 'c'];
// 将我们要监听的数组的原型指针指向上面定义的空数组对象
// 别忘了这个空数组的属性上定义了我们封装好的push等方法
list.__proto__ = arrayAugmentations;
list.push('d');  // 我被改变啦! 4

// 这里的list2没有被重新定义原型指针,所以就正常输出
let list2 = ['a', 'b', 'c'];
list2.push('d');  // 4

Приведенная выше ссылка на код:здесь

2. Второй недостаток Object.defineProperty заключается в том, что он может только захватить свойства объекта, поэтому нам нужно пройти каждое свойство каждого объекта.Если значение свойства также является объектом, то требуется глубокий обход.Очевидно, Целый объект может быть угнан, лучший выбор.

Почему vue3 использует прокси?

1. Прокси может напрямую следить за изменениями массива; 2. Прокси может отслеживать объекты вместо свойств, он устанавливает слой «перехвата» перед целевым объектом, и доступ к объекту из внешнего мира должен сначала пройти через этот слой перехвата, поэтому он обеспечивает механизм внешнего доступ Фильтровать и переписывать. Прокси может напрямую захватить весь объект и вернуть новый объект.

Суммировать

  • Proxy возвращает новый объект, мы можем использовать новый объект только для достижения цели, а Object.defineProperty может только просматривать свойства объекта и изменять их напрямую;
  • В качестве нового стандарта Proxy будет подвергаться постоянной оптимизации производительности производителями браузеров, что является бонусом производительности легендарного нового стандарта.
  • Конечно, недостаток Proxy — совместимость, и его нельзя реализовать полифиллом.

Ссылка на эту статью:Ссылка 1