Open gettinToasty opened 5 years ago
var h = this.$createElement
isn't added in transpiled functions automatically.
However in case of render I can just write render(h)
and it works. But in other functions I have to add this string manually to make it work.
Posted a question on stackoverflow as well.
@Alendorff not according to the features of this library:
Starting with version 3.4.0 we automatically inject
const h = this.$createElement
in any method and getter (not functions or arrow functions) declared in ES2015 syntax that has JSX so you can drop the (h) parameter.
@gettinToasty yes, sure, I expected this behavior, but that's not happened in my case. 🤷♂️ JSX works fine, TSX - not.
I would reccomend to look at https://github.com/kaorun343/vue-property-decorator and https://github.com/vuejs/vue-class-component, if you want to have component classes in TSX. At least check how they handle that.
We use vue-property-decorator
for our component classes, I don't think that's part of the issue here.
@healqq I didn't catch your point. At what exactly I should look? I use vue-property-decorator with TSX of course. It's quite hard to effectively utilize typescript in vue project without it.
@healqq by the way even in their example they added h
manually as an argument
@Alendorff that is just a bad(old) example, we’Re using it for our project and h is autoinjected. Other option would be to wait for vue3 release, but it’ll take some time
Can you post your tsconfig? Maybe the issue is there?
we have jsx: preserve
in our tsconfig so ts-loader shouldnt even touch it during compile
That's correct, yes. Maybe you can do minimal repo that replicates issue?
Hi,
this is a minimal example of how I resolve this issue. there are 4 approaches.
Test1.vue.ts
import { Vue, Component } from 'vue-property-decorator'
import { CreateElement, VNode } from 'vue';
import { render } from './Test1.vui';
@Component({})
export class Test1 extends Vue {
public message:string = 'hello world';
public render(h: CreateElement): VNode {
return render.bind(this)(h);
}
}
export default Test1;
Test1.vui.tsx
import { CreateElement, VNode } from 'vue';
import { Test1 } from './Test1.vue';
export function render(this: Test1, h: CreateElement): VNode {
return (
<div>
<h1>Title</h1>
{this.message}
</div>
);
}
add this rule to webpack
{
test: /\.tsx$/,
use: ['babel-loader', 'vue-jsx-hot-loader', 'ts-loader'],
exclude: /node_modules/
}
tsconfig.json
{
"compilerOptions": {
"lib": [
"dom",
"es6",
"es2015.promise"
],
"sourceMap": true,
"strict": true,
"module": "esnext",
"moduleResolution": "node",
"target": "es6",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowSyntheticDefaultImports": true,
"jsx": "preserve",
"jsxFactory": "h",
"typeRoots": ["./node_modules/@types", "./types"]
}
}
I hope it helps someone.
I got the same thing with rollup+tsx. If i use .vue all files works but with tsx h is not defined. Tried loy of babel presets but always got the same thing. BRRRRRRR....
// rollup config
import { RollupOptions, rollup } from 'rollup';
/* eslint-disable sort-imports-es6/sort-imports-es6 */
/* eslint-disable @typescript-eslint/no-var-requires */
import { join, resolve } from 'path';
import { BuildPackage } from '../build-package';
import { isObject } from '../utils';
import { terser } from 'rollup-plugin-terser';
const autoprefixer = require('autoprefixer');
const nodeResolve = require('rollup-plugin-node-resolve');
const vue = require('rollup-plugin-vue');
const babel = require('rollup-plugin-babel');
const cjs = require('rollup-plugin-commonjs');
const rollString = require('rollup-plugin-string');
const ts = require('rollup-plugin-typescript2');
const requireContext = require('rollup-plugin-require-context');
const { assign, keys } = Object;
const baseConfig = (settings: BuildPackage) => {
const {
options: { entryFile },
sourceDir
} = settings;
const pkg = require(join(sourceDir, 'package.json'));
/*const input = Array.isArray(entryFile)
? [...entryFile].map(file => join(sourceDir, file))
: join(sourceDir, entryFile);
*/
return {
external: [...keys(pkg.dependencies), ...keys(pkg.peerDependencies), ...['path', 'url']],
// inlineDynamicImports: true,
input: entryFile,
plugins: [
nodeResolve({
mainFields: ['main', 'module', 'browser'],
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue']
}),
cjs(),
requireContext(),
rollString.string({
include: '**/*.svg'
}),
vue({
css: false,
style: {
postcssPlugins: [autoprefixer]
},
compileTemplate: true
}),
ts({
cacheRoot: resolve(sourceDir, 'node_modules/.rts2_cache'),
tsconfig: join(sourceDir, 'tsconfig.build.json'),
tsconfigOverride: {
compilerOptions: {
declaration: true,
declarationDir: join(settings.outputDir, '@types'),
moduleResolution: 'node',
rootDir: settings.sourceDir
}
},
useTsconfigDeclarationDir: true
}),
babel({
// babelrc: false,
exclude: 'node_modules/**',
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
presets: [
[
'@babel/preset-env',
{
modules: false
}
],
//'@vue/babel-preset-jsx'
//'@vue/babel-preset-app'
'@vue/app'
],
include: [join(settings.sourceDir, '**/*')],
//plugins: ["transform-vue-jsx"],
/*plugins: [
"@babel/plugin-syntax-jsx",
["@babel/plugin-transform-react-jsx", { pragma : 'dom' }]
],*/
//externalHelpers: true,
runtimeHelpers: true
})
]
};
};
// compiled es format
import { __extends, __decorate, __metadata } from 'tslib';
import Vue from 'vue';
import { Component } from 'vue-property-decorator';
var UIButton =
/** @class */
function (_super) {
__extends(UIButton, _super);
function UIButton(props) {
return _super.call(this, props) || this;
}
UIButton.prototype.render = function (_h) {
return h("div", {
"attrs": {
"className": 'ui__button'
}
}, [h("button", ["Ok Button"])]);
};
UIButton = __decorate([Component({
name: 'ui-button'
}), __metadata("design:paramtypes", [Object])], UIButton);
return UIButton;
}(Vue);
export default UIButton;
// compiled umd format
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('tslib'), require('vue'), require('vue-property-decorator')) :
typeof define === 'function' && define.amd ? define(['exports', 'tslib', 'vue', 'vue-property-decorator'], factory) :
(global = global || self, factory(global.ui = {}, global.tslib, global.Vue, global.vuePropertyDecorator));
}(this, (function (exports, tslib, Vue, vuePropertyDecorator) { 'use strict';
Vue = Vue && Object.prototype.hasOwnProperty.call(Vue, 'default') ? Vue['default'] : Vue;
var UIButton =
/** @class */
function (_super) {
tslib.__extends(UIButton, _super);
function UIButton(props) {
return _super.call(this, props) || this;
}
UIButton.prototype.render = function (_h) {
return h("div", {
"attrs": {
"className": 'ui__button'
}
}, [h("button", ["Ok Button"])]);
};
UIButton = tslib.__decorate([vuePropertyDecorator.Component({
name: 'ui-button'
}), tslib.__metadata("design:paramtypes", [Object])], UIButton);
return UIButton;
}(Vue);
// eslint-disable-next-line sort-imports-es6/sort-imports-es6
/**
* Plugin install function
*
* @param vue - Vue Instance
* @param _options - Plubin Options
*
* @internal
*/
// eslint-disable-next-line id-match, @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
var install = function install(Vue, _options) {
Vue.component('ui-button', UIButton);
};
/**
* @public
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var plugin = {
install: install,
version: '1.0.0'
};
var GlobalVue = null;
if (typeof window !== 'undefined') {
GlobalVue = window.Vue;
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue;
}
if (GlobalVue) {
GlobalVue.use(plugin);
}
exports.UIButton = UIButton;
exports.plugin = plugin;
Object.defineProperty(exports, '__esModule', { value: true });
})));
When imported to a vue app created by cli always complain about h function. Any clues for Rollup+tsx??
May be a duplicate of https://github.com/vuejs/babel-plugin-transform-vue-jsx/issues/93
After configuring our
TsxComponent
class to properly allow babel to handle h auto-injection it appears that there is no actual injection happening in.tsx
files:TsxComponent
Implementation
Error