Становится Vue.js чтобы отобразить JSX с помощью машинописного текста из базового интерфейса командной строки, установите пакет JSX

#typescript #vue.js #jsx #rendering #vue-cli

Вопрос:

Настройка

Я создал базовый проект с vue-cli, в ходе которого я использовал «Функции выбора вручную» для установки, где я выбрал следующее (помимо линтера):

  • Выбран Бабель, машинопись, Vuex и Линтер / Форматер
  • Выбрано 2.x
  • Нет компонентам классового стиля
  • Да, чтобы использовать Babel вместе с машинописным текстом (требуется для современного режима, автоматически обнаруживаемых заполнений, переноса JSX)?

Затем я также установил поддержку jsx (и я подтвердил, что установленная версия Babel была 7, так как это требуется для этого репозитория поддержки jsx).

В моем bable.config.js файл, который я добавил (не заменил то, что было сгенерировано vue-cli), предустановленный, запрошенный репо jsx:

 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
    }
  }
}
 

В полученном автоматически сгенерированном файле 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 alt="Vue logo" 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>
 

The Issues

It is my understanding that the following modification to App.vue should then work (the render function is exactly what the first «Syntax» example in the jsx repo has):

 // 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>
 

But instead, I get this set of errors in the terminal window:

 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 и передать перчатку машинописи?

Ответ №1:

JSX включен по умолчанию

Вам не нужно ничего устанавливать для поддержки JSX в проекте, построенном на основе Vue CLI. @vue/cli-plugin-babel/preset включает @vue/babel-preset-app в себя , что уже включает @vue/babel-preset-jsx в себя .

Добавление '@vue/babel-preset-jsx' предустановок Babel приводит к ошибкам (вероятно, из-за дублирования предустановленных настроек, уже установленных по умолчанию). Вам следует удалить это:

 module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    // '@vue/babel-preset-jsx', // XXX: Remove this
  ],
};
 

Предостережение против расширений кода

При использовании Vetur или VueDX в коде VS вы заметите ошибки машинописи, о которых сообщается в строках JSX. Используйте <script lang="tsx"> , чтобы избежать этих ошибок:

 <script lang="tsx">
import Vue from 'vue'

export default Vue.extend({
  render() {
    return <b>hello</b>
  }
})
</script>
 

Комментарии:

1. Это решило мои проблемы. Спасибо! Слишком усердно добавлял поддержку JSX, не понимая, что она была встроена. Я удивлен, что с тех пор, как я выбрал «Машинопись» в сборке, она просто не присваивается lang="tsx" тегам автоматически script . Я считаю, что на самом деле именно отсутствие ( ts только наличие) было причиной ошибок.