변수 변경을 구현하는 방법에 따라 관련 종속성 결과도 변경됩니다
원래 price=5
가 price=가 되면 20 code> 뒤의 <code>total
은 40
이 되어야 하지만 실제 total
은 변경되지 않습니다. 해결책은 다음과 같습니다. 변수가 변경되면 다시 계산하면 결과가 최신 결과로 변경됩니다. price=5
变为price=20
后total
应该变为40
,但是实际total
并不会改变。 解决办法可以这样,当变量改变了,重新计算一次,那么结果就会改变为最新的结果。
如果需要重新计算,我们需要将total
语句存储为一个函数,才能实现依赖的变量改变就进行一次依赖项计算。这里就用effect
表示函数名。
来,试一下:
实现了变量price
改变,依赖变量price quantity
的变量total
也发生改变。
下一步,我们要解决的问题是:应该怎么把effect
存储起来,让代码更加有通用性,而不是一直复写effect
,分离出其他的功能的函数各司其职,也就是大家常说的解耦。
怎么实现变量变化,变量改变后就取出effect执行
用什么存储effect
呢?当然是用Set,因为Set会过滤出重复的元素,所以能够保证存储在Set中的函数不是重复的。 这里定义一个存储effect
依赖的变量为dep = new Set()
,定义track
函数表示存储的过程。 定义trigger
函数用以取出dep
中相关的effect
函数执行(这里定义的函数与Vue3源码同名同意义)。
effect
: 会影响结果的函数(要实现响应式的依赖语句)
track
:保存所有的effect
trigger
: 当变量改变重新执行代码
????,解耦之后代码结构更清晰了。
下面需要解决的一个问题:一个object通常有多个属性,比如product = { price: 5, quantity: 2 }
,在保存依赖时只创建了一个dep
的集合,应该给price
和quantity
都创建dep
,因为total
的最终结果依赖这两个属性,其中任何一个改变都要触发trigger
函数。创建了两个dep
就需要一个容器将dep
存储起来。
因为不同的属性名有自己对应的dep
,所以我们用Map结构(键值对形式)来保存不同dep
。
????,一个object的多个属性依赖问题解决,更具有通用性了。
下一个问题是:不可能只有一个对象,多个对象又怎么办?let product = { price: 5, quantity: 2 }
let user = { firstName: "Joe", lastName: "Smith" }
,比如两个对象的时候就需要进一步修改上面的代码了。
这里用WeakMap
数据结构去存储多个需要响应式的object的depsMap
。WeakMap
的基本使用和Map
差不多,只不过WeakMap
只接受对象为键值,而depsMap
是一个Map
结构刚好(必须是)是对象类型。targetMap
作为存储多个depsMap
的容器名。
????,到这里已经基本实现了通用性的响应式代码了,但是还有最后一个问题就是:我们的代码都需要手动执行(自己添加trigger
total
문을 효과
는 함수 이름을 나타내는 데 사용됩니다. 와서 시도해 보세요:
🎜🎜🎜🎜변수가격
이 변경되고, 변수 가격 수량
에 따라 달라지는 변수 총액
도 변경됩니다. 🎜🎜우리가 해결해야 할 다음 문제는 항상 효과
를 복사하고 다른 기능을 분리하는 대신 코드를 보다 다양하게 만들기 위해 효과
를 저장하는 방법입니다. 각각이 수행하는 기능적 기능 모두가 흔히 🎜디커플링🎜이라고 부르는 각자의 의무입니다. 🎜🎜2. 변수 변경 구현 방법🎜🎜변수 변경 구현 방법은? 물론 Set을 사용하면 Set이 반복되는 요소를 필터링하므로 Set에 저장된 기능이 반복되지 않도록 할 수 있습니다. 여기서 효과
종속성을 저장하는 변수는 dep = new Set()
로 정의되고, 저장 프로시저를 나타내기 위해 track
함수가 정의됩니다. . 실행을 위해 dep
에서 관련 효과
함수를 꺼내도록 trigger
함수를 정의합니다(여기에 정의된 함수는 Vue3과 동일한 이름과 의미를 갖습니다). 소스 코드). 🎜효과
: 결과에 영향을 미치는 함수(반응형 종속성 문 구현을 위해) 🎜trigger
: 변수가 변경되면 코드를 다시 실행🎜product = { 가격: 5, 수량: 2 }
와 같은 여러 속성이 있지만 저장할 때 하나의 dep 컬렉션인 경우 <code>total
의 최종 결과가 price
및 Quantity
모두에 대해 dep
가 생성되어야 합니다. > 이 두 속성에 따라 달라지며 둘 중 하나를 변경하면 trigger
기능이 트리거됩니다. 두 개의 dep
을 생성한 후 dep
을 저장하기 위한 컨테이너가 필요합니다. 🎜🎜3. Map에 여러 dep를 저장합니다🎜🎜다양한 속성 이름에는 해당하는 dep
가 있으므로 맵 구조(키-값 쌍 형식)를 사용하여 서로 다른 dep
를 저장합니다. . 🎜🎜🎜🎜 ??? , 객체의 다중 속성 종속성 문제가 해결되고 더 다양해졌습니다. 🎜🎜다음 질문은: 하나의 개체만 갖는 것은 불가능합니다. 여러 개체는 어떻습니까? let product = { 가격: 5, 수량: 2 }
let user = { firstName: "Joe", lastName: "Smith" }
예를 들어 두 개가 있는 경우 개체 위의 코드를 추가로 수정해야 합니다. 🎜🎜4. 계속해서 여러 개체의 depsMap 저장🎜🎜여기서 WeakMap
데이터 구조는 응답성이 필요한 여러 개체의 depsMap
을 저장하는 데 사용됩니다. WeakMap
의 기본 사용법은 Map
과 유사합니다. 단, WeakMap
은 객체만 키 값으로 허용하는 반면 depsMap은 개체를 허용합니다. code>는 <code>Map
구조가 객체 유형이어야 합니다. targetMap
은 여러 depsMap
을 저장하기 위한 컨테이너 이름으로 사용됩니다. 🎜🎜🎜🎜???? , 여기에서는 기본적으로 범용 응답 코드를 구현했지만 마지막 문제가 하나 있습니다. 코드를 수동으로 실행해야 하며(직접 실행하려면 trigger
추가) 자동으로 실행할 수 없습니다. 변수 변경 사항을 자동으로 감지하고 결과를 자동으로 수정하는 방법은 무엇입니까? 🎜🎜5. Core🎜🎜🎜Reflect 및 Proxy를 통한 자체 실행 문제 해결🎜🎜JavaScript에서는 get
처럼 변수를 자동으로 감지하는 게 아니고, 변수를 자동으로 수정하는 것은 set
처럼 되는 걸까요? Vue2.x 버전에서는 ES5의 Obeject.defineProperty()
자체 getter/setter
를 사용하여 이 문제를 해결하세요. ES6의 Proxy
도 이 문제를 해결할 수 있지만 Proxy
는 IE 브라우저와 호환되지 않습니다. 당시에는 Youda가 이 문제를 어떻게 생각했는지 모르겠다는 의견도 있었습니다. 이제 문제는 대답은 - 고려하지 말라는 것입니다. 즉, IE는 전혀 호환되지 않습니다????????. get
、自动修改变量不就是set
吗?在Vue2.x版本中用ES5的Obeject.defineProperty()
自带的getter/setter
去解决这个问题。ES6中Proxy
也能解决这个问题,但是Proxy
不兼任IE浏览器,当时大家还讨论过说不知道尤大怎么去考虑这个问题,现在问题的答案就是——不考虑。也就是根本不考虑IE兼不兼容????????。
Proxy
就是代理的意思,任何对真实数据的操作它都能拦截并且代理操作,也就是说Object
上一些能实现的方法,Proxy
也能实现。Proxy
使用语法是new Proxy(target, hanler)
,handler
是你想实现什么样的代理功能配置。 而Reflect
就更神奇了,它的作用是取代Object
类上的一些方法让Obeject
类更纯粹的代表一个类,不要附加太多方法在上面,比如a in obj
表示判断obj
中是否有a
,在Reflect
中用Reflect.has(a)
比较语义化的方式就可以代替之前的方法。
正是因为这样,Proxy
和Reflect
就对应上了,都有Object
上的方法。 具体关于Reflect
和Proxy
的语法可以参考阮一峰大大的 ES6入门教程。
稍微封装一下我们的函数,名叫Reactive
????,至此,Vue3基本的响应式原理就解析完了。
return
了createReactiveObject
函数,所以去看createReactiveObject
。
前面的代码都是判断各种情况,我们就看最后几行
const observed = new Proxy( target, collectionTypes.has(target.constructor) ? collectionHandlers : baseHandlers )
可以看到Proxy
的handler
为collectionHandlers
或者 baseHandlers
,继续选择一个看一看。
在 baseHandlers
中可以看到导出了get/set/deleteProperty
等属性配置:
我们看一下set
Proxy
는 실제 데이터에 대한 모든 작업, 즉 Object
, Proxy도 구현할 수 있습니다. <code>Proxy
의 사용 구문은 new Proxy(target, hanler)
이고, handler
는 구현하려는 프록시 기능 구성의 종류입니다. 그리고 Reflect
의 기능은 Object
클래스의 일부 메서드를 대체하여 Object
클래스가 더 순수하게 클래스를 나타낼 수 있도록 하는 것입니다. a in obj
와 같이 너무 많은 메소드를 첨부하지 마십시오. 이는 obj
, 에 <code>a
가 있는지 판단하는 것을 의미합니다. Reflect Reflect.has(a)
를 사용하여 이전 메서드를 보다 의미론적인 접근 방식으로 바꾸세요. Proxy
와 Reflect
가 서로 대응하고 둘 다 Object
에 대한 메서드를 갖는 것은 바로 이 때문입니다. Reflect
및 Proxy
의 특정 구문은 Ruan Yifeng의 ES6 입문 튜토리얼을 참조하세요.
Reactive
🎜🎜🎜🎜 ????, 지금까지 Vue3의 기본 반응 원리를 분석했습니다. 🎜return
에는 createReactiveObject
함수가 있으니 createReactiveObject
를 참조하세요. 🎜🎜🎜🎜 이전 코드 다양한 상황을 판단하기 위해 마지막 몇 줄을 살펴보겠습니다🎜rrreee🎜 Proxy
의 handler
가 collectionHandlers
또는 baseHandlers, 계속해서 하나를 선택하고 살펴보세요. 🎜🎜baseHandlers
에서 get/set/deleteProperty
와 같은 속성 구성이 내보내지는 것을 볼 수 있습니다. 🎜🎜🎜🎜set
를 살펴보겠습니다. 🎜🎜🎜 🎜위 내용은 Vue3 Reactive 응답성의 원리는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!