Un article pour parler du composant KeepAlive dans Vue
Récemment, je lisais des points de connaissances liés à Vue. Quand j'ai vu le composant KeepAlive, j'étais curieux de savoir comment il ne se restituait pas lors du basculement entre les composants, alors j'ai regardé de plus près. (Partage de vidéos d'apprentissage : tutoriel vidéo vue)
Si vous êtes également intéressé à savoir comment la mise en œuvre interne spécifique est mise en œuvre ou si vous avez une certaine compréhension mais n'êtes pas assez familier, alors vous pouvez également la consolider ensemble
Conseils : Interview comme celle-ci Quand pouvez-vous interroger à haute voix les autres sur ce point de connaissance ?
Qu'est-ce que KeepAlive ? Fonction KeepAlive
<keepalive></keepalive>
是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例。
KeepAlive 功能
KeepAlive 一词借鉴于 HTTP 协议,在 HTTP 协议里面 KeepAlive 又称持久连接,作用是允许多个请求/响应共用同一个 HTTP 连接,解决了频繁的销毁和创建 HTTP 连接带来的额外性能开销。而同理 Vue 里的 KeepAlive 组件也是为了避免一个组件被频繁的销毁/重建,避免了性能上的开销。
// App.vue <Test :msg="curTab" v-if="curTab === 'Test'"></Test> <HelloWorld :msg="curTab" v-if="curTab === 'HelloWorld'"></HelloWorld> <div @click="toggle">toggle</div>
上述代码可以看到,如果我们频繁点击 toggle 时会频繁的渲染 Test/HelloWorld 组件,当用户频繁的点击时 Test 组件需要频繁的销毁/渲染,这就造成很大的渲染性能损失。
所以为了解决这种性能开销,你需要知道是时候使用 KeepAlive 组件。
<KeepAlive> <component :is="curTab === 'Test' ? Test : HelloWorld" :msg="curTab"></component> </KeepAlive> <div @click="toggle">toggle</div>
可以看这个录屏,在首次加载后再次频繁的切换并没有重新销毁与挂载,而仅仅是将组件进行了失活(而不是销毁),渲染时只需要重新激活就可以,而不需重新挂载,如果要渲染的组件很大,那就能有不错的性能优化。
想要体验的话可以去看看这个例子?官方demo,其中数据会被缓存这个也需要在开发使用中去注意到的
如何实现
实现原理其实很简单,其实就是缓存管理和特定的销毁和渲染逻辑,使得它不同于其他组件。
KeepAlive 组件在卸载组件时并不能真的将其卸载,而是将其放到一个隐藏的容器里面,当被激活时再从隐藏的容器中拿出来挂载到真正的 dom 上就行,这也就对应了 KeepAlive 的两个独特的生命周期activated
和deactivated
。
先来简单了解下组件的挂载过程
所以在 KeepAlive 内的子组件在 mount 和 unmount 的时候会执行特定的渲染逻辑,从而不会去走挂载和销毁逻辑
具体实现(实现一个小而简单的 KeepAlive)
KeepAlive 组件的属性
const KeepAliveImpl: ComponentOptions = { name: "KeepAlive", // 标识这是一个 KeepAlive 组件 __isKeepAlive: true, // props props: { exclude: [String, Array, RegExp], include: [String, Array, RegExp], max: [String, Number] } } // isKeepAlive export const isKeepAlive = (vnode: VNode): boolean => (vnode.type as any).__isKeepAlive
KeepAlive 组件的 setup 逻辑以及渲染逻辑(重点看)
// setup 接着上面的代码 // 获取到当前 KeepAlive 组件实例 const instance = getCurrentInstance()! as any; // 拿到 ctx const sharedContext = instance.ctx as KeepAliveContext; // cache 缓存 // key: vnode.key | vnode.type value: vnode const cache: Cache = new Map() // 需要拿到某些的 renderer 操作函数,需要自己特定执行渲染和卸载逻辑 const { renderer: { p: patch, m: move, um: _unmount, o: { createElement } } } = sharedContext // 隐藏的容器,用来存储需要隐藏的 dom const storeageContainer = createElement('div') // 存储当前的子组件的缓存 key let pendingKey: CacheKey | null = null sharedContext.activate = (vnode, container, anchor) => { // KeepAlive 下组件激活时执行的 move 逻辑 move(vnode, container, anchor, 0 /* ENTER */) } sharedContext.deactivate = (vnode) => { // KeepAlive 下组件失活时执行的 move 逻辑 move(vnode, storeageContainer, null, 1 /* LEAVE */) } return () => { // 没有子组件 if (!slots.default) { return null; } const children = slots.default() as VNode[]; const rawNode = children[0]; let vnode = rawNode; const comp = vnode.type as ConcreteComponent; const name = comp.displayName || comp.name const { include, exclude } = props; // 没有命中的情况 if ( (include && (!name || !matches(include, name))) || (exclude && name && matches(exclude, name)) ) { // 直接渲染子组件 return rawNode; } // 获取子组件的 vnode key const key = vnode.key == null ? comp : vnode.key; // 获取子组件缓存的 vnode const cachedVNode = cache.get(key); pendingKey = key; // 命中缓存 if (cachedVNode) { vnode.el = cachedVNode.el; // 继承组件实例 vnode.component = cachedVNode.component; // 在 vnode 上更新 shapeFlag,标记为 COMPONENT_KEPT_ALIVE 属性,防止渲染器重新挂载 vnode.shapeFlag |= ShapeFlags.COMPONENT_KEPT_ALIVE } else { // 没命中将其缓存 cache.set(pendingKey, vnode) } // 在 vnode 上更新 shapeFlag,标记为 COMPONENT_SHOULD_KEEP_ALIVE 属性,防止渲染器将组件卸载了 vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE // 渲染组件 vnode return vnode; }
KeepAlive组件 mount 时挂载 renderer 到 ctx 上
在 KeepAlive 组件内会从 sharedContext 上的 renderer 上拿到一些方法比如 move、createElement 等
function mountComponent() { // ... if (isKeepAlive(initialVNode)) { ;(instance.ctx as KeepAliveContext).renderer = internals } }
子组件执行特定的销毁和渲染逻辑
首先从上面可以看到,在渲染 KeepAlive 组件时会对其子组件的 vnode 上增加对应的 shapeFlag 标志
比如COMPONENT_KEPT_ALIVE
标志,组件挂载的时候告诉渲染器这个不需要 mount 而需要特殊处理
const processComponent = ( n1: VNode | null, n2: VNode, container: RendererElement, anchor: RendererNode | null, ) => { if (n1 == null) { // 在 KeepAlive 组件渲染时会对子组件增加 COMPONENT_KEPT_ALIVE 标志 // 挂载子组件时会判断是否 COMPONENT_KEPT_ALIVE ,如果是不会调用 mountComponent 而是直接执行 activate 方法 if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) { ;(parentComponent!.ctx as KeepAliveContext).activate( n2, container, anchor ) } // ... } }
同理COMPONENT_SHOULD_KEEP_ALIVE
标志也是用来在组件卸载的时候告诉渲染器这个不需要 unmount 而需要特殊处理。
const unmount: UnmountFn = (vnode) => { // ... // 在 KeepAlive 组件渲染时会对子组件增加 COMPONENT_SHOULD_KEEP_ALIVE 标志 // 然后在子组件卸载时并不会真实的卸载而是调用 KeepAlive 的 deactivate 方法 if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) { ;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode) return } }
如何挂载
KeepAlive est emprunté au protocole HTTP, KeepAlive est également appelé connexion persistante. Sa fonction est d'autoriser plusieurs requêtes/réponses. partagent la même connexion HTTP, ce qui résout la surcharge de performances supplémentaire causée par la destruction et la création fréquentes de connexions HTTP. De la même manière, le composant KeepAlive dans Vue est également conçu pour empêcher un composant d'être fréquemment détruit/reconstruit, évitant ainsi une surcharge de performances.activated
和deactivated
export function onActivated( hook: Function, target?: ComponentInternalInstance | null ) { // 注册 activated 的回调函数到当前的 instance 的钩子函数上 registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target) } export function onDeactivated( hook: Function, target?: ComponentInternalInstance | null ) { // 注册 deactivated 的回调函数到当前的 instance 的钩子函数上 registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target) }
// renderer.ts // mount 函数逻辑 const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized ) => { // ... const instance: ComponentInternalInstance = compatMountInstance || (initialVNode.component = createComponentInstance( initialVNode, parentComponent, parentSuspense )) // 执行 setup setupComponent(instance) } // setupcomponent 处理 setup 函数值 export function setupComponent( instance: ComponentInternalInstance, isSSR = false ) { // ... const isStateful = isStatefulComponent(instance) // ... const setupResult = isStateful // setupStatefulComponent 函数主要功能是设置当前的 instance ? setupStatefulComponent(instance, isSSR) : undefined // ... } function setupStatefulComponent( instance: ComponentInternalInstance ){ if (setup) { //设置当前实例 setCurrentInstance(instance) // 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集 const setupResult = callWithErrorHandling( setup, instance, ErrorCodes.SETUP_FUNCTION, [__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext] ) // currentInstance = null; unsetCurrentInstance() } }

🎜Comment mettre en œuvre🎜🎜🎜Le principe de mise en œuvre est en fait très simple. il s'agit d'une 🎜gestion du cache et d'une logique spécifique de destruction et de rendu🎜, ce qui le rend différent des autres composants. 🎜🎜Le composant KeepAlive ne peut pas vraiment être désinstallé lors de la 🎜désinstallation du composant, au lieu de cela, il est placé dans un conteneur caché🎜 Lorsqu'il est activé, il est retiré du conteneur caché et monté sur le vrai dom. aux deux cycles de vie uniques de KeepAlive activé
et désactivé
. 🎜🎜
🎜🎜Commençons par comprendre brièvement le processus de montage des composants🎜🎜🎜
Ainsi, le sous-composant 🎜 de KeepAlive exécutera une logique de rendu spécifique lors du montage et du démontage, afin que la logique de montage et de destruction ne soit pas effectuée 🎜🎜🎜Implémentation concrète (implémentation d'un petit et simple KeepAlive)🎜🎜 Propriétés du composant KeepAlive🎜🎜🎜sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexionConfiguration du composant KeepAlive Logique et logique de rendu (focus)🎜 🎜🎜sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexionMontez le moteur de rendu sur le composant KeepAlive lors du montage sur ctx 🎜🎜🎜🎜 dans le Le composant KeepAlive obtiendra certaines méthodes du moteur de rendu sur sharedContext telles que move, createElement, etc. 🎜sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionLe sous-composant exécute une logique de destruction et de rendu spécifique🎜🎜🎜🎜Tout d'abord, comme vous pouvez le voir ci-dessus, lors du 🎜rendu du composant KeepAlive, le drapeau shapeFlag correspondant sera ajouté au vnode du sous-composant🎜🎜🎜 Par exemple , l'indicateur COMPONENT_KEPT_ALIVE
indique au moteur de rendu lorsque le composant est monté qu'il ne nécessite pas de montage mais nécessite un traitement spécial🎜rrreee🎜De même, l'indicateur COMPONENT_SHOULD_KEEP_ALIVE
est également utilisé pour indiquer au composant lorsqu'il est désinstallé. Le moteur de rendu n'a pas besoin d'être démonté mais nécessite un traitement spécial. 🎜rrreeeComment monter activé
et désactivé</ code> Cycle de vie (vous n'avez pas besoin de vous concentrer sur le cycle de vie) 🎜🎜🎜🎜Tout d'abord, ces deux cycles de vie sont déclarés de manière unique dans le composant KeepAlive et sont directement exportés et utilisés. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function onActivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 activated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)
}
export function onDeactivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 deactivated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>然后因为这两个生命周期会注册在 setup 里面,所以只要执行 setup 就会将两个生命周期的回调函数注册到当前的 instance 实例上</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// renderer.ts
// mount 函数逻辑
const mountComponent = (initialVNode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
// ...
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
// 执行 setup
setupComponent(instance)
}
// setupcomponent 处理 setup 函数值
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
// ...
const isStateful = isStatefulComponent(instance)
// ...
const setupResult = isStateful
// setupStatefulComponent 函数主要功能是设置当前的 instance
? setupStatefulComponent(instance, isSSR)
: undefined
// ...
}
function setupStatefulComponent(
instance: ComponentInternalInstance
){
if (setup) {
//设置当前实例
setCurrentInstance(instance)
// 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
// currentInstance = null;
unsetCurrentInstance()
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>最后在执行<code>sharedContext.activate
和sharedContext.deactivate
的时候将注册在实例上的回调函数取出来直接执行就OK了,执行时机在 postRender 之后sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexion
以下是关于上述demo如何实现的简化流程图

需要注意的知识点
1、什么时候缓存
KeepAlive 组件的onMounted
和onUpdated
生命周期时进行缓存
2、什么时候取消缓存
缓存数量超过设置的 max 时
- 监听 include 和 exclude 修改的时候,会读取缓存中的知进行判断是否需要清除缓存
修剪缓存的时候也要 unmount(如果该缓存不是当前组件)或者 resetShapeFlag 将标志为从 KeepAlive 相关 shapeFlag 状态重置为 STATEFUL_COMPONENT 状态(如果该缓存是当前组件,但是被exclude了),当然 unmount 函数内包含 resetShapeFlag 操作
3、缓存策略
KeepAlive 组件的缓存策略是 LRU(last recently used)缓存策略
核心思想在于需要把当前访问或渲染的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪。
看下面的图更加直观,图片来源一篇讲keepAlive 缓存优化的文章

4、如何添加到 vue devtools 组件树上
sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexion5、缓存的子组件 props 更新处理
当子组件有 prop 更新时是需要重新去 patch 的,所以在 activate 的时候需要重新执行 patch 进行子组件更新
sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

🎜Implémentation concrète (implémentation d'un petit et simple KeepAlive)🎜🎜 Propriétés du composant KeepAlive🎜🎜🎜sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexionConfiguration du composant KeepAlive Logique et logique de rendu (focus)🎜 🎜🎜sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexionMontez le moteur de rendu sur le composant KeepAlive lors du montage sur ctx 🎜🎜🎜🎜 dans le Le composant KeepAlive obtiendra certaines méthodes du moteur de rendu sur sharedContext telles que move, createElement, etc. 🎜sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionLe sous-composant exécute une logique de destruction et de rendu spécifique🎜🎜🎜🎜Tout d'abord, comme vous pouvez le voir ci-dessus, lors du 🎜rendu du composant KeepAlive, le drapeau shapeFlag correspondant sera ajouté au vnode du sous-composant🎜🎜🎜 Par exemple , l'indicateur COMPONENT_KEPT_ALIVE
indique au moteur de rendu lorsque le composant est monté qu'il ne nécessite pas de montage mais nécessite un traitement spécial🎜rrreee🎜De même, l'indicateur COMPONENT_SHOULD_KEEP_ALIVE
est également utilisé pour indiquer au composant lorsqu'il est désinstallé. Le moteur de rendu n'a pas besoin d'être démonté mais nécessite un traitement spécial. 🎜rrreeeComment monter activé
et désactivé</ code> Cycle de vie (vous n'avez pas besoin de vous concentrer sur le cycle de vie) 🎜🎜🎜🎜Tout d'abord, ces deux cycles de vie sont déclarés de manière unique dans le composant KeepAlive et sont directement exportés et utilisés. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function onActivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 activated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)
}
export function onDeactivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 deactivated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>然后因为这两个生命周期会注册在 setup 里面,所以只要执行 setup 就会将两个生命周期的回调函数注册到当前的 instance 实例上</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// renderer.ts
// mount 函数逻辑
const mountComponent = (initialVNode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
// ...
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
// 执行 setup
setupComponent(instance)
}
// setupcomponent 处理 setup 函数值
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
// ...
const isStateful = isStatefulComponent(instance)
// ...
const setupResult = isStateful
// setupStatefulComponent 函数主要功能是设置当前的 instance
? setupStatefulComponent(instance, isSSR)
: undefined
// ...
}
function setupStatefulComponent(
instance: ComponentInternalInstance
){
if (setup) {
//设置当前实例
setCurrentInstance(instance)
// 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
// currentInstance = null;
unsetCurrentInstance()
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>最后在执行<code>sharedContext.activate
和sharedContext.deactivate
的时候将注册在实例上的回调函数取出来直接执行就OK了,执行时机在 postRender 之后sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexion
以下是关于上述demo如何实现的简化流程图

需要注意的知识点
1、什么时候缓存
KeepAlive 组件的onMounted
和onUpdated
生命周期时进行缓存
2、什么时候取消缓存
缓存数量超过设置的 max 时
- 监听 include 和 exclude 修改的时候,会读取缓存中的知进行判断是否需要清除缓存
修剪缓存的时候也要 unmount(如果该缓存不是当前组件)或者 resetShapeFlag 将标志为从 KeepAlive 相关 shapeFlag 状态重置为 STATEFUL_COMPONENT 状态(如果该缓存是当前组件,但是被exclude了),当然 unmount 函数内包含 resetShapeFlag 操作
3、缓存策略
KeepAlive 组件的缓存策略是 LRU(last recently used)缓存策略
核心思想在于需要把当前访问或渲染的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪。
看下面的图更加直观,图片来源一篇讲keepAlive 缓存优化的文章

4、如何添加到 vue devtools 组件树上
sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexion5、缓存的子组件 props 更新处理
当子组件有 prop 更新时是需要重新去 patch 的,所以在 activate 的时候需要重新执行 patch 进行子组件更新
sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
Propriétés du composant KeepAlive🎜🎜🎜sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexionConfiguration du composant KeepAlive Logique et logique de rendu (focus)🎜 🎜🎜sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexionMontez le moteur de rendu sur le composant KeepAlive lors du montage sur ctx 🎜🎜🎜🎜 dans le Le composant KeepAlive obtiendra certaines méthodes du moteur de rendu sur sharedContext telles que move, createElement, etc. 🎜sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionLe sous-composant exécute une logique de destruction et de rendu spécifique🎜🎜🎜🎜Tout d'abord, comme vous pouvez le voir ci-dessus, lors du 🎜rendu du composant KeepAlive, le drapeau shapeFlag correspondant sera ajouté au vnode du sous-composant🎜🎜🎜 Par exemple , l'indicateur COMPONENT_KEPT_ALIVE
indique au moteur de rendu lorsque le composant est monté qu'il ne nécessite pas de montage mais nécessite un traitement spécial🎜rrreee🎜De même, l'indicateur COMPONENT_SHOULD_KEEP_ALIVE
est également utilisé pour indiquer au composant lorsqu'il est désinstallé. Le moteur de rendu n'a pas besoin d'être démonté mais nécessite un traitement spécial. 🎜rrreeeComment monter activé
et désactivé</ code> Cycle de vie (vous n'avez pas besoin de vous concentrer sur le cycle de vie) 🎜🎜🎜🎜Tout d'abord, ces deux cycles de vie sont déclarés de manière unique dans le composant KeepAlive et sont directement exportés et utilisés. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function onActivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 activated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)
}
export function onDeactivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 deactivated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>然后因为这两个生命周期会注册在 setup 里面,所以只要执行 setup 就会将两个生命周期的回调函数注册到当前的 instance 实例上</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// renderer.ts
// mount 函数逻辑
const mountComponent = (initialVNode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
// ...
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
// 执行 setup
setupComponent(instance)
}
// setupcomponent 处理 setup 函数值
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
// ...
const isStateful = isStatefulComponent(instance)
// ...
const setupResult = isStateful
// setupStatefulComponent 函数主要功能是设置当前的 instance
? setupStatefulComponent(instance, isSSR)
: undefined
// ...
}
function setupStatefulComponent(
instance: ComponentInternalInstance
){
if (setup) {
//设置当前实例
setCurrentInstance(instance)
// 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
// currentInstance = null;
unsetCurrentInstance()
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>最后在执行<code>sharedContext.activate
和sharedContext.deactivate
的时候将注册在实例上的回调函数取出来直接执行就OK了,执行时机在 postRender 之后sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexion
以下是关于上述demo如何实现的简化流程图

需要注意的知识点
1、什么时候缓存
KeepAlive 组件的onMounted
和onUpdated
生命周期时进行缓存
2、什么时候取消缓存
缓存数量超过设置的 max 时
- 监听 include 和 exclude 修改的时候,会读取缓存中的知进行判断是否需要清除缓存
修剪缓存的时候也要 unmount(如果该缓存不是当前组件)或者 resetShapeFlag 将标志为从 KeepAlive 相关 shapeFlag 状态重置为 STATEFUL_COMPONENT 状态(如果该缓存是当前组件,但是被exclude了),当然 unmount 函数内包含 resetShapeFlag 操作
3、缓存策略
KeepAlive 组件的缓存策略是 LRU(last recently used)缓存策略
核心思想在于需要把当前访问或渲染的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪。
看下面的图更加直观,图片来源一篇讲keepAlive 缓存优化的文章

4、如何添加到 vue devtools 组件树上
sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexion5、缓存的子组件 props 更新处理
当子组件有 prop 更新时是需要重新去 patch 的,所以在 activate 的时候需要重新执行 patch 进行子组件更新
sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
sharedContext.activate = (vnode, container, anchor) => { // KeepAlive 下组件激活时执行的 move 逻辑 move(vnode, container, anchor, 0 /* ENTER */) // 把回调推入到 postFlush 的异步任务队列中去执行 queuePostRenderEffect(() => { if (instance.a) { // a是 activated 钩子的简称 invokeArrayFns(instance.a) } }) } sharedContext.activate = (vnode, container, anchor) => { // KeepAlive 下组件失活时执行的 move 逻辑 move(vnode, container, anchor, 0 /* ENTER */) queuePostRenderEffect(() => { if (instance.da) { // da是 deactivated 钩子的简称 invokeArrayFns(instance.da) } }) } export const enum LifecycleHooks { // ... 其他生命周期声明 DEACTIVATED = 'da', ACTIVATED = 'a', } export interface ComponentInternalInstance { // ... 其他生命周期 [LifecycleHooks.ACTIVATED]: Function[] [LifecycleHooks.DEACTIVATED]: Function[] }
Configuration du composant KeepAlive Logique et logique de rendu (focus)🎜 🎜🎜sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexionMontez le moteur de rendu sur le composant KeepAlive lors du montage sur ctx 🎜🎜🎜🎜 dans le Le composant KeepAlive obtiendra certaines méthodes du moteur de rendu sur sharedContext telles que move, createElement, etc. 🎜sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionLe sous-composant exécute une logique de destruction et de rendu spécifique🎜🎜🎜🎜Tout d'abord, comme vous pouvez le voir ci-dessus, lors du 🎜rendu du composant KeepAlive, le drapeau shapeFlag correspondant sera ajouté au vnode du sous-composant🎜🎜🎜 Par exemple , l'indicateur COMPONENT_KEPT_ALIVE
indique au moteur de rendu lorsque le composant est monté qu'il ne nécessite pas de montage mais nécessite un traitement spécial🎜rrreee🎜De même, l'indicateur COMPONENT_SHOULD_KEEP_ALIVE
est également utilisé pour indiquer au composant lorsqu'il est désinstallé. Le moteur de rendu n'a pas besoin d'être démonté mais nécessite un traitement spécial. 🎜rrreeeComment monter activé
et désactivé</ code> Cycle de vie (vous n'avez pas besoin de vous concentrer sur le cycle de vie) 🎜🎜🎜🎜Tout d'abord, ces deux cycles de vie sont déclarés de manière unique dans le composant KeepAlive et sont directement exportés et utilisés. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function onActivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 activated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)
}
export function onDeactivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 deactivated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>然后因为这两个生命周期会注册在 setup 里面,所以只要执行 setup 就会将两个生命周期的回调函数注册到当前的 instance 实例上</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// renderer.ts
// mount 函数逻辑
const mountComponent = (initialVNode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
// ...
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
// 执行 setup
setupComponent(instance)
}
// setupcomponent 处理 setup 函数值
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
// ...
const isStateful = isStatefulComponent(instance)
// ...
const setupResult = isStateful
// setupStatefulComponent 函数主要功能是设置当前的 instance
? setupStatefulComponent(instance, isSSR)
: undefined
// ...
}
function setupStatefulComponent(
instance: ComponentInternalInstance
){
if (setup) {
//设置当前实例
setCurrentInstance(instance)
// 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
// currentInstance = null;
unsetCurrentInstance()
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>最后在执行<code>sharedContext.activate
和sharedContext.deactivate
的时候将注册在实例上的回调函数取出来直接执行就OK了,执行时机在 postRender 之后sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexion
以下是关于上述demo如何实现的简化流程图

需要注意的知识点
1、什么时候缓存
KeepAlive 组件的onMounted
和onUpdated
生命周期时进行缓存
2、什么时候取消缓存
缓存数量超过设置的 max 时
- 监听 include 和 exclude 修改的时候,会读取缓存中的知进行判断是否需要清除缓存
修剪缓存的时候也要 unmount(如果该缓存不是当前组件)或者 resetShapeFlag 将标志为从 KeepAlive 相关 shapeFlag 状态重置为 STATEFUL_COMPONENT 状态(如果该缓存是当前组件,但是被exclude了),当然 unmount 函数内包含 resetShapeFlag 操作
3、缓存策略
KeepAlive 组件的缓存策略是 LRU(last recently used)缓存策略
核心思想在于需要把当前访问或渲染的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪。
看下面的图更加直观,图片来源一篇讲keepAlive 缓存优化的文章

4、如何添加到 vue devtools 组件树上
sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexion5、缓存的子组件 props 更新处理
当子组件有 prop 更新时是需要重新去 patch 的,所以在 activate 的时候需要重新执行 patch 进行子组件更新
sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
sharedContext.activate = (vnode, container, anchor) => { // instance 是子组件实例 const instance = vnode.component! // ... // dev环境下设置, 自己模拟写的 devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance) // 官方添加 if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { // Update components tree devtoolsComponentAdded(instance) } } // 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Montez le moteur de rendu sur le composant KeepAlive lors du montage sur ctx 🎜🎜🎜🎜 dans le Le composant KeepAlive obtiendra certaines méthodes du moteur de rendu sur sharedContext telles que move, createElement, etc. 🎜sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionLe sous-composant exécute une logique de destruction et de rendu spécifique🎜🎜🎜🎜Tout d'abord, comme vous pouvez le voir ci-dessus, lors du 🎜rendu du composant KeepAlive, le drapeau shapeFlag correspondant sera ajouté au vnode du sous-composant🎜🎜🎜 Par exemple , l'indicateur COMPONENT_KEPT_ALIVE
indique au moteur de rendu lorsque le composant est monté qu'il ne nécessite pas de montage mais nécessite un traitement spécial🎜rrreee🎜De même, l'indicateur COMPONENT_SHOULD_KEEP_ALIVE
est également utilisé pour indiquer au composant lorsqu'il est désinstallé. Le moteur de rendu n'a pas besoin d'être démonté mais nécessite un traitement spécial. 🎜rrreeeComment monter activé
et désactivé</ code> Cycle de vie (vous n'avez pas besoin de vous concentrer sur le cycle de vie) 🎜🎜🎜🎜Tout d'abord, ces deux cycles de vie sont déclarés de manière unique dans le composant KeepAlive et sont directement exportés et utilisés. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function onActivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 activated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)
}
export function onDeactivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 deactivated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>然后因为这两个生命周期会注册在 setup 里面,所以只要执行 setup 就会将两个生命周期的回调函数注册到当前的 instance 实例上</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// renderer.ts
// mount 函数逻辑
const mountComponent = (initialVNode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
// ...
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
// 执行 setup
setupComponent(instance)
}
// setupcomponent 处理 setup 函数值
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
// ...
const isStateful = isStatefulComponent(instance)
// ...
const setupResult = isStateful
// setupStatefulComponent 函数主要功能是设置当前的 instance
? setupStatefulComponent(instance, isSSR)
: undefined
// ...
}
function setupStatefulComponent(
instance: ComponentInternalInstance
){
if (setup) {
//设置当前实例
setCurrentInstance(instance)
// 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
// currentInstance = null;
unsetCurrentInstance()
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>最后在执行<code>sharedContext.activate
和sharedContext.deactivate
的时候将注册在实例上的回调函数取出来直接执行就OK了,执行时机在 postRender 之后sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexion
以下是关于上述demo如何实现的简化流程图

需要注意的知识点
1、什么时候缓存
KeepAlive 组件的onMounted
和onUpdated
生命周期时进行缓存
2、什么时候取消缓存
缓存数量超过设置的 max 时
- 监听 include 和 exclude 修改的时候,会读取缓存中的知进行判断是否需要清除缓存
修剪缓存的时候也要 unmount(如果该缓存不是当前组件)或者 resetShapeFlag 将标志为从 KeepAlive 相关 shapeFlag 状态重置为 STATEFUL_COMPONENT 状态(如果该缓存是当前组件,但是被exclude了),当然 unmount 函数内包含 resetShapeFlag 操作
3、缓存策略
KeepAlive 组件的缓存策略是 LRU(last recently used)缓存策略
核心思想在于需要把当前访问或渲染的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪。
看下面的图更加直观,图片来源一篇讲keepAlive 缓存优化的文章

4、如何添加到 vue devtools 组件树上
sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexion5、缓存的子组件 props 更新处理
当子组件有 prop 更新时是需要重新去 patch 的,所以在 activate 的时候需要重新执行 patch 进行子组件更新
sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
sharedContext.activate = (vnode, container, anchor) => { // ... // props 改变需要重新 patch(update) patch( instance.vnode, vnode, container, anchor, instance, parentSuspense, isSVG, vnode.slotScopeIds, optimized ) }
Le sous-composant exécute une logique de destruction et de rendu spécifique🎜🎜🎜🎜Tout d'abord, comme vous pouvez le voir ci-dessus, lors du 🎜rendu du composant KeepAlive, le drapeau shapeFlag correspondant sera ajouté au vnode du sous-composant🎜🎜🎜 Par exemple , l'indicateur COMPONENT_KEPT_ALIVE
indique au moteur de rendu lorsque le composant est monté qu'il ne nécessite pas de montage mais nécessite un traitement spécial🎜rrreee🎜De même, l'indicateur COMPONENT_SHOULD_KEEP_ALIVE
est également utilisé pour indiquer au composant lorsqu'il est désinstallé. Le moteur de rendu n'a pas besoin d'être démonté mais nécessite un traitement spécial. 🎜rrreeeComment monter activé
et désactivé</ code> Cycle de vie (vous n'avez pas besoin de vous concentrer sur le cycle de vie) 🎜🎜🎜🎜Tout d'abord, ces deux cycles de vie sont déclarés de manière unique dans le composant KeepAlive et sont directement exportés et utilisés. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function onActivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 activated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)
}
export function onDeactivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 deactivated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>然后因为这两个生命周期会注册在 setup 里面,所以只要执行 setup 就会将两个生命周期的回调函数注册到当前的 instance 实例上</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// renderer.ts
// mount 函数逻辑
const mountComponent = (initialVNode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
// ...
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
// 执行 setup
setupComponent(instance)
}
// setupcomponent 处理 setup 函数值
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
// ...
const isStateful = isStatefulComponent(instance)
// ...
const setupResult = isStateful
// setupStatefulComponent 函数主要功能是设置当前的 instance
? setupStatefulComponent(instance, isSSR)
: undefined
// ...
}
function setupStatefulComponent(
instance: ComponentInternalInstance
){
if (setup) {
//设置当前实例
setCurrentInstance(instance)
// 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
// currentInstance = null;
unsetCurrentInstance()
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>最后在执行<code>sharedContext.activate
和sharedContext.deactivate
的时候将注册在实例上的回调函数取出来直接执行就OK了,执行时机在 postRender 之后sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexion
以下是关于上述demo如何实现的简化流程图

需要注意的知识点
1、什么时候缓存
KeepAlive 组件的onMounted
和onUpdated
生命周期时进行缓存
2、什么时候取消缓存
缓存数量超过设置的 max 时
- 监听 include 和 exclude 修改的时候,会读取缓存中的知进行判断是否需要清除缓存
修剪缓存的时候也要 unmount(如果该缓存不是当前组件)或者 resetShapeFlag 将标志为从 KeepAlive 相关 shapeFlag 状态重置为 STATEFUL_COMPONENT 状态(如果该缓存是当前组件,但是被exclude了),当然 unmount 函数内包含 resetShapeFlag 操作
3、缓存策略
KeepAlive 组件的缓存策略是 LRU(last recently used)缓存策略
核心思想在于需要把当前访问或渲染的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪。
看下面的图更加直观,图片来源一篇讲keepAlive 缓存优化的文章

4、如何添加到 vue devtools 组件树上
sharedContext.activate = (vnode, container, anchor) => {
// instance 是子组件实例
const instance = vnode.component!
// ...
// dev环境下设置, 自己模拟写的
devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance)
// 官方添加
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// Update components tree
devtoolsComponentAdded(instance)
}
}
// 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
Copier après la connexionCopier après la connexion5、缓存的子组件 props 更新处理
当子组件有 prop 更新时是需要重新去 patch 的,所以在 activate 的时候需要重新执行 patch 进行子组件更新
sharedContext.activate = (vnode, container, anchor) => {
// ...
// props 改变需要重新 patch(update)
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
vnode.slotScopeIds,
optimized
)
}
Copier après la connexionCopier après la connexionCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
Comment monter activé
et désactivé</ code> Cycle de vie (vous n'avez pas besoin de vous concentrer sur le cycle de vie) 🎜🎜🎜🎜Tout d'abord, ces deux cycles de vie sont déclarés de manière unique dans le composant KeepAlive et sont directement exportés et utilisés. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function onActivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 activated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)
}
export function onDeactivated(
hook: Function,
target?: ComponentInternalInstance | null
) {
// 注册 deactivated 的回调函数到当前的 instance 的钩子函数上
registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>然后因为这两个生命周期会注册在 setup 里面,所以只要执行 setup 就会将两个生命周期的回调函数注册到当前的 instance 实例上</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// renderer.ts
// mount 函数逻辑
const mountComponent = (initialVNode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
// ...
const instance: ComponentInternalInstance =
compatMountInstance ||
(initialVNode.component = createComponentInstance(
initialVNode,
parentComponent,
parentSuspense
))
// 执行 setup
setupComponent(instance)
}
// setupcomponent 处理 setup 函数值
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false
) {
// ...
const isStateful = isStatefulComponent(instance)
// ...
const setupResult = isStateful
// setupStatefulComponent 函数主要功能是设置当前的 instance
? setupStatefulComponent(instance, isSSR)
: undefined
// ...
}
function setupStatefulComponent(
instance: ComponentInternalInstance
){
if (setup) {
//设置当前实例
setCurrentInstance(instance)
// 执行组件内 setup 函数,执行 onActivated 钩子函数进行回调函数收集
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
)
// currentInstance = null;
unsetCurrentInstance()
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><p>最后在执行<code>sharedContext.activate
和sharedContext.deactivate
的时候将注册在实例上的回调函数取出来直接执行就OK了,执行时机在 postRender 之后sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件激活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
// 把回调推入到 postFlush 的异步任务队列中去执行
queuePostRenderEffect(() => {
if (instance.a) {
// a是 activated 钩子的简称
invokeArrayFns(instance.a)
}
})
}
sharedContext.activate = (vnode, container, anchor) => {
// KeepAlive 下组件失活时执行的 move 逻辑
move(vnode, container, anchor, 0 /* ENTER */)
queuePostRenderEffect(() => {
if (instance.da) {
// da是 deactivated 钩子的简称
invokeArrayFns(instance.da)
}
})
}
export const enum LifecycleHooks {
// ... 其他生命周期声明
DEACTIVATED = 'da',
ACTIVATED = 'a',
}
export interface ComponentInternalInstance {
// ... 其他生命周期
[LifecycleHooks.ACTIVATED]: Function[]
[LifecycleHooks.DEACTIVATED]: Function[]
}
Copier après la connexionCopier après la connexion
sharedContext.activate = (vnode, container, anchor) => { // KeepAlive 下组件激活时执行的 move 逻辑 move(vnode, container, anchor, 0 /* ENTER */) // 把回调推入到 postFlush 的异步任务队列中去执行 queuePostRenderEffect(() => { if (instance.a) { // a是 activated 钩子的简称 invokeArrayFns(instance.a) } }) } sharedContext.activate = (vnode, container, anchor) => { // KeepAlive 下组件失活时执行的 move 逻辑 move(vnode, container, anchor, 0 /* ENTER */) queuePostRenderEffect(() => { if (instance.da) { // da是 deactivated 钩子的简称 invokeArrayFns(instance.da) } }) } export const enum LifecycleHooks { // ... 其他生命周期声明 DEACTIVATED = 'da', ACTIVATED = 'a', } export interface ComponentInternalInstance { // ... 其他生命周期 [LifecycleHooks.ACTIVATED]: Function[] [LifecycleHooks.DEACTIVATED]: Function[] }
以下是关于上述demo如何实现的简化流程图
需要注意的知识点
1、什么时候缓存
KeepAlive 组件的onMounted
和onUpdated
生命周期时进行缓存
2、什么时候取消缓存
缓存数量超过设置的 max 时
- 监听 include 和 exclude 修改的时候,会读取缓存中的知进行判断是否需要清除缓存
修剪缓存的时候也要 unmount(如果该缓存不是当前组件)或者 resetShapeFlag 将标志为从 KeepAlive 相关 shapeFlag 状态重置为 STATEFUL_COMPONENT 状态(如果该缓存是当前组件,但是被exclude了),当然 unmount 函数内包含 resetShapeFlag 操作
3、缓存策略
KeepAlive 组件的缓存策略是 LRU(last recently used)缓存策略
核心思想在于需要把当前访问或渲染的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪。
看下面的图更加直观,图片来源一篇讲keepAlive 缓存优化的文章
4、如何添加到 vue devtools 组件树上
sharedContext.activate = (vnode, container, anchor) => { // instance 是子组件实例 const instance = vnode.component! // ... // dev环境下设置, 自己模拟写的 devtools.emit('component:added', instance.appContext.app, instance.uid, instance.parent ? instance.parent.uid: undefined, instance) // 官方添加 if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { // Update components tree devtoolsComponentAdded(instance) } } // 同理 sharedContext.deactivates 上也要添加,不然不会显示在组件树上
5、缓存的子组件 props 更新处理
当子组件有 prop 更新时是需要重新去 patch 的,所以在 activate 的时候需要重新执行 patch 进行子组件更新
sharedContext.activate = (vnode, container, anchor) => { // ... // props 改变需要重新 patch(update) patch( instance.vnode, vnode, container, anchor, instance, parentSuspense, isSVG, vnode.slotScopeIds, optimized ) }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

PHP et Vue : une combinaison parfaite d'outils de développement front-end À l'ère actuelle de développement rapide d'Internet, le développement front-end est devenu de plus en plus important. Alors que les utilisateurs ont des exigences de plus en plus élevées en matière d’expérience des sites Web et des applications, les développeurs front-end doivent utiliser des outils plus efficaces et plus flexibles pour créer des interfaces réactives et interactives. En tant que deux technologies importantes dans le domaine du développement front-end, PHP et Vue.js peuvent être considérés comme une arme parfaite lorsqu'ils sont associés. Cet article explorera la combinaison de PHP et Vue, ainsi que des exemples de code détaillés pour aider les lecteurs à mieux comprendre et appliquer ces deux éléments.

Lors des entretiens de développement front-end, les questions courantes couvrent un large éventail de sujets, notamment les bases HTML/CSS, les bases JavaScript, les frameworks et les bibliothèques, l'expérience du projet, les algorithmes et les structures de données, l'optimisation des performances, les requêtes inter-domaines, l'ingénierie front-end, les modèles de conception et les nouvelles technologies et tendances. Les questions de l'intervieweur sont conçues pour évaluer les compétences techniques du candidat, son expérience en matière de projet et sa compréhension des tendances du secteur. Par conséquent, les candidats doivent être parfaitement préparés dans ces domaines pour démontrer leurs capacités et leur expertise.

Django est un framework d'application Web écrit en Python qui met l'accent sur un développement rapide et des méthodes propres. Bien que Django soit un framework Web, pour répondre à la question de savoir si Django est un front-end ou un back-end, vous devez avoir une compréhension approfondie des concepts de front-end et de back-end. Le front-end fait référence à l'interface avec laquelle les utilisateurs interagissent directement, et le back-end fait référence aux programmes côté serveur. Ils interagissent avec les données via le protocole HTTP. Lorsque le front-end et le back-end sont séparés, les programmes front-end et back-end peuvent être développés indépendamment pour mettre en œuvre respectivement la logique métier et les effets interactifs, ainsi que l'échange de données.

En tant que développeur C#, notre travail de développement comprend généralement le développement front-end et back-end. À mesure que la technologie se développe et que la complexité des projets augmente, le développement collaboratif du front-end et du back-end est devenu de plus en plus important et complexe. Cet article partagera quelques techniques de développement collaboratif front-end et back-end pour aider les développeurs C# à effectuer leur travail de développement plus efficacement. Après avoir déterminé les spécifications de l’interface, le développement collaboratif du front-end et du back-end est indissociable de l’interaction des interfaces API. Pour assurer le bon déroulement du développement collaboratif front-end et back-end, le plus important est de définir de bonnes spécifications d’interface. La spécification de l'interface implique le nom de l'interface

En tant que langage de programmation rapide et efficace, le langage Go est très populaire dans le domaine du développement back-end. Cependant, peu de gens associent le langage Go au développement front-end. En fait, l’utilisation du langage Go pour le développement front-end peut non seulement améliorer l’efficacité, mais également ouvrir de nouveaux horizons aux développeurs. Cet article explorera la possibilité d'utiliser le langage Go pour le développement front-end et fournira des exemples de code spécifiques pour aider les lecteurs à mieux comprendre ce domaine. Dans le développement front-end traditionnel, JavaScript, HTML et CSS sont souvent utilisés pour créer des interfaces utilisateur.

Les méthodes de mise en œuvre de la messagerie instantanée incluent WebSocket, Long Polling, Server-Sent Events, WebRTC, etc. Introduction détaillée : 1. WebSocket, qui peut établir une connexion persistante entre le client et le serveur pour obtenir une communication bidirectionnelle en temps réel. Le frontal peut utiliser l'API WebSocket pour créer une connexion WebSocket et obtenir une messagerie instantanée en envoyant et en recevant. messages 2. Long Polling, une technologie qui simule la communication en temps réel, etc.

Combinaison de Golang et de la technologie front-end : pour explorer le rôle de Golang dans le domaine front-end, des exemples de code spécifiques sont nécessaires. Avec le développement rapide d'Internet et des applications mobiles, la technologie front-end est devenue de plus en plus importante. Dans ce domaine, Golang, en tant que puissant langage de programmation back-end, peut également jouer un rôle important. Cet article explorera comment Golang est combiné avec la technologie front-end et démontrera son potentiel dans le domaine front-end à travers des exemples de code spécifiques. Le rôle de Golang dans le domaine front-end est celui d'un outil efficace, concis et facile à apprendre.

Django : Un framework magique capable de gérer à la fois le développement front-end et back-end ! Django est un framework d'application Web efficace et évolutif. Il est capable de prendre en charge plusieurs modèles de développement Web, notamment MVC et MTV, et peut facilement développer des applications Web de haute qualité. Django prend non seulement en charge le développement back-end, mais peut également créer rapidement des interfaces frontales et obtenir un affichage de vue flexible via un langage de modèle. Django combine le développement front-end et le développement back-end dans une intégration transparente, afin que les développeurs n'aient pas à se spécialiser dans l'apprentissage.
