Vue - это потрясающий фреймворк, который уже довольно давно набирает популярность в сообществе Open Source. Он заимствует (или крадет, в зависимости от того, кого вы спросите) некоторые из лучших функций самых популярных на сегодняшний день фреймворков, включая Angular, Polymer и React. Одной из таких функций, взятых из React, является возможность писать разметку для компонентов с использованием JSX.
TypeScript - не менее потрясающий надмножество JavaScript, предназначенное для добавления в язык необязательной статической типизации. Это также добавляет большую ценность в виде TSX или Typed JSX. В этой статье описывается, как получить лучшее из обоих миров: написание компонентов Vue с использованием TypeScript и TSX.
Если вы освоили искусство чтения кода, вот исходный код.
Установка
Выполните следующие команды в корне проекта:
# Install through NPM... npm i vue vue-class-component vue-property-decorator npm i babel-core babel-plugin-jsx-v-model babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-preset-latest fuse-box typescript -D # ... or Yarn yarn add vue vue-class-component vue-property-decorator yarn add babel-core babel-plugin-jsx-v-model babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-preset-latest fuse-box typescript -D
Я не буду вдаваться в подробности того, что делают все эти зависимости, но наиболее важные из них, которые вы не часто видите:
- блок предохранителей - наш чрезвычайно быстрый и простой упаковщик
- vue-property-decorator - некоторые декораторы, упрощающие определение компонентов, свойств и т. д.
- babel-plugin-transform-vue-jsx - преобразует наш Vue JSX для использования функции createElement Vue. Эта функция немного отличается от React.
Конфигурация
Для краткости, единственными двумя частями, используемыми для настройки, будут файлы tsconfig.json и fuse.js. Создайте файл tsconfig.json и добавьте следующее:
{ "compilerOptions": { "target": "es2015", "module": "commonjs", "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "lib": [ "es2016", "dom" ], "jsx": "preserve", "noUnusedLocals": true, "noUnusedParameters": true } }
Здесь важно отметить сохранение JSX. Это сделано для того, чтобы Babel мог обрабатывать JSX-транспиляцию.
Затем создайте файл fuse.js и добавьте следующее:
const { FuseBox, BabelPlugin, WebIndexPlugin } = require('fuse-box') const fuse = FuseBox.init({ sourceMaps: true, homeDir: './src', output: 'dist/$name.js', plugins: [ BabelPlugin({ config: { presets: ['latest'], plugins: ['jsx-v-model', 'transform-vue-jsx'] } }), WebIndexPlugin({ template: './src/index.html' }) ] }) fuse.dev() fuse.bundle('app.js').instructions('>index.ts').watch() fuse.run()
Обратите внимание на использование плагина transform-vue-jsx, описанного ранее. Если вы не знакомы с FuseBox, прочтите об этом здесь. Это должно быть довольно просто, особенно если вы знакомы с webpack.
Написание некоторых компонентов
Завершив настройку, создайте компонент в src / components. Назовите его App.tsx и добавьте следующее:
import * as Vue from 'vue' import { Component, Watch } from 'vue-property-decorator' @Component export default class extends Vue { text = '' render() { return ( <div> <input type="text" placeholder="Input your name" v-model={this.text} /> </div> ) } @Watch('text') onInput() { console.log(this.text) } }
Если вы не знакомы с vue-property-decorator, в этой статье есть отличное объяснение его использования. Декоратор Component
используется для определения компонента Vue, а декоратор Watch
используется для подписки на изменения свойства text
. Также обратите внимание на использование v-model
. Было бы невозможно использовать плагин jsx-v-model.
В каталоге src создайте файлы index.ts и index.html. Добавьте в index.ts следующее:
import App from './components/App' import * as Vue from 'vue' new Vue({ el: 'main', render: h => h(App) })
А затем добавьте код в index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Vue TSX Example</title> </head> <body> <main></main> $bundles </body> </html>
Теперь мы можем запустить наше приложение с помощью node fuse.js
и получить быструю победу.
Вы также должны увидеть текст, введенный в поле ввода в консоли браузера.
Теперь давайте немного продвинемся и добавим в пример дочерний компонент. Создайте еще один компонент под названием Hello.tsx и добавьте следующее:
import * as Vue from 'vue' import { Component, Prop } from 'vue-property-decorator' @Component export default class extends Vue { @Prop() name render() { if (this.name) return ( <div> Hello {this.name}!!! </div> ) return <div>What's your name?</div> } }
Синтаксис должен быть похож на App.tsx. Незначительная разница заключается в использовании декоратора Prop
. Это позволяет компоненту получать свойство имени от своего родителя.
Наконец, измените App.tsx, чтобы он выглядел следующим образом:
import * as Vue from 'vue' import { Component, Watch } from 'vue-property-decorator' import Hello from './Hello' @Component export default class extends Vue { text = 'World' render() { return ( <div> <Hello name={this.text} /> <input type="text" placeholder="Input your name" v-model={this.text} /> </div> ) } @Watch('text') onInput() { console.log(this.text) } }
После добавления компонента Hello в функцию рендеринга обновите страницу в браузере, и вы увидите следующее:
Заключение
Подход использования Vue с файлами .tsx - это отклонение от нормы, но это также идеальный союз, который сохраняет неизменной цель Vue, связанную с одним файлом, при этом оставляя небольшой багаж на этом пути (шаблон / скрипт / style теги и т.п.).
Надеюсь, вы сочтете эту статью полезной. Теперь у вас есть полностью работающий пример со всем, что вам нужно, чтобы быть по-настоящему опасным. Удачных трасс !!!
Источники
Написание функций рендеринга Vue.js на JSX
Используйте тонкости шаблона Vue.js в компонентах JSX
Написание компонентов на основе классов с помощью Vue.js и TypeScript