vue组件基础知识
- 组件结构
- 组件注册
- 组件名
组件结构:
在 Vue 中支持单文件组件,也就是一个文件对应一个组件,这样的文件以 .vue 作为后缀。
一个组件会包含完整的一套结构、样式以及逻辑
vue
<template>
<button @click="count++">Count is: {{ count }}</button>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<style scoped>
button{
padding: 15px;
}
</style>
除了单文件组件的形式来定义组件外,还可以使用对象的形式来定义组件:
js
export default {
setup(){
// 定义数据
const count = ref(0)
return { count }
},
template: `<div>{{count}}</div>`
}
下面是一个具体的例子:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<template id="my-template-element">
<div>
<h1>{{ count }}</h1>
<button @click="count++">Increment</button>
</div>
</template>
<script src="https://unpkg.com/vue@3.2.31"></script>
<script>
const { createApp, ref } = Vue;
const App = {
setup() {
const count = ref(0);
return { count };
},
template: "#my-template-element",
};
createApp(App).mount("#app");
</script>
</body>
</html>
template
<template> 是 Vue 专门用来 写 HTML 结构的标签,它本身不会被渲染成真实的 DOM 元素 **,只用来包裹内容、组织模板结构。
setup
核心定义:
setup 是 Vue3 组合式 API 的核心入口函数,用于替代 Vue2 选项式 API 中的 data、methods、mounted 等大部分选项,专门用于组织组件的逻辑(数据、方法、监听、生命周期等)
核心作用:
将组件的逻辑代码按"业务功能"集中管理,替代选项式 API 的分散式写法,同时更好地支持逻辑复用和 TypeScript 类型推导(纯JS场景下主要提升代码可读性和可维护性)。
关键特性:
-
执行时机:组件创建前(beforeCreate 之前)执行,此时组件实例还未完全创建,无法访问 this(this 为 undefined)。
-
作用域:独立于组件实例,内部声明的变量、方法,必须通过 return 暴露,才能在模板(template)中使用。
-
从 Vue3.2 版本开始,推出了 setup 标签,所有定义的数据状态以及方法都会自动暴露给模板使用,从而减少了样板代码。
另外 setup 标签语法还有一些其他的好处:
- 有更好的类型推断
- 支持顶级 await
setup 的参数(2 个固定参数):
setup 函数有且只有 2 个固定参数,顺序不可颠倒,纯JS场景下无需关注类型,直接使用即可。
基本语法:
js
setup(props, context) {
// 逻辑代码
return { /* 暴露给模板的内容 */ }
}
1. 第一个参数:props(接收父组件传递的数据)
props 是一个响应式对象,用于接收父组件通过 props 选项传递过来的数据,必须在组件的 props 选项中声明,才能在 setup 中获取。
核心细节:
- 响应式:props 本身是响应式的,父组件传递的数据变化时,setup 中能自动感知(无需额外处理)。
- 不可修改:setup 中不能直接修改 props 的值(会报错),若需修改,需通过子传父(emit)通知父组件修改。
js
export default defineComponent({
props: {
width: { // 父组件传递的设计稿宽度
type: [String, Number],
default: 1920
},
},
setup(props) {
// 直接获取父组件传递的 props
console.log(props.width); // 1920(默认值)
// 不能直接修改 props
// props.width = 1366; // ❌ 错误,会报错
}
})
第二个参数:context(组件上下文对象)
context 是一个普通对象(非响应式),包含 3 个核心属性,用于访问组件的上下文信息,替代 Vue2 中的 this 相关功能(如 this. <math xmlns="http://www.w3.org/1998/Math/MathML"> e m i t 、 t h i s . emit、this. </math>emit、this.slots)。
核心属性:
- attrs:接收父组件传递的、未在 props 中声明的属性(相当于 Vue2 的 this.$attrs)。
- slots:组件的插槽内容(相当于 Vue2 的 this.$slots)。
- emit:用于子组件向父组件触发事件(相当于 Vue2 的 this.$emit),实现子传父通信。
js
setup(props, { attrs, slots, emit }) {
// 1. 使用 slots(渲染默认插槽,对应你之前的代码)
const slotContent = slots.default?.(); // 渲染父组件传入的插槽内容
// 2. 使用 emit(子传父,示例:通知父组件缩放比例变化)
emit('widthChange', scale); // 触发父组件的 widthChange 事件
// 3. 使用 attrs(获取未在 props 中声明的属性)
console.log(attrs.otherProp); // 父组件传递的、未声明的属性
}
setup 函数的返回值:
1. 最常用:返回一个对象(99% 场景)
返回的对象中,所有的属性和方法,都会暴露给模板(template),模板中可以直接使用,无需额外配置。
核心细节:
-
数据/方法暴露:必须将模板中需要使用的变量、方法,放入返回对象中,否则模板无法访问。
-
响应式数据:若需数据在模板中响应式更新,需用 ref 或 reactive 包裹。
js
import { ref } from 'vue';
setup(props, { slots }) {
// 1. 定义响应式数据(ref 包裹,模板中可自动响应)
const widthRef = ref(100);
// 2. 定义方法(模板中可直接调用)
function updateWidth(value) {
widthRef.value = value;
};
// 3. 返回对象:暴露给模板的内容(widthRef、updateWidth 可在模板中使用)
return {
widthRef,
updateWidth
};
}
2. 高级用法:返回一个渲染函数(极少用)
返回一个渲染函数(通常用 h 函数),用于完全用 JS 编写组件模板,替代