一、遇到的问题
在Uniapp + Vue2 项目升级到 Vue3+Ts时,如果<script>使用了setup语法糖,则无法用export default 导出 App.vue中的 globalData全局变量,其他页面就无法通过getApp()方法来获取globalData已实现好的方法和全局变量。
如果在 <script setup>
使用 export default 则报如下错误:
plugin:vite:vue] [@vue/compiler-sfc] <script setup> cannot contain ES module exports. If you are using a previous version of <script setup>, please consult the updated RFC at https://github.com/vuejs/rfcs/pull/227.
E:/Workspaces/weixin/jiaowu_a_uni/App.vue
1 | <script setup lang="ts"> ^
2 | export default {}
| ^^^^^^^^^^^^^^^^^
二、<script setup> 说明
<script setup>
是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。相比于普通的 <script>
语法,它具有更多优势:
- 更少的样板内容,更简洁的代码。
- 能够使用纯 TypeScript 声明 props 和自定义事件。
- 更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
- 更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。
三、解决方案
我们可以利用 <script> 和 <script setup> 共存方式来兼容,<script>中使用 export default 保持原有写法,<script setup> 来做语法糖实现部分
<!-- 语法糖写法 -->
<script setup lang="ts">
onLaunch(() => {
console.log('onLaunch1')
});
</script>
<!-- 兼容 setup 无法使用 export default 限制 -->
<script lang="ts">
export default {
globalData: {},
onLaunch: function () {
console.log('onLaunch2')
}
</script>
// onLaunch1 和 onLaunch2 都会被执行,如果有顺序要求,调整下 <script> 顺序即可
需要注意的是:当项目是ts的时候,普通的script上也需要声明lang=‘ts’,否则会报错
[plugin:vite:vue] [@vue/compiler-sfc] <script> and <script setup> must have the same language type.
四、总结扩展
<script setup> 可以和普通的 <script> 一起使用可以解决下面这些场景下的问题
1. 无法在<script setup> 声明的选项,例如 inheritAttrs 或通过插件启用的自定义的选项。
2. 声明命名导出。
3. 运行副作用或者创建只需要执行一次的对象。
<script>
// 普通 <script>,在模块范围下执行(只执行一次)
runSideEffectOnce()
// 声明额外的选项
export default {
inheritAttrs: false,
customOptions:{
}
}
</script>
<script setup>
// 在 setup()作用域中执行(对每个实例皆如此)
</script>