vue2x,3.x之内置组件

1. component

在Vue中,内置组件component是一个动态地渲染不同组件的元素。它可以根据数据动态地选择要渲染的组件,并在渲染过程中动态地创建和销毁这些组件。

⏰ 父组件

<template>
    <h1>我是 APP 组件</h1>
    <button @click="myId = 'my_com'">首页</button>
    <button @click="myId = 'my_com2'">分类</button>
    <button @click="myId = 'my_com3'">购物车</button>
    <button @click="myId = 'my_com4'">个人页</button>

    <component :is="myId"></component>
</template>

<script>
import my_com from './components/my_com.vue'
import my_com2 from './components/my_com2.vue'
import my_com3 from './components/my_com3.vue'
import my_com4 from './components/my_com4.vue'
export default {
    data() {
        return {
            myId: 'my_com'
        }
    },
    components: {
        my_com,
        my_com2,
        my_com3,
        my_com4,
    }
}
</script>

⏰ my_com 子组件

<template>
    <h4 style="color: red;">我是首页部分</h4>
    <input type="text">
</template>

⏰ my_com2 子组件

<template>
    <h4 style="color: green">我是分类部分</h4>
    <input type="text" />
</template>

⏰ my_com3 子组件

<template>
    <h4 style="color: blue;">我是购物车部分</h4>
    <input type="text">
</template>

⏰ my_com4 子组件

<template>
    <h4 style="color: purple;">我是个人页部分</h4>
    <input type="text" />
</template>

2.keep-alive

⏰ 父组件

<template>
  <h1>我是 APP 组件</h1>
  <button @click="myId = 'my_com'">首页</button>
  <button @click="myId = 'my_com2'">分类</button>
  <button @click="myId = 'my_com3'">购物车</button>
  <button @click="myId = 'my_com4'">个人页</button>
  <!-- 
            keep-alive 内置组件
                内部可以书写多个组件,可以让内部书写的所有组件,全部具有缓存性
                也就组件切换后,对组件内部的一些操作,会被保留下来
            当前组件 还有两个属性,两个属性值是一个数组
                inclode, 内部包含具备缓存性的组件名
                exclode, 内部不包含具有缓存性的组件名

                组件名需要是 组件内部书写 name 属性
        -->
  <keep-alive :include="['my_com', 'my_com4']">
    <component :is="myId"></component>
  </keep-alive>
</template>

<script>
import my_com from "./components/my_com.vue";
import my_com2 from "./components/my_com2.vue";
import my_com3 from "./components/my_com3.vue";
import my_com4 from "./components/my_com4.vue";
export default {
  data() {
    return {
      myId: "my_com",
    };
  },
  components: {
    my_com,
    my_com2,
    my_com3,
    my_com4,
  },
};
</script>

my_com 子组件

<template>
    <h4 style="color: red">我是首页部分</h4>
    <input type="text" />
</template>

<script>
    export default {
        name: "my_com",
    };
</script>

my_com2 子组件

<template>
    <h4 style="color: green">我是分类部分</h4>
    <input type="text" />
</template>
<script>
    export default{
        name: 'my_com2'
    }
</script>
⏰ my_com3 子组件
<template>
    <h4 style="color: blue;">我是购物车部分</h4>
    <input type="text">
</template>
<script>
    export default{
        name: 'my_com3'
    }
</script>

⏰ my_com4 子组件

<template>
    <h4 style="color: purple;">我是个人页部分</h4>
    <input type="text" />
</template>
<script>
    export default{
        name: 'my_com4'
    }
</script>

3.Transition

Vue的Transition是Vue.js提供的一种动画效果管理工具,用于在元素进入或离开DOM时添加动画效果。通过Transition组件,你可以为元素的进入和离开过程分别定义动画效果,比如淡入淡出、滑动等。Transition组件可以包裹任意元素或组件,并通过设置不同的属性来控制动画的行为。

Transition组件的主要属性包括:

  • name:指定动画效果的名称,用于在CSS中定义对应的动画样式。
  • appear:指定是否在初始渲染时触发动画效果。
  • duration:指定动画的持续时间。
  • mode:指定动画模式,可以是"in-out"、"out-in"或默认的"out-in"。

通过使用Transition组件,你可以轻松地为Vue应用中的元素添加动画效果,使用户体验更加丰富和生动。

🌰 代码演示

<template>
  <button @click="flag = !flag">隐藏/展示 p 标签</button>
  <Transition>
    <p v-if="flag">飞流直下三千尺,疑是银河落九天</p>
  </Transition>
</template>

<script>
export default {
  data() {
    return {
      flag: false,
    };
  },
};
</script>

<style scoped>
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s ease;
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
}
</style>

4.Teleport

Vue的Teleport是Vue.js 3.x版本新增的特性,它允许你将组件的内容渲染到DOM中的任何位置,而不受组件层次结构的限制。通过Teleport,你可以将组件的内容渲染到DOM中的任意位置,比如body元素下面,这样可以在组件内部实现全局级别的渲染,而不需要改变组件的层次结构。

Teleport使用一个特殊的<teleport>标签来包裹要渲染的内容,然后通过to属性指定要渲染到的目标位置,可以是CSS选择器、DOM元素或Vue组件的引用。这样,无论组件在DOM中的位置如何变化,渲染的内容都会被移动到指定的目标位置。

🌰下面是一个使用Teleport的示例:

<template>
  <teleport to="body">
    <div v-show="showModal" class="modal">
      <!-- modal content -->
    </div>
  </teleport>
  <button @click="showModal = !showModal">Toggle Modal</button>
</template>

<script>
export default {
  data() {
    return {
      showModal: false,
    };
  },
};
</script>

在这个示例中,<div class="modal">的内容会被渲染到body元素下面,而不是组件自身的位置。这样可以实现全局级别的渲染,而不需要改变组件的层次结构。

总之,Teleport是Vue.js 3.x中非常有用的特性,它可以帮助你更灵活地控制组件的渲染位置,提高了组件的复用性和灵活性。

5.Suspense

Suspense 组件是 Vue3 新增的内置组件之一。它允许我们的应用程序在等待异步组件的同时渲染一些备用内容,让我们创造一个流畅的用户体验。

⏰ 什么是 Suspense 组件?

Suspense 组件用于在等待某种异步组件解析时显示回退内容。

❓ 您可能会想,我们什么时候会使用异步组件?

老实说,比你想象的要多。每当我们希望我们的组件等待它获取数据(通常是在异步 API 调用中)时,我们可以使用 Vue3 Composition API 创建一个异步组件。

以下是一些异步组件有用的实例:

  • 在加载页面之前显示加载动画
  • 显示占位符内容
  • 处理延迟加载的图像
  • etc

以前,在 Vue2 中,我们必须使用条件(例如 v-ifv-else)来检查数据是否已加载并显示回退内容。但是现在,Vue3 内置了 Suspense,所以我们不必担心数据加载时的跟踪和相应内容的渲染。

⏰ 如何使用 Suspense 组件?

有两种类型的异步依赖可以等待 <Suspense>

  • 带有 async setup() 钩子的组件。这包括使用 <script setup> 顶级 await 表达式的组件。
  • 异步组件

🌰 例如,我们有一个 TodoInfo 组件,其中使用了 <script setup>,该组件在完全渲染前异步加载一些数据。

<template>
  <h1>{{ title }}</h1>
</template>

<script setup>
const getTodoInfo = async () => {
  return await fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(response => response.json())
    .then(json => json)
}

var { title } = await getTodoInfo()
</script>

然后,我们有一个 TodoList.vue 组件,其中包含 TodoInfo 组件。

如果我们要在等待组件获取数据并解析时显示 Loading... 之类的内容,只需要三步:

  • 将异步组件包装在 <template #default> 标签中
  • 在异步组件旁边添加一个同级的 <template #fallback> 标签
  • 将两个组件包装在 <Suspence> 组件中

使用插槽,Suspense 将渲染备用内容,直到默认内容准备就绪为止。然后,它会自动切换到显示我们的异步组件。

它看起来有点像这样。

<Suspense>
  <template #default>
    <todo-info/>
  </template>
  <template #fallback>
    <div>Loading...</div>
  </template>
</Suspense>

⏰ 捕获组件错误

当我们使用异步组件时,我们还可以捕获错误并向用户显示一些错误消息。

在 Vue2 中,我们可以使用 errorCaptured 钩子,但是在 Vue3 中,它已重命名为 onErrorCaptured

不管它被命名为什么,当任何子代组件的错误被捕获时,这个钩子就会运行。我们可以在 Suspense 中使用这个来渲染出错时的错误。

如果我们处理错误以显示错误消息,那么上面的组件就是这样的。

<template>
  <div v-if="errMsg"> {{ errMsg }} </div>
  <Suspense v-else>
    <template #default>
      <todo-info/>
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>

<script setup>
import { onErrorCaptured } from 'vue'

const errMsg = ref(null)
onErrorCaptured(e => {
  errMsg.value = '出错了!'
  return true
})
</script>

6.slot

⏰ slot是什么 ?

slot,也称插槽,可以类比为插卡式的FC游戏机,游戏机(子组件)暴露卡槽(插槽)让用户插入不同的游戏磁条(自定义内容),游戏机会读取并加载磁条里的游戏。 Vue的slot,是组件的一块HTML模版,这块模版由使用组件者即父组件提供。可以说是子组件暴露的一个让父组件传入自定义内容的接口。

⏰ slot的作用

slot的用法可以分为三类,分别是默认插槽、具名插槽和作用域插槽 子组件中:

  • 插槽用标签来确定渲染的位置,里面放如果父组件没传内容时的后备内容
  • 具名插槽用name属性来表示插槽的名字,不传为默认插槽
  • 作用域插槽在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件slot-scope接受的对象上。

Child.vue

<template>
  <div>
    <main>
    <!-- 默认插槽 -->
        <slot>
          <!-- slot内为后备内容 -->
          <h3>没传内容</h3>
        </slot>
    </main>

    <!-- 具名插槽 -->
    <header>
        <slot name="header">
          <h3>没传header插槽</h3>
        </slot>
    </header>

    <!-- 作用域插槽 -->
    <footer>
        <slot name="footer" testProps="子组件的值">
          <h3>没传footer插槽</h3>
        </slot>
    <footer>
  </div>
</template>

父组件中在使用时:

  • 默认插槽的话直接在子组件的标签内写入内容即可
  • 具名插槽是在默认插槽的基础上加上slot属性,值为子组件插槽name属性值
  • 作用域插槽则是通过slot-scope获取子组件的信息,在内容中使用。这里可以用解构语法去直接获取想要的属性

Parent.vue

<child>
  <!-- 默认插槽 -->
  <div>默认插槽</div>  
  <!-- 具名插槽 -->
  <div slot="header">具名插槽header</div>
  <!-- 作用域插槽 -->
  <div slot="footer" slot-scope="slotProps">
    {{slotProps.testProps}}
  </div>
</child>

渲染结果为

⏰ v-slot

⚠️ 在vue2.6中,上述的API被软废弃(3.0正式废弃),取而代之的是内置指令v-slot,可以缩写为【#】

子组件用法保持不变,父组件中

  • slot属性弃用,具名插槽通过指令参数v-slot:插槽名 的形式传入,可以简化为 #插槽名。
  • slot-scope属性弃用,作用域插槽通过v-slot:xxx="slotProps"的slotProps来获取子组件传出的属性
  • v-slot属性只能在<template>上使用,但在【只有默认插槽时】可以在组件标签上使用

Parent

<template>
  <child>
   <!--默认插槽-->
   <template v-slot>
     <div>默认插槽</div>
   </template>
   <!--具名插槽-->
   <template #header>
     <div>具名插槽</div>
   </template>
   <!--作用域插槽-->
   <template #footer="slotProps">
     <div>
      {{slotProps.testProps}}
     </div>
   </template>
  <child>
</template>

🍀 拓展用法:

同样可以通过解构获取v-slot={user}, 还可以重命名v-slot="{user: newName}"和定义默认值v-slot="{user = '默认值'}" 插槽名可以是动态变化的 v-slot:[slotName]

⚠️ 注意

默认插槽名为default,可以省略default直接写v-slot, 缩写为#时不能不写参数,写成#default(这点所有指令都一样,v-bind、v-on) 多个插槽混用时,v-slot不能省略default

 

posted on 2024-07-25 00:01  梁飞宇  阅读(22)  评论(0)    收藏  举报