使用 TypeScript 时如何在单个文件组件中导入 Vue?

Posted

技术标签:

【中文标题】使用 TypeScript 时如何在单个文件组件中导入 Vue?【英文标题】:How to import Vue in Single File Component when using TypeScript? 【发布时间】:2020-01-18 04:25:47 【问题描述】:

我有一个单文件组件,我需要导入 Vue:

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
...
@Component(...)
export class Comp extends Vue ...

我在浏览器中将 vue.js 作为模块导入:

<script type="module" src="module/vue/vue.js"></script>

但我得到了错误

Uncaught TypeError: Class extends value undefined is not a constructor or null

eval() 内部的某个位置,由 vue-cli-service --target lib 生成。我也将 SFC 作为模块加载:

<script type="module" src="module/comp/comp.js"></script>

作为一种解决方法,我尝试在 comp.js 的顶部添加导入:

import Vue from '/module/vue/vue.js'
import Component from '/module/vue-class-component/vue-class-component.js'
(function webpackUniversalModuleDefinition(root, factory) 
...

但这无济于事。

如何将导入重新连接到将在 Web 服务器上使用的路径?我检查了 webpack 的选项,但只找到了 resolve,这似乎有助于 webpack 在打包时找到东西。我需要一种“输出重写”选项。

请注意,我使用的是 ES 模块,而不是 CommonJS 或 RequireJS。 tsconfig.json

compilerOptions: "target": "ES2016", module: "ES2015"  

更新我尝试将最终路径放入 .vue 文件并在 vue.config.js 中使用 configureWebpack.resolve.alias 以允许 Vue 编译器定位模块,但这也不起作用。

vue.config.js:

module.exports = 
    runtimeCompiler: true,
    configureWebpack: 
        externals: [
            'module/vue/vue',
            'module/vue-class-component/vue-class-component',
        ],
        resolve: 
            alias: 
                'module/vue/vue': 'vue/dist/vue.esm.js',
                'module/vue-class-component/vue-class-component': 'vue-class-component/dist/vue-class-component.esm.js'
            
        ,
    

comp.vue:

...
import Vue from './module/vue/vue'
import Component from 'module/vue-class-component/vue-class-component'

只是给

ERROR in .../src/comp.vue
16:17 Cannot find module 'module/vue/vue'.

【问题讨论】:

可以用vue属性装饰器代替“vue-class-component”。从'vue-property-decorator'导入组件,Vue; @AmithaMahesh 谢谢。那也行不通。 vue-class-component 导入不是证明问题所必需的,我只是保留它以表明 Vue 不是唯一的导入,答案也应该适用于其他事情。 找不到路径,因为外部设置不正确。它需要指向全局变量而不是路径。 我的印象(我可能是错的)是当你使用 ES2015 模块时,没有全局变量。因此出现错误。 【参考方案1】:

概述

您可以在vue.config.js 中添加configureWebpack 来修改Webpack 配置,在Webpack 中您可以使用externals 解决此问题。

处理外部

Externals 为您提供了一种导入外部库的方法。

在您的 webpack 配置中,您将添加如下所示的一行。

我们以lodash 为例,因为导入和全局变量是不同的。

// webpack.config
externals: 
  'lodash': '_'

_ 是 webpack 可以抓取的全局变量,lodash 是它公开的导入。

此时,您可以执行以下操作。

import * as lodash from 'lodash'

处理类型检查

要使用此方法处理类型检查,您 npm install @types/... 和 TypeScript 将选择该导入的类型。

在 vue.config.js 中修改 Webpack

您可以阅读有关此here 的信息,但只需将以下内容添加到 vue.config.js 文件中。

// vue.config.js
module.exports = 
  configureWebpack: 
    externals: 
      'lodash': '_'
    
  

【讨论】:

如何将localhost/module/lodash/lodash.js 映射到浏览器中的导入语句? 如果你查看编译结果,你会得到这个module.exports = _; for 'lodash',所以它期望'_'已经存在。这只是将全局变量暴露给 webpack。对于 Vue.js,就像 lodash 一样,它会创建一个全局变量 Vue,您可以将其映射到 webpak 中。外部:'Vue'。浏览器只运行 Vue.js 并创建 Vue 全局变量,webpack 可以使用您指定的任何内容来引用它。在你的脚本中使用 type="module" 与否结果是一样的。 长话短说,这在我的测试平台上对我有用。我唯一可能做的不同的事情是我为Vue.js&lt;script type="module" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"&gt;&lt;/script&gt;使用了CDN 啊...我正在尝试使用 ES 模块,而不是旧的 requirejs/commonjs 东西。因此,在生成的代码中,我看到 import Vue from "vue" 适用于单元测试(npm/jest 会找到这些东西),但在浏览器中却没有(= 忽略的全局符号)。当我使用 应该 在浏览器中工作的相对路径时,tsc&jest 会中断。 tsconfig.json: compilerOptions: "target": "ES2016", module: "ES2015"

以上是关于使用 TypeScript 时如何在单个文件组件中导入 Vue?的主要内容,如果未能解决你的问题,请参考以下文章

在 Typescript 文件中导入时找不到 Vue 模块

如何在 Typescript 文件中导入 Svelte 组件?

使用Typescript和类组件装饰器时如何在Vue Router中传递props

如何使用 bit 在 javascript 项目中创建 typescript 组件?

当父组件在其子组件中注入道具时,如何在 Typescript 中定义道具?

如何在 TypeScript v2.x 中从自定义 React 组件公开“通用”事件