让 Vue.js 从带有 JSX 包的基本 CLI 安装使用 TypeScript 渲染 JSX
Posted
技术标签:
【中文标题】让 Vue.js 从带有 JSX 包的基本 CLI 安装使用 TypeScript 渲染 JSX【英文标题】:Getting Vue.js to render JSX with TypeScript from base CLI install with JSX package 【发布时间】:2021-09-24 21:46:08 【问题描述】:设置
我有created a basic project with the vue-cli,在此期间我使用“手动选择功能”进行安装,我选择了以下内容(除了 linter):
已选择 Babel、TypeScript、Vuex 和 Linter / Formatter 已选择 2.x 否类样式组件 Yes 将 Babel 与 TypeScript 一起使用(现代模式需要, 自动检测到 polyfills,转译 JSX)?然后,我还安装了jsx support(我验证安装的 Babel 版本是 7,因为该 jsx 支持 repo 需要它)。
在我的 bable.config.js 文件中,我添加了(没有替换 vue-cli 生成的内容)jsx repo 请求的预设: p>
module.exports =
presets: [
'@vue/cli-plugin-babel/preset',
'@vue/babel-preset-jsx', //<-- Added this
],
;
我已经确认 自动生成的 tsconfig.json 具有所需的配置(至少据我了解):
"compilerOptions":
...
"jsx": "preserve",
...
我已确认 自动生成 shims-tsx.d.ts 文件具有所需的配置(至少据我了解):
import Vue, VNode from 'vue';
declare global
namespace JSX
// tslint:disable no-empty-interface
interface Element extends VNode
// tslint:disable no-empty-interface
interface ElementClass extends Vue
interface IntrinsicElements
[elem: string]: any
在生成的 auto-generated main.ts 文件中,JSX 似乎已成功使用(尽管我相信它不是 .tsx
扩展名webpack 在幕后将事情转变为工作:
new Vue(
store,
render: (h) => h(App),
).$mount('#app');
所以自动生成的 App.vue 文件有这个(我忽略了<style>
信息),在npm run serve
上渲染得很好:
<template>
<div id="app">
<img src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
</div>
</template>
<script lang="ts">
import Vue, VNode from 'vue';
import HelloWorld from './components/HelloWorld.vue';
export default Vue.extend(
name: 'App',
components:
HelloWorld,
,
);
</script>
问题
据我了解,对 App.vue 的以下修改应该可以工作(渲染函数正是 jsx 存储库中的第一个“语法”示例所具有的):
// template removed
<script lang="ts">
import Vue, VNode from 'vue';
import HelloWorld from './components/HelloWorld.vue';
export default Vue.extend(
name: 'App',
functional: true,
render()
return <p>hello</p>
);
</script>
但相反,我在终端窗口中收到了这组错误:
ERROR in /home/scott/convrrt-component/view-play/src/App.vue(19,3):
19:3 No overload matches this call.
The last overload gave the following error.
Type '() => boolean' is not assignable to type '(createElement: CreateElement, hack: RenderContext<Record<string, any>>) => VNode'.
Type 'boolean' is not assignable to type 'VNode'.
17 | HelloWorld,
18 | ,*/
> 19 | render()
| ^
20 | return <p>hello</p>
21 |
22 | );
ERROR in /home/scott/convrrt-component/view-play/src/App.vue(20,13):
20:13 Cannot find name 'p'.
18 | ,*/
19 | render()
> 20 | return <p>hello</p>
| ^
21 |
22 | );
23 | </script>
ERROR in /home/scott/convrrt-component/view-play/src/App.vue(20,15):
20:15 Cannot find name 'hello'.
18 | ,*/
19 | render()
> 20 | return <p>hello</p>
| ^
21 |
22 | );
23 | </script>
Version: typescript 4.1.6
我想也许我需要明确地使用 h()
函数,所以我尝试了 render
函数(有点匹配 main.ts
正在做的事情):
render(h, ctx)
return h(<p>hello</p>)
那没有用。最后两个错误与上面相同,但第一个错误变为:
ERROR in /home/scott/convrrt-component/view-play/src/App.vue(20,14):
20:14 No overload matches this call.
Overload 1 of 2, '(tag?: string | VueConstructor<Vue> | FunctionalComponentOptions<any, PropsDefinition<any>> | ComponentOptions<never, any, any, any, any, Record<...>> | AsyncComponentPromise<...> | AsyncComponentFactory<...> | (() => Component<...>) | undefined, children?: VNodeChildren): VNode', gave the following error.
Argument of type 'boolean' is not assignable to parameter of type 'string | VueConstructor<Vue> | FunctionalComponentOptions<any, PropsDefinition<any>> | ComponentOptions<never, any, any, any, any, Record<...>> | AsyncComponentPromise<...> | AsyncComponentFactory<...> | (() => Component<...>) | undefined'.
Overload 2 of 2, '(tag?: string | VueConstructor<Vue> | FunctionalComponentOptions<any, PropsDefinition<any>> | ComponentOptions<never, any, any, any, any, Record<...>> | AsyncComponentPromise<...> | AsyncComponentFactory<...> | (() => Component<...>) | undefined, data?: VNodeData | undefined, children?: VNodeChildren): VNode', gave the following error.
Argument of type 'boolean' is not assignable to parameter of type 'string | VueConstructor<Vue> | FunctionalComponentOptions<any, PropsDefinition<any>> | ComponentOptions<never, any, any, any, any, Record<...>> | AsyncComponentPromise<...> | AsyncComponentFactory<...> | (() => Component<...>) | undefined'.
18 | ,*/
19 | render(h, ctx)
> 20 | return h(<p>hello</p>)
| ^
21 |
22 | );
23 | </script>
我尝试了其他一些我现在记不太清的事情(我认为,在函数本身和返回值上显式键入 render
是其中之一)。
问题:我仍然缺少什么设置/配置或者我有什么语法问题导致它仍然无法将 return
呈现为 JSX 并通过 TypeScript 挑战? p>
【问题讨论】:
【参考方案1】:JSX 默认启用
您无需在 Vue CLI 脚手架项目中安装任何 JSX 支持。
@vue/cli-plugin-babel/preset
includes @vue/babel-preset-app
,已经是includes @vue/babel-preset-jsx
。
将'@vue/babel-preset-jsx'
附加到 Babel 预设会引入错误(可能是由于默认情况下已经存在预设设置的重复)。你应该删除它:
module.exports =
presets: [
'@vue/cli-plugin-babel/preset',
// '@vue/babel-preset-jsx', // XXX: Remove this
],
;
VS 代码扩展警告
如果在 VS Code 中使用 Vetur 或 VueDX,您会注意到 JSX 行上报告的 TypeScript 错误。使用<script lang="tsx">
来避免这些错误:
<script lang="tsx">
import Vue from 'vue'
export default Vue.extend(
render()
return <b>hello</b>
)
</script>
【讨论】:
这解决了我的问题。谢谢!过分热衷于添加 JSX 支持,但没有意识到它是内置的。我很惊讶,因为我在构建中选择了“TypeScript”,它不会自动将lang="tsx"
分配给 script
标签。我相信实际上是缺少(仅是ts
)导致了错误。以上是关于让 Vue.js 从带有 JSX 包的基本 CLI 安装使用 TypeScript 渲染 JSX的主要内容,如果未能解决你的问题,请参考以下文章