효과는 저수준 API이기 때문에 일반적으로 효과를 직접 사용하지 않습니다. Vue3을 사용하면 Vue가 기본적으로 효과를 호출합니다. 효과(Effect)는 효과(Effect)로 번역되는데, 이는 작동하게 만드는 기능이 우리가 전달하는 함수이므로 효과의 기능은 우리가 전달하는 기능을 적용시키는 것, 즉 이 기능을 실행하는 것입니다. 실행 과정을 간단히 도식화하면 다음과 같습니다.
다음으로는 먼저 예제를 통해 Effect의 기본 사용법을 이해한 후 원리를 이해해 보겠습니다.
1. 효과 사용법
1. 기본 사용법
const obj = reactive({count: 1}) const runner = effect(() => { console.log(obj.count) }) obj.count++
결과는 먼저 1을 인쇄하고 obj.count++
뒤에 2를 인쇄합니다. obj.count++
之后打印出2。
流程简图如下:
运行effect(fun)
// 先执行 fun() // 打印出1 const runner = new ReactiveEffect(fn) return runner runner: { run() { this.fun() //执行fun }, stop() { } }
console.log(obj.count)
track依赖收集 结构如下:
obj.count++
触发依赖,执行runner.run(), 实际运行的是
() => { console.log(obj.count) }
所以又打印出2
2、lazy属性为true
此值为 true 时,只有在第一次手动调用 runner 后,依赖数据变更时,才会自动执行 effect 的回调,可以理解为 effect 的是在手动调用 runner 后才首次执行
const obj = reactive({count: 1}) const runner = effect(() => { console.log(obj.count) }, { lazy: true }) runner() obj.count++
只会打印出2
原因是effect源码中有如下逻辑:
3、options中包含onTrack
let events = [] const onTrack = (e) => { events.push(e) } const obj = reactive({ foo: 1, bar: 2 }) const runner = effect( () => { console.log(obj.foo) }, { onTrack } ) console.log('runner', runner) obj.foo++ console.log("events", events)
看下events的打印结果:
[ { effect: runner, // effect 函数的返回值 target: toRaw(obj), // 表示的是哪个响应式数据发生了变化 type: TrackOpTypes.GET, // 表示此次记录操作的类型。 get 表示获取值 key: 'foo' } ]
二、源码分析
1、effect方法的实现
// packages/reactivity/src/effect.ts export interface ReactiveEffectOptions extends DebuggerOptions { lazy?: boolean scheduler?: EffectScheduler scope?: EffectScope allowRecurse?: boolean onStop?: () => void } export function effect<T = any>( fn: () => T, // 副作用函数 options?: ReactiveEffectOptions // 结构如上 ): ReactiveEffectRunner { // 如果 fn 对象上有 effect 属性 if ((fn as ReactiveEffectRunner).effect) { // 那么就将 fn 替换为 fn.effect.fn fn = (fn as ReactiveEffectRunner).effect.fn } // 创建一个响应式副作用函数 const _effect = new ReactiveEffect(fn) if (options) { // 将配置项合并到响应式副作用函数上 extend(_effect, options) // 如果配置项中有 scope 属性(该属性的作用是指定副作用函数的作用域) if (options.scope) recordEffectScope(_effect, options.scope) } if (!options || !options.lazy) { // options.lazy 不为true _effect.run() // 执行响应式副作用函数 首次执行fn() } // _effect.run作用域绑定到_effect const runner = _effect.run.bind(_effect) as ReactiveEffectRunner // 将响应式副作用函数赋值给 runner.effect runner.effect = _effect return runner }
核心代码:
创建一个响应式副作用函数const _effect = new ReactiveEffect(fn)
,其运行结果如下:
非lazy状态执行响应式副作用函数_effect.run()
if (!options || !options.lazy) { // options.lazy 不为true _effect.run() // 执行响应式副作用函数 首次执行fn() }
_effect.run
作用域绑定到_effect
// _effect.run作用域绑定到_effect const runner = _effect.run.bind(_effect) as ReactiveEffectRunner
返回副作用函数runner
2、ReactiveEffect函数源码
export class ReactiveEffect<T = any> { active = true deps: Dep[] = [] // 响应式依赖项的集合 parent: ReactiveEffect | undefined = undefined /** * Can be attached after creation * @internal */ computed?: ComputedRefImpl<T> /** * @internal */ allowRecurse?: boolean /** * @internal */ private deferStop?: boolean onStop?: () => void // dev only onTrack?: (event: DebuggerEvent) => void // dev only onTrigger?: (event: DebuggerEvent) => void constructor( public fn: () => T, public scheduler: EffectScheduler | null = null, scope?: EffectScope ) { // 记录当前 ReactiveEffect 对象的作用域 recordEffectScope(this, scope) } run() { // 如果当前 ReactiveEffect 对象不处于活动状态,直接返回 fn 的执行结果 if (!this.active) { return this.fn() } // 寻找当前 ReactiveEffect 对象的最顶层的父级作用域 let parent: ReactiveEffect | undefined = activeEffect let lastShouldTrack = shouldTrack // 是否要跟踪 while (parent) { if (parent === this) { return } parent = parent.parent } try { // 记录父级作用域为当前活动的 ReactiveEffect 对象 this.parent = activeEffect activeEffect = this // 将当前活动的 ReactiveEffect 对象设置为 “自己” shouldTrack = true // 将 shouldTrack 设置为 true (表示是否需要收集依赖) // effectTrackDepth 用于标识当前的 effect 调用栈的深度,执行一次 effect 就会将 effectTrackDepth 加 1 trackOpBit = 1 << ++effectTrackDepth if (effectTrackDepth <= maxMarkerBits) { // 初始依赖追踪标记 initDepMarkers(this) } else { // 清除依赖追踪标记 cleanupEffect(this) } // 返回副作用函数执行结果 return this.fn() } finally { // 如果 effect调用栈的深度 没有超过阈值 if (effectTrackDepth <= maxMarkerBits) { // 确定最终的依赖追踪标记 finalizeDepMarkers(this) } // 执行完毕会将 effectTrackDepth 减 1 trackOpBit = 1 << --effectTrackDepth // 执行完毕,将当前活动的 ReactiveEffect 对象设置为 “父级作用域” activeEffect = this.parent // 将 shouldTrack 设置为上一个值 shouldTrack = lastShouldTrack // 将父级作用域设置为 undefined this.parent = undefined // 延时停止,这个标志是在 stop 方法中设置的 if (this.deferStop) { this.stop() } } } stop() { // stopped while running itself - defer the cleanup // 如果当前 活动的 ReactiveEffect 对象是 “自己” // 延迟停止,需要执行完当前的副作用函数之后再停止 if (activeEffect === this) { // 在 run 方法中会判断 deferStop 的值,如果为 true,就会执行 stop 方法 this.deferStop = true } else if (this.active) {// 如果当前 ReactiveEffect 对象处于活动状态 cleanupEffect(this) // 清除所有的依赖追踪标记 if (this.onStop) { this.onStop() } this.active = false // 将 active 设置为 false } } }
run方法的作用就是执行副作用函数,并且在执行副作用函数的过程中,会收集依赖;
stop方法的作用就是停止当前的ReactiveEffect对象,停止之后,就不会再收集依赖了;
activeEffect和this并不是每次都相等的,因为activeEffect会跟着调用栈的深度而变化,而this则是固定的;
三、依赖收集相关
1、如何触发依赖收集
在副作用函数中, obj.count
就会触发依赖收集
const runner = effect(() => { console.log(obj.count) })
触发的入口在get拦截器里面
function createGetter(isReadonly = false, shallow = false) { // 闭包返回 get 拦截器方法 return function get(target: Target, key: string | symbol, receiver: object) { // ... if (!isReadonly) { track(target, TrackOpTypes.GET, key) } // ... }
2、track源码
const targetMap = new WeakMap(); /** * 收集依赖 * @param target target 触发依赖的对象,例子中的obj * @param type 操作类型 比如obj.count就是get * @param key 指向对象的key, 比如obj.count就是count */ export function track(target: object, type: TrackOpTypes, key: unknown) { if (shouldTrack && activeEffect) { // 是否应该依赖收集 & 当前的new ReactiveEffect()即指向的就是当前正在执行的副作用函数 // 如果 targetMap 中没有 target,就会创建一个 Map let depsMap = targetMap.get(target) if (!depsMap) { targetMap.set(target, (depsMap = new Map())) } let dep = depsMap.get(key) if (!dep) { depsMap.set(key, (dep = createDep())) // createDep 生成dep = { w:0, n: 0} } const eventInfo = __DEV__ ? { effect: activeEffect, target, type, key } : undefined trackEffects(dep, eventInfo) } }
shouldTrack在上面也讲过,它的作用就是控制是否收集依赖;
activeEffect就是我们刚刚讲的ReactiveEffect对象,它指向的就是当前正在执行的副作用函数;
track方法的作用就是收集依赖,它的实现非常简单,就是在targetMap中记录下target和key;
targetMap是一个WeakMap,它的键是target,值是一个Map,这个Map的键是key,值是一个Set;
targetMap的结构伪代码如下:
targetMap = { target: { key: dep }, // 比如: obj: { count: { w: 0, n: 0 } } }
以上是最原始的depMap
dev环境为增加响应式调试会增加eventInfo
const eventInfo = __DEV__ ? { effect: activeEffect, target, type, key } : undefined
eventInfo结构如下:
trackEffects(dep, eventInfo)
如果 dep 中没有当前的 ReactiveEffect 对象,就会添加进去, 作用就把对象的属性操作与副作用函数建立关联,接下来看trackEffects
3、trackEffects(dep, eventInfo)源码解读
export function trackEffects( dep: Dep, debuggerEventExtraInfo?: DebuggerEventExtraInfo ) { let shouldTrack = false if (effectTrackDepth <= maxMarkerBits) { if (!newTracked(dep)) { // 执行之前 dep = Set(0) {w: 0, n: 0} // 执行之后 dep = Set(0) {w: 0, n: 2} dep.n |= trackOpBit // set newly tracked shouldTrack = !wasTracked(dep) } } else { // Full cleanup mode. shouldTrack = !dep.has(activeEffect!) } if (shouldTrack) { // 将activeEffect添加到dep dep.add(activeEffect!) activeEffect!.deps.push(dep) if (__DEV__ && activeEffect!.onTrack) { // onTrack逻辑 activeEffect!.onTrack( extend( { effect: activeEffect! }, debuggerEventExtraInfo! ) ) } } }
dep.add(activeEffect!)
如果 dep 中没有当前的 ReactiveEffect 对象,就会添加进去
最终生成的depTarget结构如下:
四、触发依赖
比如例子中代码obj.count++

effect(fun)
🎜function createSetter(shallow = false) { return function set( target: object, key: string | symbol, value: unknown, receiver: object ): boolean { //... const result = Reflect.set(target, key, value, receiver) // don't trigger if target is something up in the prototype chain of original if (target === toRaw(receiver)) { if (!hadKey) { trigger(target, TriggerOpTypes.ADD, key, value) // 触发ADD依赖更新 } else if (hasChanged(value, oldValue)) { trigger(target, TriggerOpTypes.SET, key, value, oldValue) //触发SET依赖更新 } } //... }🎜
console.log(obj.count)
track 종속성 수집 구조는 다음과 같습니다. 🎜🎜
obj.count++는 종속성을 트리거하고, runer.run()을 실행합니다. 실제로 실행 중인 것은 🎜<pre class='brush:php;toolbar:false;'>// 路径:packages/reactivity/src/effect.ts
export function trigger(
target: object,
type: TriggerOpTypes,
key?: unknown,
newValue?: unknown,
oldValue?: unknown,
oldTarget?: Map<unknown, unknown> | Set<unknown>
) {
const depsMap = targetMap.get(target) // 获取depsMap, targetMap是在track中创建的依赖
if (!depsMap) {
// never been tracked
return
}
let deps: (Dep | undefined)[] = []
if (type === TriggerOpTypes.CLEAR) {
// collection being cleared
// trigger all effects for target
deps = [...depsMap.values()]
} else if (key === &#39;length&#39; && isArray(target)) {
const newLength = Number(newValue)
depsMap.forEach((dep, key) => {
if (key === &#39;length&#39; || key >= newLength) {
deps.push(dep)
}
})
} else {
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
deps.push(depsMap.get(key))
}
// also run for iteration key on ADD | DELETE | Map.SET
switch (type) {
case TriggerOpTypes.ADD:
if (!isArray(target)) {
deps.push(depsMap.get(ITERATE_KEY))
if (isMap(target)) {
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
}
} else if (isIntegerKey(key)) {
// new index added to array -> length changes
deps.push(depsMap.get(&#39;length&#39;))
}
break
case TriggerOpTypes.DELETE:
if (!isArray(target)) {
deps.push(depsMap.get(ITERATE_KEY))
if (isMap(target)) {
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
}
}
break
case TriggerOpTypes.SET:
if (isMap(target)) {
deps.push(depsMap.get(ITERATE_KEY))
}
break
}
}
const eventInfo = __DEV__
? { target, type, key, newValue, oldValue, oldTarget }
: undefined
if (deps.length === 1) {
if (deps[0]) {
if (__DEV__) {
triggerEffects(deps[0], eventInfo)
} else {
triggerEffects(deps[0])
}
}
} else {
const effects: ReactiveEffect[] = []
for (const dep of deps) {
if (dep) {
effects.push(...dep)
}
}
if (__DEV__) {
triggerEffects(createDep(effects), eventInfo)
} else {
triggerEffects(createDep(effects))
}
}
}</pre>🎜이므로 2🎜🎜2가 인쇄됩니다. 게으른 속성은 true입니다🎜🎜이 값이 true인 경우 러너, 종속 데이터가 변경되면 효과의 콜백이 자동으로 실행됩니다. 러너를 수동으로 호출한 후 처음으로 효과가 실행되는 것으로 이해하면 됩니다. 🎜<pre class='brush:php;toolbar:false;'> const eventInfo = __DEV__
? { target, type, key, newValue, oldValue, oldTarget }
: undefined
if (deps.length === 1) {
if (deps[0]) {
if (__DEV__) {
triggerEffects(deps[0], eventInfo)
} else {
triggerEffects(deps[0])
}
}
}</pre>🎜는 2🎜🎜만 출력됩니다. 효과 소스 코드에는 다음 논리가 있습니다. 🎜🎜<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/887/227/168368876252696.png?x-oss-process=image/resize,p_40" class="lazy" alt="효과 사용 방법 Vue3 반응형 코어">🎜🎜3. 옵션에는 onTrack🎜<pre class='brush:php;toolbar:false;'>export function triggerEffects(
dep: Dep | ReactiveEffect[],
debuggerEventExtraInfo?: DebuggerEventExtraInfo
) {
// spread into array for stabilization
const effects = isArray(dep) ? dep : [...dep]
for (const effect of effects) {
if (effect.computed) {
triggerEffect(effect, debuggerEventExtraInfo)
}
}
for (const effect of effects) {
if (!effect.computed) {
triggerEffect(effect, debuggerEventExtraInfo)
}
}
}</pre>🎜이 포함됩니다. 이벤트 보기 인쇄 결과: 🎜🎜<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/887/227/168368876252696.png?x-oss-process=image/resize,p_40" class="lazy" alt="Vue3 반응형 코어의 효과를 사용하는 방법">🎜 <pre class='brush:php;toolbar:false;'>function triggerEffect(
effect: ReactiveEffect,
debuggerEventExtraInfo?: DebuggerEventExtraInfo
) {
if (effect !== activeEffect || effect.allowRecurse) {
// 如果 effect.onTrigger 存在,就会执行,只有开发模式下才会执行
if (__DEV__ && effect.onTrigger) {
effect.onTrigger(extend({ effect }, debuggerEventExtraInfo))
}
// 如果 effect 是一个调度器,就会执行 scheduler
if (effect.scheduler) {
effect.scheduler()
} else {
// 其它情况执行 effect.run()
effect.run()
}
}
}</pre>🎜2. 소스 코드 분석🎜🎜1. 효과 방법 구현🎜rrreee🎜핵심 코드:🎜🎜반응형 부작용 함수 만들기 <code>const _효과 = new ReactiveEffect(fn)
이며 실행 결과는 다음과 같습니다.🎜 🎜
_효과.run()
🎜rrreee🎜 _효과.런
범위는 _효과
🎜rrreee🎜에 바인딩되어 부작용 함수인 Runner🎜 🎜2를 반환합니다. ReactiveEffect 함수 소스 코드🎜rrreee- run 메소드의 기능은 부작용 기능을 실행하는 것이며, 부작용 기능을 실행하는 과정에서 종속성이 수집됩니다. 🎜
- 🎜stop 메소드의 기능은 다음과 같습니다. 현재 ReactiveEffect 객체를 중지합니다. 중지 후에는 종속성이 더 이상 수집되지 않으며 🎜
- 🎜activeEffect는 호출 스택의 깊이에 따라 변경되기 때문에 매번 동일하지 않습니다. 🎜
obj.count>가 종속성 수집을 실행합니다🎜 rrreee🎜트리거 항목은 get 인터셉터에 있습니다🎜rrreee🎜2. 소스 코드 추적🎜rrreee🎜shouldTrack도 위에 언급되어 있습니다. 이 기능은 종속성 수집 여부를 제어하는 것입니다.🎜🎜activeEffect 방금 이야기한 ReactiveEffect 개체입니다. 🎜🎜track 메소드의 기능은 종속성을 수집하는 것입니다. 구현은 매우 간단합니다. 이는 targetMap에 대상과 키를 기록하는 것입니다. key는 target이고 그 값은 Map이고, 그 키는 key이고 그 값은 Set입니다. 🎜🎜targetMap의 구조적 의사 코드는 다음과 같습니다: 🎜rrreee🎜<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/887/227/168368876252696.png?x-oss-process=image/resize,p_40" class="lazy" alt="Vue3 반응형 코어의 효과를 사용하는 방법">🎜🎜위는 가장 독창적인 depMap입니다🎜🎜dev 환경은 반응형 디버깅이 추가됨에 따라 증가할 것입니다eventInfo
🎜rrreee🎜eventInfo의 구조는 다음과 같습니다: 🎜🎜
trackEffects(dep, eventInfo)
🎜🎜dep에 현재 ReactiveEffect 객체가 없으면 추가되고 효과는 객체의 속성 연산과 부작용 함수 연관을 설정한 다음 trackEffects
🎜🎜3, trackEffects(dep, eventInfo) 소스 코드 해석🎜rrreee🎜dep.add(activeEffect)을 살펴보세요. !)
현재 Dep에 ReactiveEffect가 없으면 개체가 추가됩니다🎜🎜

obj.count++
예제의 코드는 집합 차단을 트리거합니다. 종속성 업데이트를 트리거합니다🎜function createSetter(shallow = false) { return function set( target: object, key: string | symbol, value: unknown, receiver: object ): boolean { //... const result = Reflect.set(target, key, value, receiver) // don't trigger if target is something up in the prototype chain of original if (target === toRaw(receiver)) { if (!hadKey) { trigger(target, TriggerOpTypes.ADD, key, value) // 触发ADD依赖更新 } else if (hasChanged(value, oldValue)) { trigger(target, TriggerOpTypes.SET, key, value, oldValue) //触发SET依赖更新 } } //... }
1、trigger依赖更新
// 路径:packages/reactivity/src/effect.ts export function trigger( target: object, type: TriggerOpTypes, key?: unknown, newValue?: unknown, oldValue?: unknown, oldTarget?: Map<unknown, unknown> | Set<unknown> ) { const depsMap = targetMap.get(target) // 获取depsMap, targetMap是在track中创建的依赖 if (!depsMap) { // never been tracked return } let deps: (Dep | undefined)[] = [] if (type === TriggerOpTypes.CLEAR) { // collection being cleared // trigger all effects for target deps = [...depsMap.values()] } else if (key === 'length' && isArray(target)) { const newLength = Number(newValue) depsMap.forEach((dep, key) => { if (key === 'length' || key >= newLength) { deps.push(dep) } }) } else { // schedule runs for SET | ADD | DELETE if (key !== void 0) { deps.push(depsMap.get(key)) } // also run for iteration key on ADD | DELETE | Map.SET switch (type) { case TriggerOpTypes.ADD: if (!isArray(target)) { deps.push(depsMap.get(ITERATE_KEY)) if (isMap(target)) { deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)) } } else if (isIntegerKey(key)) { // new index added to array -> length changes deps.push(depsMap.get('length')) } break case TriggerOpTypes.DELETE: if (!isArray(target)) { deps.push(depsMap.get(ITERATE_KEY)) if (isMap(target)) { deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)) } } break case TriggerOpTypes.SET: if (isMap(target)) { deps.push(depsMap.get(ITERATE_KEY)) } break } } const eventInfo = __DEV__ ? { target, type, key, newValue, oldValue, oldTarget } : undefined if (deps.length === 1) { if (deps[0]) { if (__DEV__) { triggerEffects(deps[0], eventInfo) } else { triggerEffects(deps[0]) } } } else { const effects: ReactiveEffect[] = [] for (const dep of deps) { if (dep) { effects.push(...dep) } } if (__DEV__) { triggerEffects(createDep(effects), eventInfo) } else { triggerEffects(createDep(effects)) } } }
const depsMap = targetMap.get(target)
获取 targetMap 中的 depsMap targetMap结构如下:
执行以上语句之后的depsMap结构如下:
将 depsMap 中 key 对应的 ReactiveEffect 对象添加到 deps 中deps.push(depsMap.get(key))
之后的deps结构如下:
triggerEffects(deps[0], eventInfo)
const eventInfo = __DEV__ ? { target, type, key, newValue, oldValue, oldTarget } : undefined if (deps.length === 1) { if (deps[0]) { if (__DEV__) { triggerEffects(deps[0], eventInfo) } else { triggerEffects(deps[0]) } } }
trigger函数的作用就是触发依赖,当我们修改数据的时候,就会触发依赖,然后执行依赖中的副作用函数。
在这里的实现其实并没有执行,主要是收集一些需要执行的副作用函数,然后在丢给triggerEffects函数去执行,接下来看看triggerEffects函数。
2、triggerEffects(deps[0], eventInfo)
export function triggerEffects( dep: Dep | ReactiveEffect[], debuggerEventExtraInfo?: DebuggerEventExtraInfo ) { // spread into array for stabilization const effects = isArray(dep) ? dep : [...dep] for (const effect of effects) { if (effect.computed) { triggerEffect(effect, debuggerEventExtraInfo) } } for (const effect of effects) { if (!effect.computed) { triggerEffect(effect, debuggerEventExtraInfo) } } }
主要步骤
const effects = isArray(dep) ? dep : [...dep]
获取effects
triggerEffect(effect, debuggerEventExtraInfo)
执行effect,接下来看看源码
3、triggerEffect(effect, debuggerEventExtraInfo)
function triggerEffect( effect: ReactiveEffect, debuggerEventExtraInfo?: DebuggerEventExtraInfo ) { if (effect !== activeEffect || effect.allowRecurse) { // 如果 effect.onTrigger 存在,就会执行,只有开发模式下才会执行 if (__DEV__ && effect.onTrigger) { effect.onTrigger(extend({ effect }, debuggerEventExtraInfo)) } // 如果 effect 是一个调度器,就会执行 scheduler if (effect.scheduler) { effect.scheduler() } else { // 其它情况执行 effect.run() effect.run() } } }
effect.run()就是执行副作用函数
위 내용은 Vue3 반응형 코어의 효과를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

Vue.js는 개발 효율성과 사용자 경험을 향상시키기 위해 프론트 엔드 기술 스택과 밀접하게 통합되어 있습니다. 1) 건설 도구 : 모듈 식 개발을 달성하기 위해 웹 팩 및 롤업과 통합. 2) 주 관리 : Vuex와 통합하여 복잡한 응용 프로그램 상태를 관리합니다. 3) 라우팅 : vuerouter와 통합하여 단일 페이지 응용 프로그램 라우팅을 실현합니다. 4) CSS 전 처리기 : 스타일 개발 효율성을 향상시키기 위해 SASS를 지원하고 덜 지원합니다.

Netflix는 React의 구성 요소 설계 및 가상 DOM 메커니즘이 복잡한 인터페이스와 빈번한 업데이트를 효율적으로 처리 할 수 있기 때문에 REACT를 선택했습니다. 1) 구성 요소 기반 설계를 통해 Netflix는 인터페이스를 관리 가능한 위젯으로 분류하여 개발 효율성 및 코드 유지 관리를 향상시킬 수 있습니다. 2) 가상 DOM 메커니즘은 DOM 운영을 최소화하여 Netflix 사용자 인터페이스의 부드러움과 고성능을 보장합니다.

Vue.js는 사용하기 쉽고 강력하기 때문에 개발자에게 사랑을받습니다. 1) 반응 형 데이터 바인딩 시스템은 뷰를 자동으로 업데이트합니다. 2) 구성 요소 시스템은 코드의 재사용 성과 유지 관리를 향상시킵니다. 3) 컴퓨팅 속성 및 청취자는 코드의 가독성과 성능을 향상시킵니다. 4) vuedevtools를 사용하고 콘솔 오류를 확인하는 것이 일반적인 디버깅 기술입니다. 5) 성능 최적화에는 주요 속성, 계산 된 속성 및 유지 구성 요소 사용이 포함됩니다. 6) 모범 사례에는 명확한 구성 요소 이름 지정, 단일 파일 구성 요소 사용 및 수명주기 후크의 합리적인 사용이 포함됩니다.

vue.js는 효율적이고 유지 관리 가능한 프론트 엔드 애플리케이션을 구축하는 데 적합한 점진적인 JavaScript 프레임 워크입니다. 주요 기능은 다음과 같습니다. 1. 응답 데이터 바인딩, 2. 구성 요소 개발, 3. 가상 Dom. 이러한 기능을 통해 vue.js는 개발 프로세스를 단순화하고 응용 프로그램 성능과 유지 관리를 향상시켜 현대 웹 개발에서 매우 인기가 있습니다.

vue.js와 반응은 각각 고유 한 장점과 단점이 있으며, 선택은 프로젝트 요구 사항 및 팀 조건에 따라 다릅니다. 1) vue.js는 단순하고 사용하기 쉬운 소규모 프로젝트 및 초보자에게 적합합니다. 2) REACT는 풍부한 생태계와 구성 요소 설계로 인해 대규모 프로젝트 및 복잡한 UI에 적합합니다.

vue.js는 여러 기능을 통해 사용자 경험을 향상시킵니다. 1. 응답 시스템은 실시간 데이터 피드백을 실현합니다. 2. 구성 요소 개발은 코드 재사용 성을 향상시킵니다. 3. Vuerouter는 원활한 내비게이션을 제공합니다. 4. 동적 데이터 바인딩 및 전환 애니메이션은 상호 작용 효과를 향상시킵니다. 5. 오류 처리 메커니즘은 사용자 피드백을 보장합니다. 6. 성능 최적화 및 모범 사례는 응용 프로그램 성능을 향상시킵니다.

웹 개발에서 vue.js의 역할은 개발 프로세스를 단순화하고 효율성을 향상시키는 점진적인 JavaScript 프레임 워크 역할을하는 것입니다. 1) 개발자는 반응 형 데이터 바인딩 및 구성 요소 개발을 통해 비즈니스 로직에 집중할 수 있습니다. 2) vue.js의 작동 원리는 반응 형 시스템 및 가상 DOM에 의존하여 성능을 최적화합니다. 3) 실제 프로젝트에서는 Vuex를 사용하여 글로벌 상태를 관리하고 데이터 대응 성을 최적화하는 것이 일반적입니다.

vue.js는 2014 년 Yuxi가 출시하여 사용자 인터페이스를 구축하기 위해 진보적 인 JavaScript 프레임 워크입니다. 핵심 장점은 다음과 같습니다. 1. 응답 데이터 바인딩, 데이터 변경의 자동 업데이트보기; 2. 구성 요소 개발, UI는 독립적이고 재사용 가능한 구성 요소로 분할 될 수 있습니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!
