vue3-组件基础

77 阅读4分钟

组件基础

一、定义一个组件

  • 1、使用构建步骤,定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称 SFC):
<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>
  • 2、不使用构建步骤时,一个 Vue 组件以一个包含 Vue 特定选项的 JavaScript 对象来定义:
  • 这里的模板是一个内联的 JavaScript 字符串,Vue 将会在运行时编译它。你也可以使用 ID 选择器来指向一个元素 (通常是原生的 <template> 元素),Vue 将会使用其内容作为模板来源。
  • 上面的例子中定义了一个组件,并在一个 .js 文件里默认导出了它自己,但你也可以通过具名导出在一个文件中导出多个组件。
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    return { count }
  },
  template: `
    <button @click="count++">
      You clicked me {{ count }} times.
    </button>`
  // 也可以针对一个 DOM 内联模板:
  // template: '#my-template-element'
}

二、全局注册

  • 使用 Vue 应用实例的 .component() 方法,让组件在当前 Vue 应用中全局可用。
  • 全局注册,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。
import MyComponent from './MyComponent.vue';
//单个
app.component('MyComponent', MyComponent);
//被链式调用
app
  .component('ComponentA', ComponentA)
  .component('ComponentB', ComponentB)
  .component('ComponentC', ComponentC)

三、使用组件

  • 通过 <script setup>,导入的组件都在模板中直接可用。
  • 全局注册的组件无需引入。
<script setup>
import ButtonCounter from './ButtonCounter.vue'
</script>

<template>
  <h1>Here is a child component!</h1>
  <ButtonCounter />
</template>
  • 如果没有使用 <script setup>,则需要使用 components 选项来显式注册:
import ComponentA from './ComponentA.vue'
export default {
  components: {
    ComponentA
  },
  setup() {  }
}
  • 如果你是直接在 DOM 中书写模板 (例如原生 <template> 元素的内容),模板的编译需要遵从浏览器中 HTML 的解析行为。
  • 在这种情况下,你应该需要使用 kebab-case 形式并显式地关闭这些组件的标签。
<!-- 如果是在 DOM 中书写该模板 -->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>

四、组件名格式

  • 在整个指引中,我们都使用 PascalCase 作为组件名的注册格式,这是因为:
  • 1.PascalCase 是合法的 JavaScript 标识符。这使得在 JavaScript 中导入和注册组件都很容易,同时 IDE 也能提供较好的自动补全。
  • 2. 在模板中更明显地表明了这是一个 Vue 组件,而不是原生 HTML 元素。同时也能够将 Vue 组件和自定义元素 (web components) 区分开来。
  • 在单文件组件和内联字符串模板中,我们都推荐这样做。但是,PascalCase 的标签名在 DOM 内模板中是不可用的。
  • Vue 支持将模板中使用 kebab-case 的标签解析为使用 PascalCase 注册的组件。这意味着一个以 MyComponent 为名注册的组件,在模板中可以通过 <MyComponent> 或 <my-component> 引用

五、插槽来分配内容

  • 向组件中传递内容
<AlertBox>
  Something bad happened.
</AlertBox>

<!-- AlertBox.vue -->
<template>
  <div class="alert-box">
    <strong>This is an Error for Demo Purposes</strong>
    <slot />
  </div>
</template>

六、动态组件

  • 通过 Vue 的 <component :is="..."> 元素和特殊的 is attribute 实现的:
  • :is 的值可以是:被注册的组件名、导入的组件对象
<!-- componentName 改变时组件也改变 -->
<component :is="componentName"></component>
  • 当使用 <component :is="..."> 来在多个组件间作切换时,被切换掉的组件会被卸载。我们可以通过 组件强制被切换掉的组件仍然保持“存活”的状态。
<!-- 非活跃的组件将会被缓存! -->
<KeepAlive>
  <component :is="activeComponent" />
</KeepAlive>

1、DOM 内模板解析注意事项

  • 如果你想在 DOM 中直接书写 Vue 模板,Vue 则必须从 DOM 中获取模板字符串。由于浏览器的原生 HTML 解析行为限制,有一些需要注意的事项。
  • 请注意下面讨论只适用于直接在 DOM 中编写模板的情况。如果你使用来自以下来源的字符串模板,就不需要顾虑这些限制了:
  • 单文件组件
  • 内联模板字符串 (例如 template: '...')
  • <script type="text/x-template">
2、大小写区分
  • HTML 标签和属性名称是不分大小写的,所以浏览器会把任何大写的字符解释为小写。这意味着当你使用 DOM 内的模板时,无论是 PascalCase 形式的组件名称、camelCase 形式的 prop 名称还是 v-on 的事件名称,都需要转换为相应等价的 kebab-case (短横线连字符) 形式:
// JavaScript 中的 camelCase
const BlogPost = {
  props: ['postTitle'],
  emits: ['updatePost'],
  template: `
    <h3>{{ postTitle }}</h3>
  `
}
<!-- HTML 中的 kebab-case -->
<blog-post post-title="hello!" @update-post="onUpdatePost"></blog-post>
3、闭合标签
  • Vue 的模板解析器支持任意标签使用 /> 作为标签关闭的标志
<MyComponent />
  • 然而在 DOM 内模板中,我们必须显式地写出关闭标签:
<my-component></my-component>
4、元素位置限制
  • 某些 HTML 元素对于放在其中的元素类型有限制,例如 <ul>,<ol>,<table> 和 <select>,相应的,某些元素仅在放置于特定元素中时才会显示,例如 <li>,<tr> 和 <option>。
  • 这将导致在使用带有此类限制元素的组件时出现问题。例如:
<table>
  <blog-post-row></blog-post-row>
</table>
  • 自定义的组件 <blog-post-row> 将作为无效的内容被忽略,因而在最终呈现的输出中造成错误。我们可以使用特殊的 is attribute 作为一种解决方案:
<table>
  <tr is="vue:blog-post-row"></tr>
</table>