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

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

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

相关推荐
xw518 小时前
uni-app中v-if使用”异常”
前端·uni-app
!win !18 小时前
uni-app中v-if使用”异常”
前端·uni-app
IT_陈寒19 小时前
Java 性能优化:5个被低估的JVM参数让你的应用吞吐量提升50%
前端·人工智能·后端
南囝coding19 小时前
《独立开发者精选工具》第 018 期
前端·后端
小桥风满袖19 小时前
极简三分钟ES6 - ES9中for await of
前端·javascript
半花20 小时前
i18n国际语言化配置
前端
编程贝多芬20 小时前
Promise 的场景和最佳实践
前端·javascript
Asort20 小时前
JavaScript 从零开始(四):基础语法详解——从变量声明到数据类型的完全指南
前端·javascript
木木jio20 小时前
前端大文件分片上传 —— 基于 React 的工程化实现
前端·javascript
南雨北斗20 小时前
JS的对象属性存储器
前端