かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Vue.js の勉強メモ 2 (TypeScript で!)

今回は TypeScript あんまり関係ないんですが、Vue.js は既存サイトに少しずつ適用可能と書いてあるじゃないですか。 これがどういうことなのかというのを試してみました。

本当に書きながらやってるのでまとまりありませんが、学習ログってことで。

プロジェクト作成

例えば、超シンプルですが以下のように index.html, css/site.css, scripts/index.js だけで構成される既存サイトがあるとします。(今時ねーよってのは置いといて)

<!DOCTYPE html>
<html lang="ja">
<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>Sample Web site</title>
    <link rel="stylesheet" type="text/css" href="css/site.css" >
    <script type="text/javascript" src="scripts/index.js"></script>
</head>
<body>
    <h1>ようこそ!!私のホームページへ!</h1>
    <span class="welcome-message">Welcome!!</span>
    <p>あなたは 201923 人目の訪問者です。</p>
    <p>現在は <span id="clock"></span> です。</p>
</body>
</html>
document.addEventListener('DOMContentLoaded', function() {
    setInterval(function() {
        var now = new Date();
        var message = `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDay()}日${now.getHours()}時${now.getMinutes()}分${now.getSeconds()}秒`;
        document.getElementById('clock').innerText = message;
    }, 1000);
});
html {
    width: 100%;
}
body {
    width: 100%;
    text-align: center;
}
.welcome-message {
    font-family: monospace; font-size: 24pt; background-color: yellow; color: red; 
}

よくあるこんな感じですね。

f:id:okazuki:20190219143542p:plain

これに Vue.js を一部当て込んでみましょう。

Vue.js の CLI でこんな感じで TypeScript のプロジェクトを作ります。

$ vue create vue-item


Vue CLI v3.4.0
? Please pick a preset: Manually select features
? Check the features needed for your project: TS
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript for auto-detected polyfills? No
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No

出来上がったら public フォルダーにサイトの中身をごそっと入れます。

そして id が app の div タグを追加。

<!DOCTYPE html>
<html lang="ja">
<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>Sample Web site</title>
    <link rel="stylesheet" type="text/css" href="css/site.css" >
    <script type="text/javascript" src="scripts/index.js"></script>
</head>
<body>
    <h1>ようこそ!!私のホームページへ!</h1>
    <span class="welcome-message">Welcome!!</span>
    <p>あなたは 201923 人目の訪問者です。</p>
    <p>現在は <span id="clock"></span> です。</p>

    <div id="app"></div>
</body>
</html>

npm run serve してみて結果を確認。なんか違和感を感じる見た目だけど動いた。

f:id:okazuki:20190219144652p:plain

ん?でも

でも create-react-app で作ったやつも同じ手順でこんな見た目のが出来ますね。

f:id:okazuki:20190219145514p:plain

ということは?

特別な JavaScript をビルドするような構成無しで以下のように追加できるのが、既存サイトに少しずつ適用可能ってことなのかな。

<!DOCTYPE html>
<html lang="ja">
<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>Sample Web site</title>
    <link rel="stylesheet" type="text/css" href="css/site.css" >
    <!-- <script type="text/javascript" src="scripts/index.js"></script> -->
</head>
<body>
    <h1>ようこそ!!私のホームページへ!</h1>
    <span class="welcome-message">Welcome!!</span>
    <p>あなたは 201923 人目の訪問者です。</p>
    <p>現在は <span id="clock">{{ message }}</span> です。</p>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script type="text/javascript" src="scripts/vueclock.js"></script>
</body>
</html>

んで vueclock.js はこんな感じ。

function generateMessage() {
    var now = new Date();
    return `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDay()}日${now.getHours()}時${now.getMinutes()}分${now.getSeconds()}秒`;
}

new Vue({
    el: '#clock',
    data: function() {
        return {
            message: generateMessage(),
        };
    },
    created: function() {
        var self = this;
        this.handle = setInterval(function() {
            self.message = generateMessage();
        }, 1000);
    },
    destroyed: function() {
        clearInterval(this.handle);
    },
});

実行結果は最初と同じでこんな感じです。

f:id:okazuki:20190219151320p:plain