当前位置:   article > 正文

Angular React Vue 比较 – 组件篇之内置组件

Angular React Vue 比较 – 组件篇之内置组件

本篇文章是组件篇的最后一篇,我们将探讨一下三大框架本身的内置组件。

Angular 的内置组件

在 Angular 中并没有内置组件,它只有一些内置指令。

虽然 Angular 官方把指令也称为一种特殊的组件,不过我们还是把指令在另外的篇章中讨论,就不在组件篇里讨论了。

React 的内置组件

React 提供了一些内置的组件,我们可以在 JSX 中使用它们。

组件描述
<Fragment><Fragment> 通常使用 <>…</> 代替,它们都允许你在不添加额外节点的情况下将子元素组合。
<Profiler><Profiler> 允许你编程式测量 React 树的渲染性能。
<StrictMode><StrictMode> 帮助你在开发过程中尽早地发现组件中的常见错误。
<Suspense><Suspense> 允许在子组件完成加载前展示后备方案。

<Fragment>

当我们需要单个元素时,我们可以使用 <Fragment> 将其他元素组合起来,使用 <Fragment> 组合后的元素不会对 DOM 产生影响,就像元素没有被组合一样。在大多数情况下,<Fragment></Fragment> 可以简写为空的 JSX 元素 <></>

  1. <>
  2. <OneChild />
  3. <AnotherChild />
  4. </>

<Fragment> 还可以有一个可选参数 key ,如果我们要传递 key 给一个 <Fragment>,不能使用 <>...</>,必须从 'react' 中导入 Fragment 且表示为<Fragment key={yourKey}>...</Fragment>

  1. import { Fragment } from 'react';
  2. function Blog() {
  3. return posts.map(post =>
  4. <Fragment key={post.id}>
  5. <PostTitle title={post.title} />
  6. <PostBody body={post.body} />
  7. </Fragment>
  8. );
  9. }

<Profiler>

我们使用 <Profiler> 包裹组件树,以测量其渲染性能。进行性能分析会增加一些额外的开销,因此 在默认情况下,它在生产环境中是被禁用的

  1. <Profiler id="App" onRender={onRender}>
  2. <App />
  3. </Profiler>

参数:

  • id:字符串,用于标识正在测量的 UI 部分。
  • onRender:onRender 回调函数,当包裹的组件树更新时,React 都会调用它。它接收有关渲染内容和所花费时间的信息。

<StrictMode>

我们可以使用 StrictMode 来启用组件树内部的额外开发行为和警告。

  1. import { StrictMode } from 'react';
  2. import { createRoot } from 'react-dom/client';
  3. const root = createRoot(document.getElementById('root'));
  4. root.render(
  5. <StrictMode>
  6. <App />
  7. </StrictMode>
  8. );

严格模式启用了以下仅在开发环境下有效的行为:

  • 组件将 重新渲染一次,以查找由于非纯渲染而引起的错误。
  • 组件将 重新运行 Effect一次,以查找由于缺少 Effect 清理而引起的错误。
  • 组件将被 检查是否使用了已弃用的 API

<Suspense>

<Suspense> 允许在子组件完成加载前展示后备方案。

  1. <Suspense fallback={<Loading />}>
  2. <SomeComponent />
  3. </Suspense>

参数:

  • children:真正的 UI 渲染内容。如果 children 在渲染中被挂起,Suspense 边界将会渲染 fallback
  • fallback:真正的 UI 未渲染完成时代替其渲染的备用 UI,它可以是任何有效的 React 节点。后备方案通常是一个轻量的占位符,例如表示加载中的图标或者骨架屏。当 children 被挂起时,Suspense 将自动切换至渲染 fallback;当数据准备好时,又会自动切换至渲染 children。如果 fallback 在渲染中被挂起,那么将自动激活最近的 Suspense 边界。

Vue 的内置组件

Vue 提供了一些内置的组件,我们可以在任意别的组件中使用,无需注册。

组件描述
<Transition><Transition>可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。
<TransitionGroup><TransitionGroup> 是一个内置组件,用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。
<KeepAlive><KeepAlive> 的功能是在多个组件间动态切换时缓存被移除的组件实例。
<Teleport><Teleport> 可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。
<Suspense>实验<Suspense> 用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。

<Transition>

<Transition> 可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发:

  • 由 v-if 所触发的切换
  • 由 v-show 所触发的切换
  • 由特殊元素 <component> 切换的动态组件
  • 改变特殊的 key 属性

<Transition> 可以基于 css3 的动画或第三方的 JS 动画库来实现动画。

基于 css 执行动画的示例代码

  1. <script setup>
  2. import { ref } from 'vue'
  3. const show = ref(true)
  4. </script>
  5. <template>
  6. <button @click="show = !show">Toggle Slide + Fade</button>
  7. <Transition name="slide-fade">
  8. <p v-if="show">hello</p>
  9. </Transition>
  10. </template>
  11. <style>
  12. .slide-fade-enter-active {
  13. transition: all 0.3s ease-out;
  14. }
  15. .slide-fade-leave-active {
  16. transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
  17. }
  18. .slide-fade-enter-from,
  19. .slide-fade-leave-to {
  20. transform: translateX(20px);
  21. opacity: 0;
  22. }
  23. </style>

基于 GreenSock 库执行动画的示例代码

  1. <script setup>
  2. import { ref } from 'vue'
  3. import gsap from 'gsap'
  4. const show = ref(true)
  5. function onBeforeEnter(el) {
  6. gsap.set(el, {
  7. scaleX: 0.25,
  8. scaleY: 0.25,
  9. opacity: 1
  10. })
  11. }
  12. function onEnter(el, done) {
  13. gsap.to(el, {
  14. duration: 1,
  15. scaleX: 1,
  16. scaleY: 1,
  17. opacity: 1,
  18. ease: 'elastic.inOut(2.5, 1)',
  19. onComplete: done
  20. })
  21. }
  22. function onLeave(el, done) {
  23. gsap.to(el, {
  24. duration: 0.7,
  25. scaleX: 1,
  26. scaleY: 1,
  27. x: 300,
  28. ease: 'elastic.inOut(2.5, 1)'
  29. })
  30. gsap.to(el, {
  31. duration: 0.2,
  32. delay: 0.5,
  33. opacity: 0,
  34. onComplete: done
  35. })
  36. }
  37. </script>
  38. <template>
  39. <button @click="show = !show">Toggle</button>
  40. <Transition
  41. @before-enter="onBeforeEnter"
  42. @enter="onEnter"
  43. @leave="onLeave"
  44. :css="false"
  45. >
  46. <div class="gsap-box" v-if="show"></div>
  47. </Transition>
  48. </template>
  49. <style>
  50. .gsap-box {
  51. background: #42b883;
  52. margin-top: 20px;
  53. width: 30px;
  54. height: 30px;
  55. border-radius: 50%;
  56. }
  57. </style>

<TransitionGroup>

<TransitionGroup> 是一个内置组件,用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。

<TransitionGroup> 支持和 <Transition> 基本相同的 props、CSS 过渡 class 和 JavaScript 钩子监听器,但有以下几点区别:

  • 默认情况下,它不会渲染一个容器元素。但你可以通过传入 tag prop 来指定一个元素作为容器元素来渲染。
  • 过渡模式在这里不可用,因为我们不再是在互斥的元素之间进行切换。
  • 列表中的每个元素都必须有一个独一无二的 key attribute。
  • CSS 过渡 class 会被应用在列表内的元素上,而不是容器元素上。

基于 GreenSock library 的动画示例

  1. <script setup>
  2. import { ref, computed } from 'vue'
  3. import gsap from 'gsap'
  4. const list = [
  5. { msg: 'Bruce Lee' },
  6. { msg: 'Jackie Chan' },
  7. { msg: 'Chuck Norris' },
  8. { msg: 'Jet Li' },
  9. { msg: 'Kung Fury' }
  10. ]
  11. const query = ref('')
  12. const computedList = computed(() => {
  13. return list.filter((item) => item.msg.toLowerCase().includes(query.value))
  14. })
  15. function onBeforeEnter(el) {
  16. el.style.opacity = 0
  17. el.style.height = 0
  18. }
  19. function onEnter(el, done) {
  20. gsap.to(el, {
  21. opacity: 1,
  22. height: '1.6em',
  23. delay: el.dataset.index * 0.15,
  24. onComplete: done
  25. })
  26. }
  27. function onLeave(el, done) {
  28. gsap.to(el, {
  29. opacity: 0,
  30. height: 0,
  31. delay: el.dataset.index * 0.15,
  32. onComplete: done
  33. })
  34. }
  35. </script>
  36. <template>
  37. <input v-model="query" />
  38. <TransitionGroup
  39. tag="ul"
  40. :css="false"
  41. @before-enter="onBeforeEnter"
  42. @enter="onEnter"
  43. @leave="onLeave"
  44. >
  45. <li
  46. v-for="(item, index) in computedList"
  47. :key="item.msg"
  48. :data-index="index"
  49. >
  50. {{ item.msg }}
  51. </li>
  52. </TransitionGroup>
  53. </template>

<KeepAlive>

<KeepAlive> 的功能是在多个组件间动态切换时缓存被移除的组件实例。

我们可以用 <KeepAlive> 内置组件将这些动态组件包装起来:

  1. <!-- 非活跃的组件将会被缓存! -->
  2. <KeepAlive>
  3. <component :is="activeComponent" />
  4. </KeepAlive>

<Teleport>

<Teleport> 可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。

有时我们可能会遇到这样的场景:一个组件模板的一部分在逻辑上从属于该组件,但从整个应用视图的角度来看,它在 DOM 中应该被渲染在整个 Vue 应用外部的其他地方。

这类场景最常见的例子就是全屏的模态框。理想情况下,我们希望触发模态框的按钮和模态框本身是在同一个组件中,因为它们都与组件的开关状态有关。但这意味着该模态框将与按钮一起渲染在应用 DOM 结构里很深的地方。这会导致该模态框的 CSS 布局代码很难写。

模态框的示例代码

  1. <script setup>
  2. import { ref } from 'vue'
  3. const open = ref(false)
  4. </script>
  5. <template>
  6. <button @click="open = true">Open Modal</button>
  7. <Teleport to="body">
  8. <div v-if="open" class="modal">
  9. <p>Hello from the modal!</p>
  10. <button @click="open = false">Close</button>
  11. </div>
  12. </Teleport>
  13. </template>
  14. <style scoped>
  15. .modal {
  16. position: fixed;
  17. z-index: 999;
  18. top: 20%;
  19. left: 50%;
  20. width: 300px;
  21. margin-left: -150px;
  22. }
  23. </style>

<Suspense>

<Suspense> 用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。

  1. <Suspense>
  2. <!-- 具有深层异步依赖的组件 -->
  3. <Dashboard />
  4. <!-- 在 #fallback 插槽中显示 “正在加载中” -->
  5. <template #fallback>
  6. Loading...
  7. </template>
  8. </Suspense>

<Suspense> 组件有两个插槽:#default 和 #fallback。两个插槽都只允许一个直接子节点。在可能的时候都将显示默认槽中的节点。否则将显示后备槽中的节点。

总结

关于三大框架组件篇的比较文章到这里就结束了,在组件篇里我们对生命周期、Props、Slots、事件、动态组件、异步组件、内置组件这七个主题进行了比较。

我们抽象出来的七个主题在三大框架并不是全都存在的,我们试图以这个抽象的模型来加深对三大框架的理解,可能有些主题并不能准确表述出框架本身的意图,建议在相关主题下阅读框架本身的官方文档。

文章参考链接:

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/241511
推荐阅读
相关标签
  

闽ICP备14008679号