まだ書いてないけど
もやもやポイント書き出し
TypeScriptでVue.jsを使うサンプル(前半)
【計画】前半と後半に分ける
前半
プロジェクトの作成と簡単なアプリ作成
後半
vue-router組み込み
主要な使用技術
- TypeScript 1.6.2
- vue 1.0.8
- vue-router 0.7.5
- vue-class-component 2.0.0
- TypescriptのコンパイルオプションはES6
大まかな手順
- プロジェクト作成と環境の準備
- TypeScriptまわりの準備
- vueの簡単なサンプル作り
- vue-router挑戦
プロジェクト作成と環境の準備
# ディレクトリ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir build
mkdir -p src/{components,views,assets,directives,filters}
mkdir src/assets/js
# npm で必要なものをあつめてくる
npm init
npm i -g webpack webpack-dev-server mocha typescript tsd tslint
npm i -S vue vue-class-component vue-router
npm i -D babel-loader@^5.3 webpack style-loader css-loader sass-loader ts-loader html-loader typescript tsd tslint-loader mocha mocha-loader chai
# tsd で必要なものを集めてくる
tsd init
tsd install vue --save
tsd install require --save
# tslint用の定義ファイルをテンプレートからコピってくる。しかしこれ厳しすぎてつらいので適宜ゆるく改修する必要あり
cp ./node_modules/tslint-loader/node_modules/tslint/docs/sample.tslint.json ./tslint.json
webpack.config.jsの作成
module.exports = {
entry: {
app: "./src/assets/js/entry.ts"
},
output: {
path: './build/js',
publicPath: '/js/',
filename: "[name].js"
},
resolve: {
alias: {
vue: "vue/dist/vue"
},
modulesDirectories: ['node_modules', 'src/', 'src/assets/js/', 'src/views/', 'src/components/'],
// require()するときに拡張子を省略可能にします
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js']
},
devServer: {
contentBase: "./build",
},
module: {
preloaders: [
{
test: /\.ts$/,
loader: "tslint"
}
],
loaders: [
{
test: /\.scss$/,
loader: "style!css!sass"
},
{
test: /\.html$/,
loader: "html"
},
{
test: /\.ts(x?)$/,
loader: 'babel-loader?sourceMaps=true!ts-loader'
}
]
}
};
tsconfig.jsonを作成する
{
"compilerOptions": {
"module": "commonjs",
"removeComments": true,
"noImplicitAny": false,
"target": "es6",
"sourceMap": true,
"experimentalDecorators": true,
"preserveConstEnums": true
},
"exclude": [
"node_modules",
"build"
]
}
src/assets/js/にentry.tsを作成
console.log("hello");
/build/index.htmlを作成
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample</title>
</head>
<body>
<div id="app">this is app</div>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
ここで一旦、webpack-dev-serverを起動してプレビュー
起動コマンド : webpack-dev-server -d --inline
http://localhost:8080
コンソールにhelloと表示されたらここまでOK
横道:IntelliJ使ってる場合の設定
Preferences->Languages & Frameworks->JavaScript
- JavaScript language version を「ECMAScript 6」にする
Preferences->Languages & Frameworks->TypeScript
- Enable TypeScript Compilerをチェックする(重かったらチェック外してもいいかも)
- コマンドラインオプション
--noImplicitAny --target ES6 --experimentalDecorators
- generate sourceMapのチェックをはずす。
Preferences->Languages & Frameworks->TypeScript->Tslint
- プロジェクトのtslint.jsonを設定する
横道から復帰
TypeScriptまわりの準備
typingsの中にあるvue.d.tsの中でexport =
とある部分をexport default
と書き換える
※es6を使うときに怒られちゃうからこれでごまかす。。。
独自定義ファイルディレクトリを作る
mkdir -p custom-typings/vue-class-component
custom-typings/vue-class-component/vue-class-component.d.tsを作る(これでいいのか不明)
declare module "vue-class-component" {
let VueComponent:ClassDecorator;
export default VueComponent;
}
custom-typings/custom.d.tsを作る
/// <reference path="vue-class-component/vue-class-component.d.ts" />
vueの簡単なサンプル作り
src/assets/js/entry.tsを書き換え
/// <reference path="../../../typings/tsd.d.ts" />
import Vue from "vue";
require("../sass/main.scss");
new Vue(require("../../views/app"));
src/assets/sass/main.scss作成(てきとー)
body {
margin: 0px;
padding: 0px;
}
.main-header {
margin: 0px;
padding: 3px;
background-color: #fafafa;
border-bottom: 1px solid #CCCCCC;
text-align: center;
}
.main-footer {
position: fixed;
width: 100%;
margin: 0px;
padding: 3px;
background-color: #fafafa;
border-top: 1px solid #CCCCCC;
bottom: 0px;
}
src/views/app/index.tsを作成
/// <reference path="../../../typings/tsd.d.ts" />
import Vue from "vue";
import Header from "../../components/header/index";
const app = new Vue({
el: "#app",
template: require('./template.html'),
components: {
'app-header': Header
}
});
src/views/app/template.htmlを作成
<app-header></app-header>
src/components/header/index.tsを作成
/// <reference path="../../../typings/tsd.d.ts" />
/// <reference path="../../../custom-typings/custom.d.ts" />
import VueComponent from "vue-class-component";
@VueComponent
export default class Header {
public static template:string = require("./template.html");
public ready():void {
console.log("hogehoge");
}
}
src/component/header/template.html
<div class="main-header">
<h3>TypeScript & Vue.js sample</h3>
</div>
サーバを起動して動作確認する。ヘッダーが表示されていればここまでOK
横道2 ChromeのVue Devtoolsについて
能力の無さは積極的にツールでカバーしたい。ということで便利ツールのChromeのプラグイン「Vue Devtools」
webpackの起動オプションに--inlineを設定してあったり、babel-loaderかますときにsourceMapつけてるのはこのツールを使えるようにするためです。
このプラグインのおかげで表示されているコンポーネントの情報をブラウザで実行時に見ることができます。
chrome上でブレイクポイント置いてステップ実行できるようになるものも相当嬉しい(それはVue Devtoolsの機能じゃないけど)
TypeScriptでvue-class-componentを使ってみる
追記:書き直した->
http://kurokokoruru.hatenablog.com/entry/2015/11/14/131304
以下のこと書くメモ
- Vue.jsでコンポーネントベースで開発する
- TypeScriptでvue-class-componentを使ってみる
- sass使う
- gulpなしwebpackのみ
環境構築手順(mac) 2015/11/4
- ディレクトリを用意する
- npmの初期化&必要なものをインストール
- ビルドの設定
- ヘッダーコンポーネント定義&設置
- todoAppをクラスベースに書き換えると
vue-class-componentについて
ES7/TypeScript向けにクラスベースでコンポーネントを定義するためのもの
https://github.com/vuejs/vue-class-component
TypeScriptの1.5.0-alphaから利用可能になったDecoratorを利用している。
環境構築手順詳細(mac)2015/11/4
ディレクトリを用意する
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir build
mkdir -p src/{components,views,assets,directives,filters}
mkdir src/assets/js
npmの初期化&必要なものをインストール
npm init
npm i -g webpack webpack-dev-server mocha typescript tsd tslint
npm i -S vue vue-class-component
npm i -D webpack style-loader css-loader sass-loader ts-loader html-loader typescript tsd tslint-loader mocha mocha-loader chai
cp ./node_modules/tslint-loader/node_modules/tslint/docs/sample.tslint.json ./tslint.json
// ターミナルで定義ファイルのインストール
tsd init
tsd install vue --save
tsd query require -so -a install
ビルドの設定
webpack.config.js
module.exports = {
entry: {
app: "./src/assets/js/entry.js"
},
output: {
path: './build/js',
publicPath: '/js/',
filename: "[name].js"
},
devtool: "source-map", // source-mapを生成する
module: {
preloaders: [
{
test: /\.ts$/,
loader: "tslint"
}
],
loaders: [
{
test: /\.scss$/,
loader: "style!css!sass"
},
{
test: /\.html$/,
loader: "html"
},
{
test: /\.ts$/,
loader: "ts-loader"
}
]
},
resolve: {
// require()するときに拡張子を省略可能にします
extensions: ['', '.js', '.scss']
}
};
src/assets/js/にentry.tsを作成
console.log("hello");
/build/index.htmlを作成
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample</title>
</head>
<body>
<div id="app">this is app</div>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
webpack-dev-serverを起動してプレビュー
http://localhost:8080/webpack-dev-server/
// コンソールで"hello"の文字が出力されてればここまでOK
ヘッダーコンポーネント定義&設置
src/assets/js/entry.tsを書き換え
/// <reference path="../../../typings/tsd.d.ts" />
import Vue = require('vue');
require('../sass/main');
new Vue(require('../../views/app'));
src/assets/sass/main.scss作成(てきとー)
body {
margin: 0px;
padding: 0px;
}
.main-header {
margin: 0px;
padding: 3px;
background-color: #fafafa;
border-bottom: 1px solid #CCCCCC;
text-align: center;
}
.main-footer {
position: fixed;
width: 100%;
margin: 0px;
padding: 3px;
background-color: #fafafa;
border-top: 1px solid #CCCCCC;
bottom: 0px;
}
src/views/app/index.tsを作成
/// <reference path="../../../typings/tsd.d.ts" />
import Vue = require('vue');
var app = new Vue({
el: "#app",
template: require('./template.html'),
components: {
'app-header': require('../../components/header').Header
}
});
src/views/app/template.htmlを作成
<app-header></app-header>
src/components/header/index.tsを作成
/// <reference path="../../../typings/tsd.d.ts" />
import VueComponent = require('vue-class-component');
@VueComponent
export class Header {
static template = require("./template.html");
ready() {
console.log('hogehoge');
}
}
src/component/header/template.html
<div class="main-header">
<h3>TypeScript & Vue.js sample</h3>
</div>
ここでプレビュー画面にヘッダーが表示されてればOK.
あとのコンポーネント追加は同じことの繰り返しなので割愛。
todoAppをクラスベースで書き換えると
先日エントリのTodoアプリのコンポーネントかつクラスベース版
/// <reference path="../../../typings/tsd.d.ts" />
import VueComponent = require('vue-class-component');
interface ITask {
body: string;
done: boolean;
}
@VueComponent
export class TodoApp {
tasks:ITask[];
newTaskBody = '';
static template = require('./template.html');
data() {
return {
tasks: this.tasks,
newTaskBody: this.newTaskBody
}
}
get computedDoneCount() {
return this.getDoneCount();
}
created () {
this.tasks = [
{body: 'do this 1', done: false},
{body: 'do this 2', done: false},
{body: 'do this 3', done: false},
{body: 'do this 4', done: false}
]
}
addNew():void {
console.log("addNew");
var task:string = this.newTaskBody && this.newTaskBody.trim();
if (!task) {
return;
}
this.tasks.push({body: task, done: false});
this.newTaskBody = '';
}
deleteTask(delIndex:number):void {
console.log("deleteTask");
this.tasks.splice(delIndex, 1);
}
deleteDone():void {
console.log("deleteDone");
var oldTasks = this.tasks;
this.tasks = [];
oldTasks.forEach(task => {
if (!task.done) this.tasks.push(task);
});
}
getDoneCount():number {
var count = 0;
this.tasks.forEach(task => {
count += task.done ? 1 : 0;
});
return count;
}
}
うーん。良い。
定義ファイル(d.ts)について
d.tsファイルの作り方がよくわからない。
declare module "vue-class-component" {
var VueComponent:ClassDecorator;
export default VueComponent;
}
このようなものを用意したが、export defaultはES6の書き方だ。。
他にもTypeScriptがらみでintellij上で怒られるのを回避しないと行けないので課題多し。
あと、実際にやってから一週間ほど経っているのでもうすでに情報が古いかも。。
追記
- そのままやるとbabelの6が入ってしまって動かない
- tsのコンパイルはIntelliJがやっててそれで動いてたみたい。ほかのエディタじゃ動かないはず
- tsconfig.jsonとか用意しないとね!
- 一応拡張子はtsだけど、とくにTypeScriptの利点が生かされてない
ってことで近いうちに書き直す
もやもやポイント書き出し
今週分のもやもや
- export, import, requireまわりが混乱してきた。整理したい。ES6, commonjs, amd, TypeScript(内部,外部)
- TypeScriptを使ったVue.jsのコンポーネント化が思ってたよりうまくいかない。整理したい
- Vue.jsはES6で書いたほうがすっきりしてて良いのかも・・・でも型ほしい。ES7かな・・・いやいやいや
- lodashとかいうjsの便利屋さんが学習でソース読むのによさそーだなー
- vue-class-componentなどというVue.js作者さんが書いたらしきものがヒントにならないかなぁー。
vuejs/vue-class-component · GitHub
はー。。。ハロウィンなのに外出するのヤダなぁ。
仮装して気が大きくなっちゃってる変な人に絡まれませんように
TypescriptとVue.js 1.0系とwebpackと
TypeScriptプロジェクト作成メモ
このメモについて
まだtypescriptについての予備知識はないので基本トライアンドエラー
最終目標目標設定
以下の条件の最小限の開発環境の準備
- typescript
- vue.js 1.0系
- webpack
- sass
プロジェクトのフォルダ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir build
mkdir -p src/{components,views,assets,directives,filters}
mkdir src/assets/js
npmの初期化と準備
npm init
npm i -g webpack webpack-dev-server mocha typescript tsd
npm i -D webpack style-loader css-loader sass-loader ts-loader tsd tslint-loader mocha mocha-loader chai vue html-loader
cp ./node_modules/tslint-loader/node_modules/tslint/docs/sample.tslint.json ./tslint.json
// ターミナルで定義ファイルのインストール
tsd init
tsd install vue --save
tsd query require -so -a install
簡単なビルドができるようになるために
webpack.config.jsを作成
module.exports = {
entry: {
app: "./src/assets/js/entry.js"
},
output: {
path: './build/js',
publicPath: '/js/',
filename: "[name].js"
},
devtool: "source-map", // source-mapを生成する
module: {
preloaders: [
{
test: /\.ts$/,
loader: "tslint"
}
],
loaders: [
{
test: /\.scss$/,
loader: "style!css!sass"
},
{
test: /\.html$/,
loader: "html"
},
{
test: /\.ts$/,
loader: "ts"
}
]
},
resolve: {
// require()するときに拡張子を省略可能にします
extensions: ['', '.js', '.scss', '.ts']
}
};
src/assets/js/にentry.tsを作成
console.log("hello");
ターミナルでwebpackを実行 -> build/jsにapp.jsができていることを確認する
/build/index.htmlを作成
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample</title>
</head>
<body>
<div id="app">this is app</div>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
webpack-dev-serverを起動してプレビュー url: http://localhost:8080/webpack-dev-server/
webpack-dev-server --content-base build/ -d
// コンソールで"hello"の文字が出力されてればここまでOK
vue.jsを入れてってみよう
src/assets/js/entry.tsを書き換えてwebpack-dev-serverでプレビューしてみる
/// <reference path="../../../typings/tsd.d.ts" />
console.log("hello");
var Vue = require('vue');
new Vue({
el: "#app",
data: {
msg: "message"
},
template: "<p>hoge{{msg}}</p>"
});
TODOアプリがちゃんと動くようにする
IntelliJ->Preferences->Languages & Frameworks->Typescript->command line options
ここに「--sourcemap --noImplicitAny --target es5 --module commonjs」と入れる
Error:Error has occurred in the compile process TypeError: host.fileExists is not a function
このエラーがどうやっても取れない。どうすればいいんだろう???????
IntelliJ->Preferences->Languages & Frameworks->Typescript->Compiler version をカスタマイズすると下の問題に遭遇することがあるようです。
当方はtypescript をbundleされている1.4から1.6.2にあげたら起きました。
TODOアプリの実装をする(コピペするだけ)
build/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample</title>
<style>
.done-true{
color: gray;
text-decoration: line-through;
}
</style>
</head>
<body>
<div class="todoapp">
<h1>vue & typescript</h1>
<p>Finish Task: {{getDoneCount}} / {{ tasks.length}}</p>
<button @click="deleteDone">Delete Finished</button>
<ul>
<li v-for="task in tasks">
<input type="checkbox" v-model="task.done" />
<span class="done-{{task.done}}">{{$index}}:{{task.body}}</span>
<a href="#" @click="deleteTask($index)">[x]</a>
</li>
</ul>
<form onsubmit="return false;" @submit="addNew">
<input type="text" v-model="newTaskBody" />
<input type="submit" value="add">
</form>
</div>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
src/assets/js/entry.ts
/// <reference path="../../../typings/tsd.d.ts" />
import Vue = require('vue');
interface ITask {
body: string;
done: boolean;
}
class TodoApp extends Vue {
tasks:ITask[];
newTaskBody = '';
constructor() {
super(false);
this._init({
el: '.todoapp',
data: {
tasks: this.tasks,
newTaskBody: this.newTaskBody
},
computed: {
getDoneCount: this.getDoneCount
},
created: () => {
this.tasks = [
{body: 'do this 1', done: false},
{body: 'do this 2', done: false},
{body: 'do this 3', done: false},
{body: 'do this 4', done: false}
]
},
methods: {
addNew: this.addNew,
deleteTask: this.deleteTask,
deleteDone: this.deleteDone
}
});
}
addNew():void {
console.log("addNew");
var task:string = this.newTaskBody && this.newTaskBody.trim();
if (!task) {
return;
}
this.tasks.push({body: task, done: false});
this.newTaskBody = '';
}
deleteTask(delIndex:number):void {
console.log("deleteTask");
this.tasks.splice(delIndex, 1);
}
deleteDone():void {
console.log("deleteDone");
var oldTasks = this.tasks;
this.tasks = [];
oldTasks.forEach(task => {
if (!task.done) this.tasks.push(task);
});
}
getDoneCount():number {
var count = 0;
this.tasks.forEach(task => {
count += task.done ? 1 : 0;
});
return count;
}
}
export var todoApp = new TodoApp();
webpack-dev-serverを起動して動作を確認する -> 動いていればOK
これからのこのメモに関するTODO
- モジュールをちゃんと分割してみる
- sassの設定
- ハシゴはずされるかもしれないけどvue-routerでroutingしてみたい