学海无涯

导航

组件基础

组件基础

组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构:

 

 

Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。

定义一个组件

当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称 SFC):

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

const count = ref(0)
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>

使用组件

要使用一个子组件,我们需要在父组件中导入它。假设我们把计数器组件放在了一个叫做 ButtonCounter.vue 的文件中,这个组件将会以默认导出的形式被暴露给外部。

<script setup>
import ButtonCounter from './ButtonCounter.vue'
</script>

<template>
  <h1>Here is a child component!</h1>
  <ButtonCounter />
</template>

  在单文件组件中,推荐为子组件使用 PascalCase 的标签名,以此来和原生的 HTML 元素作区分。

向组件传递数据 props

Props 是一种特别的 attributes,你可以在组件上声明注册。要传递给博客文章组件一个标题,我们必须在组件的 props 列表上声明它。这里要用到 defineProps 宏:

<template>
<h4>{{ title }}</h4>

</template>

<script setup>
import { ref } from 'vue';
const props= defineProps(['title'])

console.log(props.title)

</script>

  defineProps 是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入。声明的 props 会自动暴露给模板。defineProps 会返回一个对象,其中包含了可以传递给组件的所有 props:

 循环数组批量调用组件

父组件数据:

const posts = ref([
  { id: 1, title: 'My journey with Vue' },
  { id: 2, title: 'Blogging with Vue' },
  { id: 3, title: 'Why Vue is so fun' }
])

使用 v-for 来渲染子组件:

<BlogPost
  v-for="post in posts"
  :key="post.id"
  :title="post.title"
 />

 子组件触发父组件的事件 

<template>
<h4>{{ title }}</h4>
<button @click="changeFontSize">Enlarge text</button>
</template>

<script setup>
import { ref } from 'vue';
const props= defineProps(['title'])
//公开 enlarge-text 事件
const emit=defineEmits(['enlarge-text'])
function changeFontSize(){
  emit('enlarge-text')
}
console.log(props.title)

</script>

父组件

  <div :style="{fontSize: postFontSize+'em'}">
        <BlogPost @enlarge-text="postFontSize+=0.1" v-for="post in posts" :key="post.id" :title="post.title"/>
    </div>

通过插槽来分配内容 <slot />

将在父组件调用子组件时,把传递的内容插入到子组件中

<template>
  <div class="alert-box">
    <strong>This is an Error forDemo Purposes</strong><br/>
    <slot/>
  </div>
</template>

<script setup>

</script>

<style >
.alert-box {
  /* ... */
  font-size: 20px;
}
.alert-box strong {
     color:red;
    }
</style>

 父组件调用子组件,交将内容传入子组件

<AlertBox>
      Somthing bad happedn.
    </AlertBox>

动态组件

有些场景会需要在两个组件间来回切换,比如 Tab 界面:

<script setup>
import Home from './Home.vue'
import Posts from './Posts.vue'
import Archive from './Archive.vue'
import { ref } from 'vue'
 
const currentTab = ref('Home')

const tabs = {
  Home,
  Posts,
  Archive
}
</script>

<template>
  <div class="demo">
    <button
       v-for="(_, tab) in tabs"
       :key="tab"
       :class="['tab-button', { active: currentTab === tab }]"
       @click="currentTab = tab"
     >
      {{ tab }}
    </button>
      <component :is="tabs[currentTab]" class="tab"></component>
  </div>
</template>

<style>
.demo {
  font-family: sans-serif;
  border: 1px solid #eee;
  border-radius: 2px;
  padding: 20px 30px;
  margin-top: 1em;
  margin-bottom: 40px;
  user-select: none;
  overflow-x: auto;
}

.tab-button {
  padding: 6px 10px;
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
  border: 1px solid #ccc;
  cursor: pointer;
  background: #f0f0f0;
  margin-bottom: -1px;
  margin-right: -1px;
}
.tab-button:hover {
  background: #e0e0e0;
}
.tab-button.active {
  background: #e0e0e0;
}
.tab {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>
View Code

上面的例子是通过 Vue 的 <component> 元素和特殊的 is attribute 实现的:

<!-- currentTab 改变时组件也改变 -->
<component :is="tabs[currentTab]"></component>

在上面的例子中,被传给 :is 的值可以是以下几种:

  • 被注册的组件名
  • 导入的组件对象

你也可以使用 is attribute 来创建一般的 HTML 元素。

当使用 <component :is="..."> 来在多个组件间作切换时,被切换掉的组件会被卸载。我们可以通过 <KeepAlive> 组件强制被切换掉的组件仍然保持“存活”的状态。

 

 

 

 

 

posted on 2023-02-28 14:22  宁静致远.  阅读(21)  评论(0编辑  收藏  举报