1.vue3.2 源码浅析:createApp、视图视图mount
2.[译] 关于 Angular 的函数函数变化检测,你需要知道的源码源码一切
3.vueVue3中使用函数调用组件内函数和创建组件超详细+源码
4.Vue原理依赖更新 - 源码版
5.解读FlaskBB源码
vue3.2 源码浅析:createApp、mount
Vue3.2 源码浅析:createApp与mount功能解析
在构建Vue3应用时,视图视图我们通常会用到createApp()和mount()这两个关键函数,函数函数它们负责初始化整个应用。源码源码网站源码搭建演示这里以vue3.2版本的视图视图源码为基础进行分析。 createApp()的函数函数核心代码揭示了其主要职责:首先,它处理初始化流程,源码源码包括3个主要步骤。视图视图这部分源码的函数函数精简版展示其功能核心。 相比之下,源码源码mount()的视图视图代码更为繁杂,但总体上负责将应用实例与DOM挂载。函数函数以下是源码源码关键部分的概览:app.mount():它首先通过normalizeContainer()获取挂载点,然后调用自身的mount()。这两个mount()功能有别,但都与组件的挂载过程密切相关。
render()函数:这个函数在mount()中创建了VDOM的根节点,与我们日常使用的Vue.render()不同,它们在初始化时承担着构建视图的任务。
patch()函数:作为diff算法的一部分,它负责在初始化阶段,通过先序遍历创建Vue实例和VNode,并将它们与DOM节点紧密关联。
mountComponent():这部分主要关注实例的创建、初始化以及数据和VNode的双向绑定。初始化流程涉及vue实例的构建,以及setupRenderEffect()的执行路径。
通过以上分析,createApp()与mount()共同构建并挂载了Vue应用,确保了组件的正确渲染和交互。深入了解这两个函数有助于我们更好地掌握Vue3.2的内部运作机制。[译] 关于 Angular 的变化检测,你需要知道的一切
关于 Angular 的变化检测,你需要知道的一切
探究内部实现和具体用例
要全面了解 Angular 的变化检测机制,查看源码是不可或缺的步骤,因为网络上相关文章少之又少。掌握全局公式源码大部分文章只涉及每个组件自身的变化检测器、不可变变量(immutable)和变化检测策略(change detection strategy)的概念,但缺乏深入剖析。本文旨在深入探讨不可变变量如何触发变化检测,以及变化监测策略对检测的影响。同时,你将能将这些知识应用到优化性能的场景中。
本文分为两部分,第一部分侧重于技术细节,包含大量源码链接。我们基于 Angular 4.0.1 版本来解释变化检测机制的工作原理。该版本与 Angular 2.4.1 版本有所差异。若想了解更多,可参考 Stack Overflow 上的相关讨论。
第二部分将展示如何运用变化检测。值得注意的是,尽管两个版本的 API 有所不同,但第二部分的内容对两个版本都适用。
核心概念:视图(view)
Angular 的教程常提到应用是一颗组件树,但在 Angular 内部,视图(view)是一种较低级的抽象概念。视图与组件之间存在直接关联,每个视图都通过 component 属性与对应的组件类关联。所有操作在视图中执行,包括属性检查和 DOM 更新。因此,从技术角度来看,更准确的说法是 Angular 应用是一颗视图树。组件可以视为视图的更高阶概念。源码中对视图有如下描述:
视图是应用 UI 的基本组成元素,由一组在创建和销毁时共同存在的最小集合构成。视图的属性可以改变,但元素结构(数量和顺序)不能改变。想要改变元素结构,只能通过 ViewContainerRef 插入、移动或移除嵌入的视图。每个视图可以包含多个视图容器。文献在哪找源码
在本文中,我们将交替使用“组件视图”和“组件”概念。
值得注意的是,网络上有关变化检测的文章和 StackOverflow 回答中的“视图”常被称作变化检测器对象(Change Detector Object)或 ChangeDetectorRef。实际上,变化检测并非独立对象,而是在视图上运行的。
每个视图通过 nodes 属性关联子视图,以便对子视图进行操作。
视图的状态
每个视图都有一个 state 属性,这是极其重要的属性,决定了是否对视图及其所有子视图执行变化检测。state 属性有多种可能的值,与本文相关的有:
如果ChecksEnabled 为 false 或视图状态为 Errored 或者 Destroyed,变化检测将跳过此视图及其所有子视图。默认情况下,所有视图均以 ChecksEnabled 作为初始值,除非使用了 ChangeDetectionStrategy.OnPush。
Angular 中有许多高级概念用于操作视图。在文章中已提及部分概念,如 ViewRef。它封装了组件视图并提供了一个名为 detectChanges 的方法,该方法会在异步事件触发时在最顶层的 ViewRef 上执行变化检测。最顶层的 ViewRef 执行变化检测后,会递归地对其子视图执行检测。
通过 ChangeDetectorRef 令牌将 viewRef 注入组件构造函数中,可以实现此操作:
从其定义可知这一点:
变化检测操作
执行变化检测的主要逻辑在 checkAndUpdateView 方法中,该方法主要针对子组件视图执行操作,并递归地调用此方法以遍历从宿主组件到所有组件的所有视图。这意味着,下一次递归中,子组件就成为了新的父组件。
执行变化检测的主要步骤如下:
有几个关键点需要注意:
首先,子组件在子视图被检测之前会触发onChanges 生命周期钩子,即使子视图的变化检测被跳过了。这一点至关重要,后续部分将展示如何利用这一点。个人blog源码htmlcss
第二,当检测视图时,更新视图的 DOM 是变化检测机制的一部分。因此,如果组件未被检测,DOM 将不会更新,模板中的组件属性发生改变时也是如此。在第一次检测之前,模板已被渲染。这里所说的更新 DOM 指的是更新插值。例如,some { { name}},在第一次检测之前,已经将 DOM 元素 span 渲染好。检测过程中,只会渲染 { { name}} 部分。
另一个有趣的是,子组件视图的状态可以在变化检测过程中改变。所有组件视图默认初始化为 ChecksEnabled。但是,使用 OnPush 策略的组件在第一次检测后不再执行变化检测(步骤第 9 步)。OnPush 文档说明,只有绑定发生变化时才会执行检测。因此,需要将 ChecksEnabled 位设置为启用检测(步骤第 2 步操作):
只有当父视图绑定发生变化,且子组件视图初始化为 ChangeDetectionStrategy.OnPush 时,才会更新状态。
最后,当前视图的变化检测负责启动子视图的变化检测(步骤第 8 步)。以下是相关的代码:
现在你知道了视图状态控制了是否对此视图及其子视图进行变化检测。那么问题来了——我们能控制这个状态吗?答案是可以,这也是本文第二部分将探讨的内容。
有些生命周期钩子在更新 DOM 前调用(步骤 3、4、5),有些在之后(步骤 9)。例如,小程序网赚源码组件结构为 A -> B -> C,它们的生命周期钩子调用和更新绑定的顺序是:
总结
假设我们有如图所示的组件树,根据前面所述,每个组件都有一个与之关联的视图。每个视图初始化为 ViewState.ChecksEnabled,这意味着 Angular 进行变化检测时,树中的每个组件都会被检测。
如果我们希望禁用 AComponent 及其子组件的变化检测,只需将 ViewState.ChecksEnabled 设置为 false。由于状态操作是低级操作,Angular 提供了许多视图的公共方法。每个组件都可以通过 ChangeDetectorRef 令牌获取关联的视图。Angular 文档定义了该类的公共接口:
接下来,我们将探讨如何使用这些接口。
detach
detach 允许我们操作状态,它可以对当前视图禁用检查:
在代码中实现如下:
这确保了接下来的变化检测中,从 AComponent 开始,左子树的所有组件都会被跳过(橙色的组件不会被检测):
需要注意的是,改变的是 AComponent 的状态,其所有子组件都不会被检测。第二点是,由于整个左子树的组件都不执行变化检测,它们模板中的 DOM 也不会更新。以下例子简要描述了这种情况:
当组件首次被检测时,span 将被渲染为“See if I change: false”。两秒后,changed 属性变为 true,但 span 中的文字不会更新。然而,如果去掉了 this.cd.detach(),就会按照预期更新。
reattach
如第一部分所述,如果 AComponent 的输入绑定 aProp 发生变化,AComponent 的 Onchanges 生命周期钩子就会被触发。这意味着一旦得知输入属性发生变化,即可启动当前组件的变化检测器来检测变化,然后在下一个周期将其分离。以下是实现此功能的代码片段:
由于reattach 只是简单地设置 ViewState.ChecksEnabled 位:
这与将 ChangeDetectionStrategy 设置为 OnPush 的效果相似:在第一次变化检测后禁用检测,当父组件绑定的属性发生变化时启用,检测完之后再次禁用。
需要注意的是,OnChanges 钩子仅在禁用检查的子树的最顶端组件触发,子树中的其他组件不会触发。然而,我们可以通过这个钩子执行自定义逻辑,然后将组件标记为可以执行一次变化检测。由于 Angular 只检测对象引用,我们在此可以检查对象的属性:
markForCheck
reattach 方法仅对当前组件启用检测,如果父组件未启用变化检测,效果有限。我们需要一个能够检测所有父组件直到根组件的方法,这个方法就是 markForCheck:
从代码中可以看出,它仅向上迭代直至根节点,使所有父组件都启用检查。
何时使用这个方法?与 ngOnChanges 一样,在使用 OnPush 策略时也会触发 ngDoCheck 生命周期钩子。再次强调,只有禁用检查的子树的最顶端组件会触发,子树中的其他组件都不会触发。但是,我们可以通过这个钩子执行一些自定义逻辑,然后将组件标记为可以执行一次变化检测。由于 Angular 只检测对象引用,我们在此可以检查对象的属性:
detectChanges
有一种方法可以对当前组件和所有子组件执行一次变化检测,这就是 detectChanges 方法。此方法会对当前组件视图执行变化检测,不管组件的状态如何。也就是说,视图仍会禁用检测,并且在接下来常规的变化检测中,不会检测此组件。例如:
尽管变化检测器引用仍保持分离,但 DOM 元素仍会随着输入绑定的变化而变化。
checkNoChanges
这是变化检测器的最后一个方法,主要作用是确保当前执行的变化检测中,没有变化发生。简单来说,它执行本文第一部分提到的列表中的第 1、7、8 步。如果发现绑定发生变化或 DOM 需要更新,会抛出异常。
还有疑问?
若对本文有任何疑问,欢迎在 Stack Overflow 上提问,并在本文评论区贴上链接。这样整个社区都能受益。感谢。
关注我以获取更多资讯
若发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。本文永久链接即为本文在 GitHub 上的 MarkDown 链接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、 iOS、 前端、 后端、 区块链、 产品、 设计、 人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、 官方微博、 知乎专栏。
vueVue3中使用函数调用组件内函数和创建组件超详细+源码
在uniapp项目中,结合vue3和typescript,你可能会遇到不想频繁在视图层引入组件的困扰。传统的组件应用方式需要每次使用时都进行应用,即使不使用也需引入。为了解决这个问题,你可能尝试通过函数调用直接创建和操作组件。
首先,你可能会查阅到使用`createApp`方法,创建组件实例并传递参数,就像父组件传递数据给子组件。例如:
然而,直接在`createApp`中调用组件方法可能并不直接有效。此时,你可以考虑转向函数式组件(h)和`render`函数。将组件的方法挂载到vue原型链上,以便在外部函数中调用。例如在`toast.ts`中:
typescript
// toast.ts
Vue.prototype.$toast = function(message) {
// 实现 toast 方法...
};
然后在项目中这样使用:
显示提示
最后,记得分享你的发现,关注个人博客和开源项目,加入技术交流群组,与他人交流学习,共同进步。如果你在过程中遇到问题,欢迎留言,大家会一起探讨解答。
Vue原理依赖更新 - 源码版
本文深入剖析Vue源码中的依赖更新机制,带你从源码层面理解这一关键概念。依赖更新是响应式系统中不可或缺的一环,它确保了数据变化时视图的及时响应。理解依赖更新,需要从依赖收集的背景出发,掌握其核心逻辑。
依赖收集是响应式系统中数据变化追踪的基础,它使得Vue能够在数据变动时,自动更新相关视图。此过程涉及基本数据类型和引用数据类型的收集,为依赖更新奠定了基础。
依赖更新的核心操作是调用`Object.defineProperty`的`set`函数。当数据值发生改变时,`set`函数被触发,从而触发依赖更新。这一步骤是依赖更新的关键,实现了数据变化与视图更新之间的联动。
依赖更新的精髓在于通知机制。这一机制通过`dep.notify`函数实现,负责遍历依赖存储器,并调用`watcher.update`方法,以此触发视图的更新。`dep`是依赖存储器的核心,存储了所有与数据变化相关的监视器(`watcher`)。
了解`dep`和`watcher`的交互是理解依赖更新的关键。`dep`负责收集依赖,而`watcher`则在数据变化时触发视图更新。当数据变化触发`dep.notify`时,`watcher.update`方法被调用,执行预设的更新函数。这个过程涉及数据的重新读取、DOM节点的生成与插入,实现了视图的即时响应。
从Vue实例创建到初始化,再到挂载页面,整个流程中`watcher`的更新函数起到了关键作用。这个函数通常包含了视图更新的具体逻辑,如调用渲染函数生成DOM节点。虽然涉及的源码较多,但核心在于重新生成DOM节点,确保页面在数据变化时能够实时更新。
依赖更新的流程简而言之,包括直接调用`watcher.update`、执行渲染函数以生成DOM节点、以及更新DOM节点以完成页面更新。这一机制确保了Vue应用在数据变化时的高效响应,使得用户体验更加流畅。
理解Vue依赖更新不仅有助于深入掌握Vue源码,还能提升开发者在实际项目中的应对能力,特别是在复杂应用中处理数据变化与视图更新的关系。通过细致分析Vue源码,可以更加清晰地认识到这一机制在实际应用中的实现细节与优化空间。
如有任何描述不当或疑问,欢迎在后台联系作者,共同探讨Vue响应式系统中的依赖更新机制。
解读FlaskBB源码
解读FlaskBB源码
FlaskBB源码解读开始。目录结构清晰,根目录包含常见依赖文件和自动测试代码,主文件夹flaskbb内则包含了核心功能。
主程序app.py中的create_app函数展示了FlaskBB的配置加载、扩展初始化与蓝本挂载。自动测试确保代码质量,模板过滤器丰富功能。
目录下四大板块(user、forum、auth、management)构建论坛核心功能,每个板块包含模型、视图、表单三部分,结构清晰。
models.py定义模块关系,如用户与主题的关联通过ORM实现,简化数据库操作。html模板、静态资源(js、css、)分别存放于templates和static文件夹。
FlaskBB源码展示了一个成熟项目结构,代码规范、可读性强。理解其结构与实现细节有助于定制与扩展论坛功能,实现真正可用的论坛产品。