[TypeScript] Vue.jsをTypeScriptで使ってみたい2

2016/08/10

こんにちは。きんくまです。

前回、Vue.jsをTypeScriptで使ってみたいという記事を書いたのですが、あのやり方でコンポーネントを作ろうとするとうまくいかなかったので、もう一回ちゃんと調べてみました。

こんな感じのができます(画像のみで動きません)
vue_typescript_demo

できたもののソース
>> KinkumaDesign/vue-typescript-sample-project

– vue-typescriptというのを使った
– gulp-typescriptでビルド
– webpackを使用
– typingsを使用
– tsconfig.jsonを使用

これまでtsifyを使っていたのですが、いろいろとうまくいかなかったので、最近の構成を試してみました。

vue-typescriptというのは、このスレッドの最後の方に出てくる方が作ったものです。
>> Typescript and Vue in general #478

github
>> itsFrank/vue-typescript

TypeScriptにはデコレーターという機能があるらしく、これを使うとコンパイル時にマクロみたいなことをやってくれるみたいです。

できたソースhtml

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/main.css">
    <title>Document</title>
</head>
<body>

<template id="child-template">
    <input v-model="msg">
    <button v-on:click="notify">Dispatch Event</button>
</template>

<template id="events-example">
    <p>Messages: {{ messages | json }}</p>
    <child></child>
</template>

<div id="app_root">
    <app></app>
</div>

<script src="js/main.js"></script>
</body>
</html>

子供コンポーネント ChildComponent.ts

import * as Vue from 'vue'
import { VueComponent } from 'vue-typescript'

@VueComponent({
    template:'#child-template'
})
export class ChildComponent extends Vue {
    msg:string = "hello";
    notify(){
        if(this.msg.trim()){
            this.$dispatch('child-msg', this.msg);
            this.msg = '';
        }
    }
}

メインコンポーネント ApplicationMain.ts

/// <reference path="../../../typings/index.d.ts" />

import * as Vue from 'vue'
import { ChildComponent } from './child/ChildComponent'
import { VueComponent, Prop } from 'vue-typescript'

@VueComponent('app', {
    template:'#events-example',
    events:{
        'child-msg': function(msg){
            this.addMessage(msg);
        }
    },
    components:{
        'child':ChildComponent
    }
})
export default class ApplicationMain extends Vue {
    messages:string[] = [];

    constructor(){
        super();
    }

    addMessage(msg){
        this.messages.push(msg);
    }
}

(function(){
    new Vue({
        el:'#app_root'
    })
})();

– コンポーネント単位にファイル分割
– 子供から親へイベント送信
– 親がうけとって何かする

あたりは確認できたので、なんかうまくいけそうな気が、、。

あと、最近の環境構築についてはこちらの方の記事がすごく助かりました。

>> TypeScript, React, Sass, webpack, gulp導入記 – モダンなクライアントサイドWeb開発に挑戦した話

どうも最近のjsの流れとしては、こういう感じに再利用可能なコンポーネントを作ってそれを組み合わせて作っていくってやつみたいですね。なるほど。

=====
2016/08/11追記

その後、コンポーネントのhtmlをいくつかのファイルに分割しようとしたところで詰まってしまった。
一応公式でサポートされている promiseっぽい書き方の resolveを使うやりかたがありました。

Vue.component('my-component', function (resolve, reject) {
  $.get('mycomponent.html', function (res) {
  	$('body').append(res);
    resolve({
      template: '#mycomponent_id'
    })
  });
})

が、これがTypeScriptで実現しようとすると、また無理が生じるということに、、。

– TypeScriptで普通にVueオブジェクトをextendできない(公式でないvue-typescriptを使う必要がある)
– htmlを分割したときTypeScriptだと難しい

という理由から VueをTypeScriptで使うというのはあきらめることにしました。

ためしに、ReactでTypeScriptをやってみたところ、コンポーネントごとにファイルを分割してクラスを作ってレンダリングするというところまでは、比較的すぐにできました。
あとは、ここからどうやって各コンポーネントを連携したり、データをどうやって扱うかについて調べてみようと思います。

ただReactだとプログラムの中にDOMを書いていくのがあんまり好きじゃないという、好みの問題もあるのですが、TypeScriptと一緒に使ってしまうと、DOMをいじったあとに確認するのに、毎回ビルドする必要があるんですよね。

そうなったときに、プログラマじゃないデザイナーさんが確認しづらくなるっていう点があるかと思っています。(デザイナーさんにTypeScriptのビルド環境をちゃんと構築してっていうのも、、。npmやgulpがあるとはいえ。うーん)

なんか、こうやって書いているとTypeScript自体が重荷になっている気がするけど、どうなんだろ。
やったことないんだけど、ES2015 + babel の構成の方が柔軟になるのかな。でもあっちも結局はビルドするしな。うーん。


自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る