5
8

More than 5 years have passed since last update.

Vue.js+TypeScriptのコンポーネントのクラス定義ミスでハマった話

Posted at

概要

export default class Hoge extends Vue {} のクラス定義をミスった際に不思議な挙動をしたので、覚書。

教訓

Vueファイルをコピーしたらクラス名を変更し忘れないようにしよう。

GitHubに利用したプロジェクトをUPしています。実際に試してみたい方どうぞ^^
https://github.com/kai-kou/vue-js-typescript-component-class-name

準備

ここではDockerを利用して環境構築していますが、ローカルで構築してもらってもOKです。

> mkdir 任意のディレクトリ
> cd 任意のディレクトリ
> vi Dockerfile
> vi docker-compose.yml
Dockerfile
FROM node:10.8.0-stretch

RUN npm install --global @vue/cli

WORKDIR /projects
docker-compose.yml
version: '3'

services:
  app:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ".:/projects"
    tty: true
> docker-compose up -d
> docker-compose exec app bash
コンテナ内
> vue create app

Vue CLI v3.0.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Linter, Unit
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript for auto-detected polyfills? Yes
? Pick a linter / formatter config: TSLint
? Pick additional lint features: Lint on save
? Pick a unit testing solution: Mocha
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
? Pick the package manager to use when installing dependencies: (Use arrow keys)
❯ Use Yarn
  Use NPM
コンテナ内
> cd app

これで環境が整いました。

検証

新しくコンポーネントを追加します。

> touch src/components/Hoge.vue
src/components/Hoge.vue
<template>
  <div>hoge</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component
export default class Hoge extends Vue {}
</script>

追加したコンポーネントをコピーしてもうひとつ追加します。

> cp src/components/Hoge.vue src/components/Hoge2.vue

あえて、export default class Hoge extends Vue {}Hoge をそのままにしておきます。

src/components/Hoge2.vue
<template>
  <div>hoge2</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component
export default class Hoge extends Vue {}
</script>

もとからあるApp.vueで追加したコンポーネントを利用します。

src/App.vue
<template>
  <div id="app">
    <hoge/>
    <hoge2/>
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';

import Hoge from './components/Hoge.vue';
import Hoge2 from './components/Hoge2.vue';

@Component({
  components: {
    HelloWorld,
    Hoge,
    Hoge2,
  },
})
export default class App extends Vue {}
</script>
(略)

ブラウザで確認してみます。

> yarn serve
yarn run v1.9.2
$ vue-cli-service serve
 INFO  Starting development server...
Starting type checking and linting service...
Using 1 worker with 2048MB memory limit
 98% after emitting CopyPlugin

 DONE  Compiled successfully in 67085ms                                                                  7:53:09 AM

No type errors found
No lint errors found
Version: typescript 3.0.3, tslint 5.11.0
Time: 28863ms

  App running at:
  - Local:   http://localhost:8080/

  It seems you are running Vue CLI inside a container.
  Access the dev server via http://localhost:<your container's external mapped port>/

  Note that the development build is not optimized.

スクリーンショット 2018-09-26 16.54.09.png

はい。
追加コンポーネントが表示されました。
追加した2つのコンポーネントのClass名はHoge で同じなのですが、特にエラー出力はありません。

単体テストを追加してみます。

> touch tests/unit/App.spec.ts
tests/unit/App.spec.ts
import { expect } from 'chai';
import { shallowMount } from '@vue/test-utils';

import App from '@/App.vue';
import HelloWorld from '@/components/HelloWorld.vue';
import Hoge from '@/components/Hoge.vue';
import Hoge2 from '@/components/Hoge2.vue';

describe('App.vue', () => {
  it('Hogeコンポーネントが表示されるか', () => {
    const wrapper = shallowMount(App, {});
    wrapper.is(App);
    expect(wrapper.findAll(HelloWorld)).to.length(1);
    expect(wrapper.findAll(Hoge)).to.length(1);
    expect(wrapper.findAll(Hoge2)).to.length(1);
  });
});

テスト実行してみます。

> yarn test:unit
 WEBPACK  Compiled successfully in 1101ms

 MOCHA  Testing...

  App.vue
    1) Hogeコンポーネントが表示されるか

  0 passing (1s)
  1 failing

  1) App.vue
       Hogeコンポーネントが表示されるか:

      AssertionError: expected { Object () } to have a length of 1 but got 2
      + expected - actual

      -2
      +1

      at Context.<anonymous> (dist/webpack:/tests/unit/Hoge.spec.ts:15:1)

 MOCHA  Tests completed with 1 failure(s)

oh。
Hogeコンポーネントが2つとみなされました。
そりゃあ、そうクラス定義しているので、そうですね。
けど、単体テストを書かないと気が付かずにそのまま。。。になりかねないので、 皆さま、うっかりミスには気をつけましょう^^

参考

Vue.js+TypeScriptで開発するときの参考記事まとめ
https://qiita.com/kai_kou/items/19b494a41023d84bacc7

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8