@vue/compiler-sfc是给什么用的, 用调用链表示谁调用了它
js
`@vue/compiler-sfc` 的主要用途是解析和编译 Vue.js 的单文件组件(Single File Components,SFCs)。这个库通常不会被直接调用,而是在 Vue 开发和构建工具中被使用,作为处理 .vue 文件的核心工具。
### `@vue/compiler-sfc` 的调用链
要显示 `@vue/compiler-sfc` 的调用链,我们可以考虑它在一个典型的 Vue 项目中的使用场景。以下是一种常见的调用链表示:
1. **开发工具(如 Vue CLI、Vite 等)**:
- 开发者配置和运行构建工具,这些工具设置项目的构建过程,包括解析和编译源代码。
2. **构建工具的 SFC 解析器插件**:
- Vue CLI 或 Vite 使用内部或第三方插件来处理 .vue 文件。这些插件利用 `@vue/compiler-sfc` 来解析和编译 `.vue` 文件。
3. **`@vue/compiler-sfc`**:
- 被插件调用来处理单文件组件。它会解析组件的各个部分(模板、脚本、样式),并将模板编译成 JavaScript 渲染函数。
4. **生成的代码**:
- `@vue/compiler-sfc` 返回经过处理的组件代码,此代码可用于进一步的打包和优化,最终生成可以在浏览器中运行的 JavaScript。
5. **应用在浏览器中运行**:
- 打包过的代码通过浏览器执行,实现最终的应用效果。
### 实际代码中怎么体现
在实际项目中,`@vue/compiler-sfc` 的使用通常被抽象掉了,开发者不需要直接与它交互。例如:
// 假设在一个 Vite 项目中使用 Vue
import { createApp } from 'vue';
import App from './App.vue';
// 这里的 .vue 文件会自动被处理,
// 通过 Vite 或构建工具背后的调用链使用 `@vue/compiler-sfc`
const app = createApp(App);
app.mount('#app');
在上面的例子中,对 `App.vue` 的引用将自动触发 Vite 中的相应插件来使用 `@vue/compiler-sfc` 解析和编译这个组件文件。
因此,`@vue/compiler-sfc` 的调用链是从开发工具到插件系统,最终在内部完成对 .vue 文件的解析和编译。
编译器宏(compiler macros)
markdown
1. **`defineProps`**
- 作用:用于声明组件的 props。
- 示例:
<script setup>
const props = defineProps({
title: String,
count: Number
})
</script>
2. **`defineEmits`**
- 作用:用于声明组件可以发出的事件。
- 示例:
<script setup>
const emit = defineEmits(['update', 'delete'])
function updateItem() {
emit('update')
}
</script>
3. **`defineExpose`**
- 作用:用于显式暴露给父组件的属性或方法。
- 示例:
<script setup>
function someMethod() { /* ... */ }
defineExpose({
someMethod
})
</script>
4. **`withDefaults`**
- 作用:为 props 提供默认值。
- 示例:
<script setup>
const props = withDefaults(defineProps({
message: String
}), {
message: 'Hello World'
})
</script>
5. **`useSlots`**
- 作用:用于获取插槽对象。
- 示例:
<script setup>
const slots = useSlots()
if (slots.default) {
// 使用默认插槽内容
}
</script>
6. **`useAttrs`**
- 作用:用于获取透传的 attribute。
- 示例:
<script setup>
const attrs = useAttrs()
// 可以将 attrs 传递给子组件
</script>
7. **`defineModel`**
- defineModel编译器宏 3.3版本引入 | 2023年4月8日pull请求
- 作用:用于声明模型属性,实现双向绑定。
- 示例:
<script setup>
defineModel({
props: 'modelValue',
emit: 'update:modelValue'
})
</script>
8. **`defineOptions`**
- 作用:用于在 `<script setup>` 中声明组件选项。
- 示例:
<script setup>
defineOptions({
name: 'MyComponent'
})
</script>
9. **`ref` (setup function specific)**
- 作用:用于声明响应式引用。
- 示例:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
10. **`computed` (setup function specific)**
- 作用:用于声明计算属性。
- 示例:
<script setup>
import { computed } from 'vue'
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
</script>
类型检查
vue
<script lang="ts">
import { defineComponent, ref } from 'vue';
// 接口定义
interface User {
id: number;
name: string;
email?: string; // 可选属性
}
// 字面量类型
type Status = 'success' | 'error' | 'pending';
// 组件定义
export default defineComponent({
name: 'ExampleComponent',
setup() {
// 使用基本类型
const count = ref<number>(0);
// 使用联合类型
const identifier: string | number = "user_123";
// 使用泛型
function identity<T>(arg: T): T {
return arg;
}
const numberIdentity = identity<number>(123);
// 使用交叉类型
const user: User & { status: Status } = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
status: 'success'
};
// 类型断言
const someElement = document.querySelector('.my-element') as HTMLDivElement;
// 可选链和空值合并
const email = user.email ?? 'No email provided';
// 使用类定义和成员可见性
class Service {
public status: Status = 'pending';
private data: string[] = [];
public addData(item: string): void {
this.data.push(item);
}
protected getData(): string[] {
return this.data;
}
}
const service = new Service();
service.addData('Hello');
return {
count,
identifier,
user,
someElement,
email,
service,
numberIdentity,
};
},
});
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<p>Identifier: {{ identifier }}</p>
<p>User: {{ user.name }} - Status: {{ user.status }}</p>
<p>Email: {{ email }}</p>
<p>Service Status: {{ service.status }}</p>
<p>Number Identity: {{ numberIdentity }}</p>
</div>
</template>