20190301のvue.jsに関する記事は6件です。

Vue.jsのデバッグを快適にする(VScode+Chrome or FireFox)

参考

https://jp.vuejs.org/v2/cookbook/debugging-in-vscode.html
https://qiita.com/hashimoto-1202/items/c81f5d4c271eef16d957

環境

vue-cli(この記事では3.0以上)
VScode
Chrome または FireFox

Debugger for Chrome/FireFox(VSCode拡張機能)

インストール

以下リンク、またはVSCodeの拡張機能検索からインストール
Debugger for Chrome
Debugger for Firefox

インストール後、vue-cli3で作成したプロジェクトフォルダ直下に
vue.config.js を作成し以下を記述する。

vue.config.js
module.exports = {
  configureWebpack: {
    devtool: 'source-map'
  }
}

VSCodeのデバッグビュー→歯車アイコンをクリックしlaunch.jsonファイルを開き
以下を記述する。
スクリーンショット 2019-03-01 22.13.16.png

launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "vuejs: chrome",
      "url": "http://localhost:8080",
      "webRoot": "${workspaceFolder}/src",
      "breakOnLoad": true,
      "sourceMapPathOverrides": {
        "webpack:///./src/*": "${webRoot}/*"
      }
    },
    {
      "type": "firefox",
      "request": "launch",
      "name": "vuejs: firefox",
      "url": "http://localhost:8080",
      "webRoot": "${workspaceFolder}/src",
      "pathMappings": [{ "url": "webpack:///src/", "path": "${webRoot}/" }]
    }
  ]
}

機能

  • F5(メニュー→Debbug→StartDebugging)でブラウザ起動とlocalhost:8080の表示
    npm run serve などをあらかじめ動かしておく必要あり
    スクリーンショット 2019-03-01 22.06.02.png
    起動ブラウザは左上でlaunch.jsonファイル記載のものが選択可能。
    スクリーンショット 2019-03-01 22.37.32.png

  • ブレイクポイントの設定が可能
    行番号の左をクリックしてブレイクポイント設定

Vue Devtools(Chrome/FireFoxアドオン)

インストール

以下リンク、またはブラウザのアドオン検索からインストール
Vue.js devtools(Chrome)
Vue.js devtools(FireFox)

Chromeの場合インストール後に拡張器の設定を開き
「ファイルのURLへのアクセスを許可する」を有効にする。
スクリーンショット 2019-03-01 22.33.01.png

機能

デベロッパーツールにvueタブが追加され
component内のデータなどが参照できる。
スクリーンショット 2019-03-01 22.53.02.png
スクリーンショット 2019-03-01 23.04.49.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel5基本機能Tips&ブロックチェーン

概要

目的:MVCのWebアプリケーション開発用のオープンソースであるLaravelについて基本機能を調査して記録した。今後、マイニング機器を使用して得られた採掘結果の欲しい情報をAPIなどからバックエンドで取得し見やすいUIにまとめグラフ化する予定である。

開発環境

-PHP5
-MySQL
-laravel5
- ローカル
- mac osx
- (XAMPP)
- Vscode
- 未定:リモートレンタルサーバー(AWS)、Docker
ーNanoppol API

主な参照記事:Laravel5 入門 インストールからMVCの基本機能をさっと眺める
[リンク](https://blog.hrendoh.com/getting-start-and-overview-of-laravel5/)

1 インストール&ローカル環境構築手順(Windows、Mac)
2 ルーティング
3コントローラー
4 ビュー
 4.1 基本的なビューの呼び出し方
 4.2 Bladeテンプレート
 4.3 Asset
5データベース操作
 5.1 接続設定
 5.2 モデル (ORM)
 5.3 マイグレーション
 5.4 モデルの利用
6 テスト
 6.1 データベースを利用するテスト
 6.2 テストデータベースのマイグレーション
7 標準機能について
 7.1Authについて
 7.2 使用可能なライブラリについて
 7.3 JavaScriptフレームワークについて(Vue.jsなど)

8  その他
 8.1 よく使うコマンドや実装について
         

1 インストール&ローカル環境構築手順(Windows、Mac)

   Laravel プロジェクトの作成

  Laravelインストール手順は、上記の手順を参照

$ composer create-project laravel/laravel --prefer-dist
<project name>

  
$ php artisan serve
Laravel development server started on http://localhost:8000/

artisanコマンドは、 Artisan CLI Usage を参照。artisan listで使用可能なコマンドは右のコマンドで確認できる。

$ php artisan list

2ルーティング

  ルーティングは app/Http/routes.php に記述する

// app/Http/routes.php

<?php
Route::get('/', 'WelcomeController@index');

   上記は、プロジェクトの作成後のデフォルト、’/’を
   WelcomeControllerの indexメソッドにマッピングしている

3コントローラー

コントローラーは、app/Http/Controllersに
App\Http\Controllers\Controllerを継承するクラスを置く
artisanコマンドでもコントローラーを生成可能
$ php artisan make:controller ArticleController
生成されるコントローラーはRestfullなリソースアクセスを提供する
RESTful Resource Controllers

4 ビュー

基本的なビューの呼び出し方
概要は、The BasicsのViews を参照
ビューのファイルは、resources/viewsに置く
ビューへ渡すデータは、view関数の第二引数に渡す
return view('greeting', ['name' => 'James']);
ビュー側は以下のように、渡されたマップのキーで値を参照できる

// resources/views/greeting.php
<html>
<body>
<h1>Hello, <?php echo $name; ?></h1>
</body>
</html>

resources/viewsのサブディレクトリに配置したビューの呼び出しは、以下のようにドットで連結して呼び出す(‘/’でも呼び出せる)

return view('article.create');

Asset

Laravel5 では、CSS、JavascriptをビルドするGulp タスク Laravel Elixir が標準で提供されている
プロジェクト直下のgulpfile.jsを見てみると、resources/assets/less/app.lessをビルドするタスクがはじめから設定されている

    // gulpfile.js
var elixir = require('laravel-elixir');

elixir(function(mix) {
mix.less('app.less');
});

npm実行環境とgulpをインストールして、プロジェクト直下にて以下のコマンドを実行する

$ npm install

開発中はgulp watchしておけば、lessの修正が自動で反映される

$ gulp watch

5 データベース操作

Basic Database Usage の Configuration によると対応データベースは、
MySQL, Postgres, SQLite, SQL Server と豊富
参照URL:laravel データベースの接続、マイグレーションによる

テーブル作成
https://qiita.com/ryo2132/items/a1c8119b00799d3aed00
LaravelでMAMPのMySQLに接続する
https://qiita.com/kei4eva4/items/480448b83df25774fc74

接続設定

データベースへの接続設定は、config/database.phpに記述する
Laravelのルートディレクトリ.envがあり、環境ごとの設定はこちらに記述
Environmentの設定については、LaravelはDotEnv PHPを利用する
MySQLを使用し Read/Write接続を分けない場合は、config/database.phpではなく.envに接続情報を記述する
デフォルトは以下の.env.exampleがインストール時に.envにコピーされる
(homesteadは、MySQLが.env.exampleの内容に合わせてセットアップ済み)

// .env

APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString

DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

参考: Laravel 5.0 – Environment Detection & Environment Variables
モデル (ORM)

Laravelには、Eloquent ORMというActiveRecord実装がある
モデル生成の artisan コマンドが用意されている

$ php artisan make:model Article

app直下に以下のBlog.phpが生成される

// app/Blog.php

 `<?php

  namespace App;

 use Illuminate\Database\Eloquent\Model;

  class Article extends Model
 {
  //
  }

$tableプロパティに明示的にテーブル名を指定していないので、
このArticleクラスの場合は、articlesテーブルにアクセスする

マイグレーション

上記のArticleモデルを保存するarticlesテーブルを追加する
マイグレーションを作成する場合、以下のように

 artisan mke:migration コマンドを実行する
 $ php artisan make:migration create_articles_table
 Created Migration: 2015_06_09_164737_create_articles_table

マイグレーションファイルはdatabase/migrationsに作成される
(モデル作成時、artisan make:modelコマンドにオプション-mを付けると、モデルと同時にマイグレーションも生成される)
マイグレーションの書き方はWriting Migrationを参照
オートインクリメントのレコードIDと、文字列のtitleとtextをフィールドに持つarticlesテーブルを作成するマイグレーションは以下のようになる

  database/migrations/2015_06_09_164737_create_articles_table

 <?php
 use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Database\Migrations\Migration;

 class CreateArticlesTable extends Migration
  {
   /**
    * Run the migrations.
    *
    * @return void
    */
       public function up()
     { 
         Schema::create('articles',                  
         function($table)
         {
         $table->increments('id');
         $table->string('title');
         $table->text('text');
         $table->timestamps();});
                                }
     /**
     * Reverse the migrations.
     *
     * @return void
     */
        public function down()
     {
        Schema::drop('articles');
                               }
                                }

timestampsは、インスタンスのdateTime型のupdated_atおよびcreated_at列マイグレーションはmigrateコマンドで適用
$ php artisan migrate 
Illuminate/Database/Eloquent/Model – Laravel API
モデルの利用
コントローラーでモデルを利用するには、インポートする
モデル操作は、Modelクラスのファサードおよびインスタンスメソッドで行う
Illuminate/Database/Eloquent/Model – Laravel API

RESTFullコントローラーの実装例

// app/Http/Controllers/ArticleController" highlight="7, 15, 21
<?php
  namespace App\Http\Controllers;
  use Illuminate\Http\Request;
  use App\Article;
  use App\Http\Requests;
  use App\Http\Controllers\Controller;
  class ArticleController extends Controller
   {
   public function index()
   {
     $articles = Article::all();
     return view('article.index', ['articles' => $articles];  }
      public function destroy($id)
     {
    $article = Article::find($id);
    $article->delete(); }}

6 テスト

データベースを利用するテスト
Laravel5では、テスト時にデータベースを切り替える仕組みを標準で用意していない
必要な環境変数はphpunit.xmlに記述する
データベースだけ切り替られれば良いのでDB_DATABASEのみ追加する

// phpunit.xml

テストデータベースのマイグレーション
マイグレーションは、DatabaseMigrationsトレイトを利用して、テストごとにMigrationを実行する

  //tests/ArticleTest
  <?php
  use Illuminate\Foundation\Testing\WithoutMiddleware;
  use Illuminate\Foundation\Testing\DatabaseMigrations;
  use Illuminate\Foundation\Testing\DatabaseTransactions;

    class ArticleTest extends TestCase
       {
           use DatabaseMigrations;
                                    }

7 標準機能について

7.1Authについて
Laravel5.2からmake:authでViewが生成できるようになった
参照:Laravelの標準Authentication(Auth)の動きを調べてみる
   
7.2 使用可能なライブラリについて

Laravelと合わせて使いたいライブラリ
・Pusher
     PusherはPHPでwebsocket(双方向データ通信)を行うためのライブラリ 
    参照URL:PusherはPHPでwebsocket(双方向データ通信)を行う
・Carbon
  PHPで時間を扱うDateTimeのラッパーライブラリ。

   参照URL:PHPで日付時刻処理を書くならCarbonを使うべき
参照URL:Laravelと合わせて使いたいライブラリ5選

7.3 JavaScriptフレームワークについて(Vue.jsなど)
Laravelとフロントエンド

Laravelでは、5.3から、Vue.jsが標準のJavaScriptフレームワークになっているさらに、5.4では、フロントエンドのビルドツールが、gulpベースのElixirから、WebpackベースのMixに変わった。Laravelをインストールすれば、Web APIはLaravelで作って、SPA(Single Page Application)をVue.jsで組む、といったことが簡単にできるようになっている

8.1 よく使うコマンドや実装について

参照URL:
https://walking-succession-falls.com/laravel%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%A9%9F%E8%83%BD%E3%80%81%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E3%81%97%E3%81%9F%E5%B0%8F%E6%8A%80%E3%81%BE%E3%81%A8%E3%82%81/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

2019年版Vue.jsを使ってる人には必ず知っていてほしいVue.jsの武器とドキュメントに書かれていないコンポーネントやメンテナンスの際に役立つTips

はじめに

私はVue.js with Vuexを使った業務で1画面30APIを叩く必要のある画面から、たったの数APIしか叩かないけれど、代わりにUIがとても機能的で複雑な画面まで設計し、構築しました。
もちろん、Vue.jsのコンポーネントシステムをフル活用し、Vuexを入れていないプロジェクトの経験もあります。
現在は構築したシステムを保守・運用しています。
また、勉強の為にReact、 Angular、 最近はElm等にも少し触れています。
その際に得られたノウハウ、Vue.jsが他のライバルフレームワークと比べた際に現時点で本当に勝っている利点やノウハウを言語化し、共有出来たらと思います。

※ 記事の内容に意見がありましたら直接編集リクエストをください。

Vue.js含めどのフレームワークも利点・欠点があります

せっかくなので自分が把握しているVue.jsの利点と欠点を説明しようと思います。

利点

Vue.jsの武器は単一ファイルコンポーネントとそのシンタックスです!

コンポーネントシステムやファイルの粒度は思想は違えどReactでも似たような事はできますし、Angularでも似たような事はできますが、Vue.jsの場合は1つのコンポーネントを作るのに必要なファイルがたったの1つであり、そのファイルの中に慣れ親しんだhtmlで描画部分を書き、慣れ親しんだ普通のjavascriptでコンポーネントに必要な処理や表示ロジックを書け、css in js, css module, sass, stylus等、好きな方法でそのコンポーネントにだけ当たるスタイルを書けます。
これが他のフレームワークと比べて圧倒的に見やすく、学習していない状態でもなんとなく触れるレベルでわかりやすく、シンプルでしょう。

利点を妨げる要素

Vuexはできる限り入れないほうが良いよという話

Vuexを入れるメリット

  • Vuexを入れるとFluxライクなアーキテクチャが採用でき、model層でのデータ管理が可能になります。
  • 設計の仕方によってはmodel同士の結合度等を自由に操作でき、かなり疎結合にもできます。 また、これはテストしやすいです。
  • etc...

デメリット

  • model同士の結合度をコントロールするのはかなりの設計面の技術力が要求され、苦しんでいる話をよく耳にします。
  • そこそこjavascript力も要求されます。
  • Vue本来の1ファイルで完結するような圧倒的な見通しの良さがなくなってしまします。
  • model層が発生するとそれだけ複雑になりますし、イベントが誰から発行されたのかの管理も難しいです。
  • Typescriptを入れない場合は、Vuexとのミスバインドもよく発生しますし、Vuexのロードマップにはこれから破壊的な変更が沢山入る事が記されています。
  • Typescript対応も凄く困難が多いです。
  • Vueは実はReactのようなコントロールドコンポーネントが作れません。dataがこれだから、表示されている値はこれという保証が一切ないです。
  • Stateが代入構文しか受け付けない為、Object.assignですり抜ける以外にStateでUnionTypeを使う方法がないです

Vue + Vuexの感想

もちろん部分的に状態管理が本当に必要な箇所があれば入れるのは良いと思いますが、本当に最低限の利用に留めた方が良いと思います。
しかし現時点で全体的にVuexを入れるとなると、Vue.jsの長所であるSFCの恩恵が大分減るので、他のフレームワーク使ったほうが良いと思いました。

欠点

顕在化した業界主流とのズレ

現時点では、ある程度の中・大規模開発ではTypescriptを利用するのが業界の主流です。
Vue.jsの場合だとここで1歩遅れを取っていて、その理由を以下に上げます。

  1. vueファイルはオリジナルファイル形式であるため、エディターでvueのサポートをするのが大変なのです。2019年3月1日時点だと、vscodeではvueファイルのtsのバージョンと本当に入れているtypescriptのバージョンに差分がでています。もしかしたら自分が使っているのよりも良いvueの構文解析ツールがあるかもしれませんが、このvueファイルのメンテナンスや出来に影響を受ける開発者さんは多いでしょう。また、構文解析ツールを作る人達の大変な声をよく耳にします。

  2. ファイルの拡張子がvueであり、オリジナル構文なため、何がそのファイルからexportされているか既存の解析ツールの資産だとわかりません。例えばimport Hoge from Hoge.vueとした場合、現時点だと、とりあえずvueインスタンス又はvueのコンポーネントオプションがdefaultでexportされているよ!ぐらいに型をつけるのが精一杯でしょう。

改善

Vue.jsの今後

Vue.jsのロードマップはここにあります。
https://github.com/vuejs/roadmap

Evan Youさんが言うには

  • Vue.jsをTypescriptで作り直し、vueのtemplate内でも型は効くようになるし、tsxのサポートも強化するようです。
  • どうしようもない部分にanyとかの型を付けていたのもきっと消えると期待しています。
  • import Hoge from Hoge.vueとした時もちゃんと型がついているのを期待していいのではないかと思います。
  • Vuexでよく型が辛いと言われますが、その部分も改善すると思われます。
  • VueのClass Base Componentをネイティブにサポートするなどの細かい追加もあります。

なので、Vue.js + Typescriptをしっかりとやりたい場合はVue.js3のリリースを待つのが良いのではないかとおもいます。

フロントを新しく作る場合どのフレームワークで作ればいいの?

個人的には

  • javascriptがそこまで得意でもないフロント初学者 => Vue.js
  • Typescript + classベースの構文が好き => Angular
  • 関数型の構文が好きな場合はReact
  • バックエンドをScala、Haskellとかで書いてたことがあり、且つ好き => Elm

とかでいいんじゃないのだろうかと思います。

まとめ

確かに受けれる恩恵もありますが、もしVuexを全面的に入れるぐらいなら現時点だと他のフレームワークで書いたほうが良いのは間違いないでしょう。

Vue.jsの最も協力な武器であるSFCの質を上げるTips

ほとんどのバグは変数から来ます。
もし全ての値が定数なら状態から来るバグはほとんど無くなるでしょう。
ここではこの変数や式を極力減らしたり、見通しを更によくするTipsを紹介したいと思います。

htmlやvue標準で用意されているタグやコンポーネント名と同じ名前のコンポーネント名を付けない

もしhtmlやvue標準で用意されているタグやコンポーネント名と同じ名前のコンポーネント名を付けたい場合は、The prefixを付けるなどして、必ず別名にしてください。
参考リンク

自分が1度遭遇したバグなんですが、プロジェクト全体にprettierでフォーマットかけて、かならずprettier通してないとCIが通らないようにした際にヘッダー部分とか色んなコンポーネントが表示されなくなり、アプリが一時的に壊れました。
それの原因は、Header部分のコンポーネントをHeaderと書いており、prettierによってheaderに修正されたからです。
その影響により、htmlのheaderタグがただ表示されるようになってしまいました。
他にも同じようなコンポーネントにいくつか出会いましたが、この命名方式はそのようなバグから逃れる為です。

templateで必要じゃないmethodは極力vueに定義しない

これはどのmethodがそのcomponentで使われているのかを簡単に把握する為です。

悪い例:

export default {
  data() {
    return {
      users: [],
      loading: true
    };
  },
  mounted() {
    this.getUsers();
  },
  methods: {
    async getUsers() {
      const { data } = await this.$axios.get('/api/users');

      this.users = data.users;
      this.loading = false;
    }
  }
};

例えばこちら、getUsersがなんかtemplate内でも使われてそうな雰囲気があります。
また、もしかしたら他のcomponentthis.$refs.hoge.getUsers()ってコードを書いて、そのメソッドを実行している可能性もあります。
チーム開発で、それはしていない、このメソッドは使ってない!消せる!って言い切るには、全文検索するしか今の所方法がないです。このTipsを適用すればそのような不安もある程度緩和できると思います。

改善例:

async function getUsers(axios) {
  const { data } = await axios.get('/api/users');
  return data.users
}

export default {
  data() {
    return {
      users: [],
      loading: true
    };
  },
  async mounted() {
    this.users = await getUsers(this.$axios);
    this.loading = false;
  },
};

afterでは、このコンポーネントはmount時にデータ取得を1度だけするんだなってのが凄く明瞭だと思います。
また、他のcomponentthis.$refs.hoge.getUsers()ってコードを書いて、そのメソッドを実行している可能性が完全になくなりましたね!

dataを極力定義しない

Vue.jsでコンポーネントを定義する際ついdata()に沢山変数を定義しちゃいますよね。
しかし、dataはいわゆるインスタンス変数です。
もしそのdataの値が定数とかpropsから算出できる値だったりした場合できるだけcomputedに移してあげましょう。
なぜならsetterがないcomputed はread onlyだからです。read onlyは変更される心配がないためバグを減らしてくれるとても素晴らしいものです!

悪い例:

export default {
  props: {
    user: {
      type: Object,
      required: true,
    },
  },
  data() {
    const birthdayDate = new Date(this.user.birthday);
    return {
      max: 5,
      birthday: `${birthdayDate.getFullYear()}/${birthdayDate.getMonth() + 1}`
    };
  },
};

悪い例ではmaxやbirthdayがtemplate内でも変更される心配があります。
また、user propの値が変わってもbirthdayは再計算されることはないでしょう。

改善例:

export default {
  computed: {
    max: () => 5,
    birthday() {
      const birthdayDate = new Date(this.user.birthday);
      return `${birthdayDate.getFullYear()}/${birthdayDate.getMonth() + 1}`;
    },
  },
};

改善例ではmaxやbirthdayがtemplate内でも変更される心配がない事がすぐにわかります。
また、user propの値が変わってもcomputedのbirthdayは正しい値をリアクティブに再計算してくれます。
改善例の方がこれはどういう値か伝わってきますね!
しかもダメな例と比べ状態(変数)を1つ減らせました!つまりバグの原因が1つ減りました!おめでとうございます!

template内でできるだけ式を書かない

template内でdataなどを直接変更したりイベントを発火したりするコードを直接書くことはよくありません。
それには大まかに2つの理由があります。

  • 変数を定義している場所と変更されている場所が遠すぎて視認性にすぐれない
  • methodで定義すれば式にメソッド名という形式でこのカプセル化された式はどういう意図をもった式なのかを簡単に伝えられる
    • template内に直接式を書いた場合は逆にこの式はどういう式かをコードを見た人全員が推測しなければなりません。つまりハイコンテキスト、空気を読めって事です。メンテする際に大抵困ります。

悪い例:

<template>
  <button @click="count++ && $emit('change', count)">ボタン</button>
</template>


<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
};
</script>

改善例:

<template>
  <button @click="incAndNotify()">ボタン</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    incAndNotify() {
      this.count++;
      this.$emit('change', count);
    },
  },
};
</script>

templateタグを最大限に有効活用

このようなコードをたまにみます。
お世辞でもスマートとは言い難いですね。

悪い例:

<template>
  <div>
    <button @click="inc()">ボタン</button>

    <div v-if="isSmallCount">これはとても小さな値です!</div>
    <div v-if="isSmallCount">値をもっともっと増やしてください!</div>

    <div v-if="!isSmallCount">これはとても大きな値です!</div>
    <div v-if="!isSmallCount">すごいです!</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  computed: {
    isSmallCount() {
      return this.count < 5;
    },
  },
  methods: {
    inc() {
      this.count++;
    },
  },
};
</script>

改善例:

<template>
  <div>
    <button @click="inc()">ボタン</button>

    <template v-if="isSmallCount">
      <div>これはとても小さな値です!</div>
      <div>値をもっともっと増やしてください!</div>
    </template>

    <template v-else>
      <div>これはとても大きな値です!</div>
      <div>すごいです!</div>
    </template>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  computed: {
    isSmallCount() {
      return this.count < 5;
    },
  },
  methods: {
    inc() {
      this.count++;
    },
  },
};
</script>

改善例では、templateタグ内にtemplateタグが使われています。
どういうことでしょうか?
一度isSmallCountが真の時にDOMがどのようにマウントされるのかを見てみましょう!

<div>
  <button @click="inc()">ボタン</button>
  <div>これはとても小さな値です!</div>
  <div>値をもっともっと増やしてください!</div>
</div>

なんてことでしょう!templateタグがどこにも見当たりません!
そうtemplateタグはなんとマウントされる際に表示されないのです!
これはv-ifなどの式を書く際にとても重宝できます!スコープはありませんが、ブロック的なものを表現できますしね!

※ もちろんv-forなどにも使えますよ?
※ 注意: v-showなどスタイルを当てる奴は反応しません

フラグを極力減らす

通信をするコンポーネントでは通信中状態と通信していない待機状態があります。
例えばこれを2つのフラグで管理していた場合不整合が発生する可能性が出ます。
これはとても不健康な状態です。きっと将来待機状態なのに通信状態という意味不明な状態が発生するでしょう。

悪い例:

<template v-if="isInitializing">
  <div>初期化中です。。。?</div>
</template>

<template v-else-if="isStandby">
  <div>初期化完了です?</div>
</template>

<script>
export default {
  data() {
    return {
      isStandby: false,
      isInitializing: true,
    };
  },
};
</script>

悪い例では先程も言ったようにフラグの整合性を保証できるものが何もありませんね。
ですのでこれらを1つの状態フラグで管理するようにします。
名前は適当にcurrentStateで良いでしょう。

改善例:

<template v-if="isInitializing">
  <div>初期化中です。。。?</div>
</template>

<template v-else-if="isStandby">
  <div>初期化完了です?</div>
</template>

<script>
const IS_STANDBY = 'IS_STANDBY';
const IS_INITIALIZING = 'IS_INITIALIZING';

export default {
  data() {
    return {
      currentState: IS_STANDBY,
    };
  },
  computed: {
    isStandby() {
      return this.currentState === IS_STANDBY;
    },
    isInitializing() {
      return this.currentState === IS_INITIALIZING;
    },
  },
  methods: {
    toStandby() {
      this.currentState = IS_STANDBY;
    },
    toInitializing() {
      this.currentState = IS_INITIALIZING;
    },
  },
};
</script>

やりました!改善例では変数を1つ減らし、不整合が絶対に起こり得なくなりました!
今回の例はとてもシンプルですが、画面のタブを管理する時など状態が多くなればなるほど役に立つテクニックになります。

必須propsに必ずrequired trueを付ける

必須propsには必ずrequired trueを付けるべきです。
たまにあるのが、必須propsなのにdefault値だけを指定してrequired trueを設定しないケースです。

悪い例:

export default {
  props: {
    account: { type: Object, default: null },
    shokai: { type: Object, default: null }
  },
};

なぜこれが悪いのかというと、account propに何か入れて欲しいのに、入れ忘れた場合でも一切警告がでなく、バグ発見が困難になります。
また、本当に任意であるpropがどれか見分ける難易度が上がってしまいます。

改善例:

export default {
  props: {
    // account: { type: Object, default: null },
    // shokai: { type: Object, default: null }
    account: { type: Object, required: true },
    shokai: { type: Object, required: true }
  },
};

やりました!
改善例ではaccountにpropをバインドし忘れてもエラーがでるのですぐに気付けますね!

汚いコンポーネントをスマートにするテクニック

レイアウトやアニメーションに関するコードと表示用コンポーネントのコードが一緒になっているコード等が対象です。
大抵の場合別に良いのですが、v-forでリストを表示して、そのリストの各アイテムにも詳細情報の開閉ボタンがあり、クリックされたら詳細が開示されるなどのコードがあります。
まぁ大抵ここまでのコードを1つのコンポーネントで書くと、とてもではないですがメンテナブルなコードとは言い難いですね。バグが発生しても各アイテムの開閉状態のコードなど色んなコードが一箇所に書かれているため何が原因か特定するのにも時間がかかりますし、破壊する恐れもあります。
では、slotに渡されたアイテムの開閉だけを担当するコンポーネントと、専用のslotをいくつか用意したレイアウト用のコンポーネントを作成し、それをメインとなるコンポーネントで使ってはどうでしょうか。コードがとても見通しがよくなります。
また、メインとなるコンポーネントからはきっと大量のインスタンス変数が消えてバグが減ったかと思われます。

一応これは開閉だけするコンポーネントのサンプルです。
これは自分がフォークして作ったライブラリで、メンテしてないのでお世辞にも綺麗なコードとは言えませんが、参考程度に。
https://github.com/kahirokunn/vue-slide-up-down-component

OSSのUIライブラリを利用しましょう

1からプロダクトを作成する際にdialog、tooltip、form、validationなど他にも目眩がする程の大量のコンポーネントを作る必要があります。しかも自社でそういうのを全部書いてるときっと粒度も何もかもがバラバラでしょう。しかもレスポンシブ対応もできるだけしたい!あぁ、これはとても大変です!
そういう場合は既存のOSSからUIライブラリを拝借しましょう!
その際に重要なチェック項目として

  • 活発
  • ドキュメント、サンプルコードが豊富
  • レスポンシブ

などがあります。
ちなみによくできたUIライブラリはCSSは基本上書きできますので大抵のデザイン要件を満たせます!
それでもデザイン要件を満たすのが辛い場合はデザイナーさんと相談しましょう!このUIライブラリを使っていてできるだけこれに沿って工数を減らしたいといえばきっと協力してくれるでしょう!
ちなみに私のオススメはVuetifyです。これはとてもよくできていて、活発で、ドキュメントやサンプルコードが豊富でレスポンシブ対応です!

※ 自社専用のUIライブラリ別リポジトリで用意し、上手くメンテできるほどの潤沢なリソースがある環境は例外とします。

OSSのUIコンポーネントなどを積極的に利用しましょう

私はよく全然活発でなくてメンテされていなくても現在のニーズにあったOSSのUIコンポーネントがあった場合はとりあえず利用します。
それはとても怖いことではないでしょうか?もしそのOSSがバグっていたらと思うとゾッとするのではないですか?そう思われる方はきっと沢山いるでしょう。
しかし自分が書いてもそのコードはバグってないと保証できるのでしょうか?
かのマーク・ザッカーバーグもこう言っています。

これみて.jpg

そう、とりあえず使ってみればいいでしょう!
よく運用している途中でそのOSSのバグを見つけたりします。
もし見つけた場合は、正しく動くように利用していたOSSのコードを参考に自分で改善した奴をnpmに公開したりします。もしくは利用していたOSSへ感謝の気持ちを込めてプルリクエストを作ってあげましょう!
そう、結局は自分で書いても他の人が書いてもバグる時はバグるのでとりあえず使ってみてバグったら直しましょう!

最後に

如何だったでしょうか?
最近あまり記事を書いていないので久しぶりに前の記事の延長として書いてみました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メモ > Vue フォーム とバリデーション(途中です)

Vueで、フォームを作成したのでメモ(途中です)

動作デモ
sugasaki vue form test

ソース
sugasaki/vue-mailform-test: vue mail form test

  • vue
  • vuex
  • vue-router
  • axios
  • sanitaize-html
  • vuetify
  • element-ui

cccccccc

  • namespaced: true, sotreはネームスペースでモジュール分け
  • 値はgettersで取得
  • 値のSETはactionsからmutationsをCALL

store.js
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

//カウンターのモジュール
const counterModule = {
  namespaced: true,
  state: { count: 0 },
  mutations: {
    increment(state) {
      state.count++;
    },
    increment2(state, addCount) {
      state.count += addCount;
    },
    decrement(state) {
      state.count--;
    }
  },
  actions: {
    increment(context) {
      context.commit("increment");
    },
    decrement(context) {
      context.commit("decrement");
    },
    increment2(context, data) {
      //console.log("increment2", data);
      context.commit("increment2", data);
    }
  }
};
  • ActionをCALLするときは、以下のような感じ this.$store.dispatch("counter/increment2", 2);

router

router.js
import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";

Vue.use(Router);

export default new Router({
  mode: "history",
  base: process.env.BASE_URL,
  scrollBehavior() {
    return { x: 0, y: 0 };
  },
  routes: [
    {
      path: "/",
      name: "home",
      component: Home
    },
    {
      path: "/counter",
      name: "counter",
      component: () =>
        import(/* webpackChunkName: "counter" */ "./views/Counter.vue")
    }
  ]
});

画面遷移した時に、スクロール位置を最上部にしたければ以下を付ける
js
scrollBehavior() {
return { x: 0, y: 0 };
},

view

counter.vue
  <template>
  <div class="about">
    <h1>This is an counter page</h1>

    <el-button type="primary" v-on:click="increment">+</el-button>
    <el-button type="danger" v-on:click="decrement">-</el-button>
    <el-button type="primary" v-on:click="increment_add">+2</el-button>
    <el-button type="primary" v-on:click="increment2(2)">+2</el-button>

    <h2>{{ count }}</h2>
  </div>
</template>

<script>
import { mapActions } from "vuex";

export default {
  name: "about",
  components: {},
  computed: {
    count() {
      return this.$store.state.counter.count;
    }
  },
  methods: {
    ...mapActions("counter", [
      "increment", // -> this.increment()
      "increment2", // -> this.increment2()
      "decrement" // -> this.decrement()
    ]),
    increment_add: function() {
      this.$store.dispatch("counter/increment2", 2);
      //console.log(this.$store.state.counter);
    }
  }
};
</script>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メモ > Leaflet > Vue > Vue2Leaflet

vue2-leaflet - Vue2 leaflet library

yarn add leaflet
yarn add vue2-leaflet


yarn add vue-style-loader
yarn add css-loader
yarn add sass-loader

@import "../node_modules/leaflet/dist/leaflet.css";

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メモ > vue > error: Parsing error: Unexpected token

js: .eslintrc.json
{
"parser": "babel-eslint",
// 以下、設定が続く…
}

ESLintで Parsing error: Unexpected token = となる場合の対処法 - Qiita

error: Parsing error: Unexpected token < at

> 1 | <template>
    | ^
  2 |   <div class="hello">
npm install --save-dev eslint eslint-plugin-vue
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む