
предисловие
vue3
Он был в центре внимания в течение двух лет с момента его выпуска, и теперь у него есть импульс, чтобы поделиться миром с реагировать, Мы знаем, что это основано на способности прокси-сервера достигать отзывчивости, что решило некоторые vue2
из оставшихся проблем. в то же время, благодаря характеристикам прокси, он также улучшил производительность во время выполнения
У всего есть преимущества и недостатки proxy
, хотя он и непобедим, но также имеет свои ограничения, что приводит к некоторым недостаткам, на мой взгляд (на самом деле, он не соответствует естественному способу написания языка js, некоторые люди думают, что это особый метод написания, и он не относится к недостаткам)
-
1. Реализация отзывчивой системы примитивных значений приводит к тому, что она должна быть упакована как объект и доступ .value
к ней посредством -
2. Деструктурирование ES6 нельзя использовать по желанию. сломал бы его отзывчивую натуру
Движимый любопытством, я исследовал и обдумал, почему он вызвал эти два недостатка.
Реализация реактивной системы для примитивных значений
Прежде чем понять реализацию реактивной системы примитивных значений, давайте сначала рассмотрим возможности прокси!
const obj = {
name: 'win'
}
const handler = {
get: function(target, key){
console.log('get--', key)
return Reflect.get(...arguments)
},
set: function(target, key, value){
console.log('set--', key, '=', value)
return Reflect.set(...arguments)
}
}
const data = new Proxy(obj, handler)
data.name = 'ten'
console.log(data.name,'data.name22')
复制代码
В приведенном выше коде мы обнаружили, что использование прокси само по себе является перехватом объекта new Proxy
, а объект obj перехватывается через возвращаемое значение
Таким образом, когда вы получаете доступ к значению в объекте, он запускает get
метод , а когда вы изменяете значение в объекте, он запускает set
метод .
Но когда дело доходит до исходного значения, у него нет объекта, что делать, его new proxy
нельзя использовать.
В отчаянии мы можем только завернуть его, поэтому у нас есть .value
доступ к использованию
Давайте посмотрим на конкретную реализацию
import { reactive } from "./reactive";
import { trackEffects, triggerEffects } from './effect'
export const isObject = (value) => {
return typeof value === 'object' && value !== null
}
// 将对象转化为响应式的
function toReactive(value) {
return isObject(value) ? reactive(value) : value
}
class RefImpl {
public _value;
public dep = new Set; // 依赖收集
public __v_isRef = true; // 是ref的标识
// rawValue 传递进来的值
constructor(public rawValue, public _shallow) {
// 1、判断如果是对象 使用reactive将对象转为响应式的
// 浅ref不需要再次代理
this._value = _shallow ? rawValue : toReactive(rawValue);
}
get value() {
// 取值的时候依赖收集
trackEffects(this.dep)
return this._value;
}
set value(newVal) {
if (newVal !== this.rawValue) {
// 2、set的值不等于初始值 判断新值是否是对象 进行赋值
this._value = this._shallow ? newVal : toReactive(newVal);
// 赋值完 将初始值变为本次的
this.rawValue = newVal
triggerEffects(this.dep)
}
}
}
复制代码
Приведенный выше код представляет собой упаковку исходного значения, оно упаковано как объект, и доступ к исходному значению осуществляется через методы get value
и , в результате чего выполняется необходимая операция, что на самом деле является беспомощным выбором.set value
.value
相当于两瓶毒药,你得选一瓶
Нельзя есть и рыбу, и медвежью лапу
Почему деструктурирование ES6 и невозможность его использования разрушит его адаптивные функции
Первый вопрос, наконец, понят, поэтому давайте рассмотрим второй самый важный вопрос,为什么结构赋值,会破坏响应式特性
фон прокси
Прежде чем мы начнем, давайте обсудим, почему изменение响应式方案
Vue2 основан на Object.defineProperty , но имеет много дефектов, таких как невозможность отслеживать модификацию массива на основе индексов, а также не поддерживаются такие дефекты, как Map, Set, WeakMap и WeakSet .
На самом деле, это не задерживает наше развитие, vue2 по-прежнему остается мейнстримом,
Насколько я понимаю 与时俱进
, 新一代的版本,一定要紧跟语言的特性,一定要符合新时代的书写风格
хотя proxy
и есть много улучшений по сравнению с Object.defineProperty, он не лишен недостатков.Например,不兼容IE
Как может быть что-то совершенное в мире?
Ваше великое мужество заключается в том, чтобы отказаться от настоящего, чтобы построить будущее!
Принцип реализации
Разобравшись с предысторией, давайте рассмотрим принцип в режиме фейка proxy
, хотя это все тухло.
Однако при написании гидрологии на что следует обратить внимание: два слова - когерентность

const obj = {
count: 1
};
const proxy = new Proxy(obj, {
get(target, key, receiver) {
console.log("这里是get");
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log("这里是set");
return Reflect.set(target, key, value, receiver);
}
});
console.log(proxy)
console.log(proxy.count)
复制代码
Приведенный выше код представляет собой особый способ использования Proxy.Благодаря сотрудничеству с Reflect можно реализовать перехват объектов.

С такой зависимостью можно добиться отзывчивости, можно обнаружить, что весь объект этого obj перехватывается, но вы обнаружите, что объект вложен на один уровень глубже.
Например:
const obj = {
count: 1,
b: {
c: 2
}
};
console.log(proxy.b)
console.log(proxy.b.c)
复制代码
Он не может перехватить, мы должны упаковать
const obj = {
a: {
count: 1
}
};
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
console.log("这里是get");
// 判断如果是个对象在包装一次,实现深层嵌套的响应式
if (typeof target[key] === "object") {
return reactive(target[key]);
};
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log("这里是set");
return Reflect.set(target, key, value, receiver);
}
});
};
const proxy = reactive(obj);
复制代码
Ну, принцип сделан, давайте формально изучим
Теперь перечислю несколько известных мне ситуаций, в которых теряется отзывчивость:
-
1. Деконструировать props
объект, потому что он теряет свою отзывчивость -
2. Прямое присвоение reactive
реактивных объектов -
3. vuex
Назначение API средней комбинации
Разрушение props
объектов, потому что они теряют отзывчивость
const obj = {
a: {
count: 1
},
b: 1
};
//reactive 是上文中的reactive
const proxy = reactive(obj);
const {
a,
b
} = proxy;
console.log(a)
console.log(b)
console.log(a.count)
复制代码

В приведенном выше коде мы обнаруживаем, что присваивание деструктурирования, b 不会触发响应式
, a如果你访问的时候
, вызовет отклик
Почему это?
Не волнуйтесь, давайте объясним по одному?
Давайте сначала обсудим, почему деструктурирующее задание потеряет отзывчивость?
Мы знаем деструктурирующее присваивание, различаем присваивание примитивных типов и присваивание ссылочных типов,
原始类型的赋值相当于按值传递
,引用类型的值就相当于按引用传递
эквивалентно
// 假设a是个响应式对象
const a={ b:1}
// c 此时就是一个值跟当前的a 已经不沾边了
const c=a.b
// 你直接访问c就相当于直接访问这个值 也就绕过了 a 对象的get ,也就像原文中说的失去响应式
复制代码
Так почему a
же он отзывчив?
Поскольку a
это ссылочный тип, мы помним решение в приведенном выше коде. Если он, object
то переупаковать как реактивный
Формально из-за текущей фичи, если это ссылочный тип, вы не потеряете отзывчивость при доступе к его содержимому
// 假设a是个响应式对象
const a={ b:{c:3}}
// 当你访问a.b的时候就已经重新初始化响应式了,此时的c就已经是个代理的对象
const c=a.b
// 你直接访问c就相当于访问一个响应式对象,所以并不会失去响应式
复制代码
Вышеприведенное примерно объясняет, почему присваивание деструктурирования может потерять отзывчивость.Я думаю, документу лень объяснять причину, поэтому я просто установил правило, вы!
Не используйте его, сохраните ошибки, которые вы считаете vue
правдой, и заранее измените привычки пользователя! Не используется для
Прямое присвоение reactive
реактивных объектов
Когда мы впервые использовали vue3, мы указали, что будет написан следующий код
const vue = reactive({ a: 1 })
vue = { b: 2 }
复制代码
А потом задавать вопросы reactive
разве это не отзывчиво? Почему после того, как я присвоил значение, у него пропала отзывчивость, а потом он орал, фигня вью
На самом деле, это потому, что вы не понимаете концепцию js native, на самом деле 尤大
вы приложили максимум усилий, чтобы не допустить ошибок.
Например, из-за проблемы деструктурирующего присваивания он прямо запрещает реактивное деструктурирующее присваивание.

Когда вы используете операцию присваивания деструктурирования, она напрямую отключает
Потом кто-то снова спросил, 为啥props 不给禁用了呢
?
因为你的props 的数据可能不是响应式的啊,不是响应式的,我得能啊
, особенно он не может мешать пользователю использовать новый синтаксис.
Так что это одно и то же предложение: 框架现在的呈现,其实充满了取舍
Иногда это действительно две бутылки яда, выбери одну!
Вернемся к теме, поговорим о нативном синтаксисе js.
Первое, что нужно подтвердить, это то, что назначение ссылочного типа нативного js на самом деле основано на ссылочном адресе!
// 当reactive 之后返回一个代理对象的地址被vue 存起来,
// 用一个不恰当的比喻来说,就是这个地址具备响应式的能力
const vue = reactive({ a: 1 })
// 而当你对于vue重新赋值的时候不是将新的对象赋值给那个地址,而是将vue 换了个新地址
// 而此时新地址不具备响应式,可不就失去响应式了吗
vue = { b: 2 }
复制代码
Выше приведено reactive
объяснение потери отзывчивости, так что это также причина, по которой многие пользователи ругаются.不符合他的使用习惯了,这都是被vue2 培养起来的一代
Здесь я хочу сказать честное слово за Тебя Да 人家又没收你钱,还因为他,你有口饭吃
,
Ты сам не можешь идти в ногу со временем и принимать новое, это ты 能耐
,
это типично端起碗吃肉,放下筷子骂娘
vuex
Назначение API средней композиции
Использование присваивания в vuex также может привести к потере отклика.
import { computed } from 'vue'
import { useStore } from 'vuex'
export default {
setup () {
const store = useStore()
return {
// 在 computed 函数中访问 state
count: computed(() => store.state.count),
// 在 computed 函数中访问 getter
double: computed(() => store.getters.double)
}
}
}
复制代码
В приведенном выше коде мы обнаружили, что store.getters.double
необходимо computed
обернуть с помощью . На самом деле причина та же, и она же является причиной присваивания переменных, здесь мы их повторять не будем!
в конце концов
Эта статья, в процессе использования vue3, некоторый опыт и исследования после майнинга, надеюсь, она будет вам полезна, чтобы вы могли получить повышение и прибавку к зарплате на работе!
Наконец, в конце концов, я буду продвигать свой анализ исходного кода vue.Может быть, анализ не очень хороший, но он весь читается построчно.Может быть, вы можете подумать о предложении или предложении после его прочтения, что полезно!
Адрес анализа исходного кода [1]
приветственная звезда
Об этой статье
Автор: фермер Лао Цзи
https://juejin.cn/post/7114596904926740493
Конец
》》Банк вопросов, который используют интервьюеры, приходите и смотрите 《》
Не забудьте поставить лайк в конце!
Удачи в 2022 году! Жестокая красота! Сильно худой!