Skip to content
This repository has been archived by the owner on Jun 23, 2020. It is now read-only.

MeetehS/vue-class-ts

Repository files navigation

vue-class-ts

Coding Vue happier with Class and TypeScript.

VueClassTs is a good helper for you to use Vue with Class and TypeScript, it's supported by vue-class-component, vue-property-decorator and vue-tsx-support

Usage

Install

npm install vue-class-ts

Config TypeScript with webpack

Install devDependencies

npm install --save-dev typescript ts-loader babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props babel-preset-env

TypeScript config: tsconfig.json

{
  "include": [
    "./src/**/*",
    "./types/**/*",
    "./node_modules/vue-class-ts/types/enable-tsx-check.d.ts" // Enable tsx check
  ],
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "es2018", "scripthost"],
    "strict": true,
    "module": "esNext",
    "moduleResolution": "node",
    "sourceMap": true,
    "types": ["node"],
    "experimentalDecorators": true,
    "jsx": "preserve" // Enable tsx
  }
}
Reference

webpack config

Add this to your vue webpack config

{
  module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/],
        },
      },
      {
        test: /\.tsx$/,
        exclude: /node_modules/,
        use: [
          'babel-loader', // Transform vue jsx with babel
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [/\.vue$/],
            },
          },
        ],
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.vue', '.ts', '.tsx'],
  },
}
Reference

babel config

{
  "presets": ["env"],
  "plugins": ["transform-vue-jsx"]
}

types/vue-shims.d.ts

declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}
Reference

Write your first vue component with tsx

src/components/NavBar/index.tsx

import Vue, { CreateElement } from 'vue'
import { ClassComponent, Component, Emit } from 'vue-class-ts'

import BackButton from '../BackButton'
import StatusBar from '../StatusBar'

import template from './template.vue'

export enum Mode {
  Dark = 'dark',
  Light = 'light',
}

interface IProps {
  mode?: Mode,
}

@ClassComponent({
  mixins: [template],

  props: {
    mode: {
      type: String,
      default: Mode.Dark,
    },
  },
})
export default class NavBar extends Component<IProps> {
  @Emit()
  public back() {
    return
  }

  private render(h: CreateElement) {
    return (
      <div>
        <StatusBar />

        <div class={this.navBarClass}>
          <div class="left">
            <BackButton mode={this.$props.mode} onClick={this.back} />
          </div>
          <div class="middle">
            {this.$slots.default}
          </div>
          <div class="right">

          </div>
        </div>
      </div>
    )
  }

  private get navBarClass() {
    return {
      RealNavBar: true,
      darkMode: this.$props.mode === Mode.Dark,
      lightMode: this.$props.mode === Mode.Light,
    }
  }
}

src/components/NavBar/template.vue

<style scoped>
  .RealNavBar {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 44px;
    font-size: 18px;
    line-height: 20px;
    font-weight: 500;
  }

  .darkMode {
    background: white;
    color: #333; 
  }

  .lightMode {
    background: transparent;
    color: white;
  }

  .left,
  .middle,
  .right {
    display: flex;
    flex: 1;
    height: 100%;
    align-items: center;
  }

  .middle {
    justify-content: center;
  }
</style>

Mixins

Mixins