typescript - Vue: can't use render props with TSX
问题描述
In my setup jsx written inside vue component works correctly, then I migrate project on TS and use vue-class-component
.
The only thing which works with tsx for me is the following (as in example in repo)
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
@Component
export default class TSXTest extends Vue {
render(h) {
return <h1>It works</h1>
}
}
notice h
here - without it - it doesn't work, but should
I have a component which can accept render props. Looks like this:
// this is js component, so works even without `h` added manually
render() {
return (
<td>
{this.$props.render
? this.$props.render(this)
: this.defaultRender(this)}
</td>
)
}
In defaultRender some other jsx. And default works fine. But when I try to pass function with jsx, it doesn't work (in TSX, for common vue js based component it works perfect).
I used to have this jsx written inside my created hook. Like this:
created() {
this.columns = [
{
field: 'fieldWithCustomRenderFn',
label: 'Some name',
renderCell: ({ row }) => (
<div onClick={() => this.someHandler(row)}>
{row.someData}
</div>
)
}
]
}
Notice that I don't have to pass h
here somehow. It works in JS - but doesn't work in TSX. Have no idea why...
When it's transpiled it looks like this:
renderCell: function renderCell(_a) {
var row = _a.row
return h('a', {
on: {
'click': function click(e) {
_this.someHandler(row)
}
}
}, [row.someData])
}
Indeed, jsx is transformed, but h
is undefined here. I saw transpiled code from js (which works) and the key difference as for me is that line:
var h = this.$createElement;
inside created() function. I don't see this line in transpiled code for my tsx component. What I do wrong here?
Here is my .babelrc (I use babel 6)
"presets": [
["env", {
"modules": "commonjs",
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 11"]
}
}],
"stage-2"
],
"plugins": [
"syntax-dynamic-import",
"transform-vue-jsx",
"transform-runtime"
],
And webpack rules
{
test: /\.ts$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
transpileOnly: true
}
},
{
test: /\.tsx$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
},
{
loader: 'ts-loader',
options: {
transpileOnly: true
}
}
]
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
)
},
解决方案
That looks like a known issue with babel-plugin-transform-vue-jsx. I solved this just by adding this string manually inside my function with jsx:
const h = this.$createElement;
And it works as it should in terms that it compiles and works fine. But of course it's just a crutch.
推荐阅读
- laravel - 如何更改 Laravel Sanctum 网址前缀?
- c# - 从 .Net 4 迁移到 5 会更改构建任务行为,并且不会将“中间输出”生成的资源包含到 dll 中
- typescript - 无法使用 PassportJS 读取未定义、NestJS 的属性“validateUser”
- javascript - 无法读取未定义的属性“ajaxSetup”
- python - FileNotFoundError:[Errno 2] 没有这样的文件或目录:'/mytrigger\xa0_init__.py'
- node.js - 是否可以使用节点 SDK 打包 Hyperledger Fabric 链码?
- rust - 为什么 read_line 不改变它的论点?
- ffmpeg - 使用ffmpeg为视频加水印时如何将特殊字符作为文本包含在内?
- python-3.x - 在第一个空白行将 CSV 上传到谷歌表格
- python - 如何在不添加子列表的情况下将键值对添加到列表中?