Vue 3 组件开发中的"双脚本"困境

一目拾贝

  1. 缘起:一个真实的开发困扰
  2. 背景:Vue 3 的两种组件写法
  3. 核心问题:为什么想要"双脚本"?
  4. 技术现状:不同构建工具的差异
  5. 解决方案:因地制宜的选择
  6. 最佳实践:推荐的工作流
  7. 小结与总结

缘起:一个真实的开发困扰

最近在 Vue 3 项目中遇到一个有趣的问题:想要在同一个 .vue 文件中同时使用 <script setup> 的简洁语法和普通 <script> 的组件选项,就像这样:

js 复制代码
<script setup>
// 响应式数据、方法等逻辑
const count = ref(0)
const increment = () => count.value++
</script>
<script>
export default {
  name: 'MyComponent',
  components: {
    CustomButton: () => import('./CustomButton.vue')
  }
}
</script>

这个想法听起来很美好,但现实却给了我们当头一棒。

背景:Vue 3 的两种组件写法

Vue 3 为我们提供了两种组件编写方式:

选项式 API(Options API)

js 复制代码
<script>
export default {
  name: 'MyComponent',
  data() {
    return { count: 0 }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}
</script>

组合式 API + <script setup>

js 复制代码
<script setup>
import { ref } from 'vue'
const count = ref(0)
const increment = () => count.value++
</script>

核心问题:为什么想要"双脚本"?

开发者们想要"双脚本"的原因其实很实际:

  1. 组件命名需求<script setup> 默认无法设置组件名,而组件名在调试、DevTools 中很重要
  2. 组件注册:某些场景下需要手动注册子组件,如别名 或 变量命名组件
js 复制代码
import { Select, SelectOption, PageHeader, Tag, Button } from 'ant-design-vue'
...
components: {
    // 别名
    'a-select': Select,
    'a-select-option': SelectOption,
    // 变量命名组件
    [PageHeader.name]: PageHeader,
    [Tag.name]: Tag,
    [Button.name]: Button
  }
  1. 渐进式迁移:从选项式 API 迁移到组合式 API 时的过渡需求
  2. 团队协作:不同开发者习惯不同写法

技术现状:不同构建工具的差异

这里有个关键问题:你的构建工具决定了能否实现"双脚本"

Vite 项目:有解决方案

如果你用的是 Vite,恭喜你!有一个专门的插件:vite-plugin-vue-setup-extend

arduino 复制代码
npm install vite-plugin-vue-setup-extend --save-dev

vite.config.ts 中配置:

js 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'

export default defineConfig({
  plugins: [
    vue(),
    vueSetupExtend()
  ]
})

然后你就可以愉快地写"双脚本"了:

js 复制代码
<script setup>
const count = ref(0)
</script>
<script>
export default {
  name: 'MyComponent'
}
</script>

Vue CLI 项目:无解

如果你用的是 Vue CLI(基于 Webpack),很遗憾😭,目前没有官方或社区插件支持这种写法

Vue CLI 项目只能二选一:

  • 要么用 <script setup>
  • 要么用普通 <script>

解决方案:因地制宜的选择

方案一:升级到 Vue 3.3+ 使用 defineOptions

如果你的 Vue 版本是 3.3 及以上,可以使用 defineOptions

js 复制代码
<script setup>
defineOptions({
  name: 'MyComponent',
  components: {
    CustomButton: () => import('./CustomButton.vue')
  }
})

const count = ref(0)
</script>

方案二:迁移到 Vite

如果项目允许,考虑从 Vue CLI 迁移到 Vite:

  1. 安装 Vite 相关依赖
  2. 创建 vite.config.ts
  3. 配置 vite-plugin-vue-setup-extend
  4. 享受"双脚本"的便利

方案三:统一使用一种写法

最稳妥的方案是统一团队代码风格:

推荐:纯 <script setup>

js 复制代码
<script setup>
// 组件名通过文件名或目录结构体现
// 子组件直接 import 使用,无需注册
import CustomButton from './CustomButton.vue'
const count = ref(0)
</script>

最佳实践:推荐的工作流

基于实际项目经验,我推荐这样的工作流:

  1. 新项目 :直接使用 Vite + <script setup> + defineOptions
  2. 老项目 :逐步迁移到 <script setup>,统一代码风格
  3. 团队规范:制定明确的组件编写规范,避免混用

小结

要点梳理:

  • Vue 3 的"双脚本"需求源于实际开发中的命名和注册需求
  • Vite 项目可以通过 vite-plugin-vue-setup-extend 实现
  • Vue CLI 项目目前无法实现,需要选择单一写法
  • Vue 3.3+ 的 defineOptions 提供了官方解决方案
  • 统一代码风格比追求"双脚本"更重要

总结

Vue 3 的"双脚本"需求反映了开发者对灵活性的追求,但技术实现受限于构建工具。与其纠结于语法糖的混用,不如专注于代码的可维护性和团队协作效率。

在实际项目中,统一的代码风格和清晰的组件结构往往比语法糖的便利性更重要。选择适合你项目的方案,保持代码的一致性,这才是真正的最佳实践。

记住:技术是为了解决问题,而不是制造问题。选择简单有效的方案,往往比追求复杂的"完美"解决方案更实用。

相关推荐
徐子颐11 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭23 分钟前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu1 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花1 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋1 小时前
场景模拟:基础路由配置
前端
六月的可乐2 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程
一 乐2 小时前
智慧党建|党务学习|基于SprinBoot+vue的智慧党建学习平台(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·学习