组件基础

什么是组件?

组件是 Vue 应用的基本构建块,允许我们将 UI 拆分为独立、可复用的片段。每个组件都有自己的模板、逻辑和样式。

组件的注册方式

全局注册

import { createApp } from 'vue'
import App from './App.vue'
import MyComponent from './components/MyComponent.vue'

const app = createApp(App)

// 全局注册组件
app.component('MyComponent', MyComponent)

app.mount('#app')

局部注册

import { defineComponent } from 'vue'
import MyComponent from './components/MyComponent.vue'

export default defineComponent({
  name: 'App',
  components: {
    // 局部注册组件
    MyComponent
  }
})

组件的基本结构

单文件组件 (SFC)

<template>
  <div class="my-component">
    <h2>{{ title }}</h2>
    <p>{{ content }}</p>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  props: {
    title: String,
    content: {
      type: String,
      default: '默认内容'
    }
  },
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}
</script>

<style scoped>
.my-component {
  padding: 20px;
  border: 1px solid #eee;
  border-radius: 8px;
}
</style>

组件的使用

在模板中使用组件

<template>
  <div>
    <h1>应用标题</h1>
    <!-- 使用全局注册的组件 -->
    <MyComponent title="组件标题" content="组件内容" />
    
    <!-- 使用局部注册的组件 -->
    <my-component title="另一个组件" />
    
    <!-- 动态绑定属性 -->
    <MyComponent :title="dynamicTitle" />
  </div>
</template>

组件的命名规范

  • PascalCase :推荐用于组件定义和导入,例如 MyComponent
  • kebab-case :推荐用于模板中使用,例如 <my-component>
  • 组件名应该是有意义的,避免使用单个单词
  • 避免使用 Vue 的保留字,如 component、model 等

组件的生命周期

组件实例从创建到销毁的过程中,会经历一系列的生命周期阶段,每个阶段都有对应的钩子函数。

组件生命周期示例

export default {
  beforeCreate() {
    console.log('组件实例刚被创建')
  },
  created() {
    console.log('组件实例已创建完成')
  },
  beforeMount() {
    console.log('模板编译完成,但尚未挂载')
  },
  mounted() {
    console.log('组件已挂载到 DOM')
  },
  beforeUpdate() {
    console.log('数据更新前,DOM 尚未重新渲染')
  },
  updated() {
    console.log('数据更新后,DOM 已重新渲染')
  },
  beforeUnmount() {
    console.log('组件卸载前')
  },
  unmounted() {
    console.log('组件已卸载')
  }
}

组件的样式隔离

Vue 提供了 scoped 属性来实现组件样式的隔离,确保组件的样式不会影响到其他组件。

scoped 样式

<style scoped>
.my-component {
  color: red;
}
</style>

深度选择器

<style scoped>
/* 深度选择器,用于修改子组件的样式 */
.my-component :deep(.child-component) {
  color: blue;
}

/* 或者使用 ::v-deep */
.my-component ::v-deep .child-component {
  color: blue;
}
</style>

最佳实践

  • 优先使用局部注册,避免全局命名冲突
  • 组件应该保持单一职责,专注于一个功能
  • 合理使用 props 和 events 进行组件通信
  • 使用 scoped 样式隔离组件样式
  • 为组件添加清晰的文档和类型定义