いがにんのぼやき

WEBエンジニアのブログ。IT、WEB、バンド、アニメ。

JavaScriptで指定のスタイルが当たっている要素を探す

JavaScriptで指定の要素に適用されているスタイルや、特定のスタイルが適用されている要素を探したいときってあるよね。
そんなときに簡単にとろうと思ってJSでコードを書いてみると、

document.getElementById('hoge').style

こんなコード書けばとれるんじゃないかと。
で、オブジェクトが返ってくるので中身を見てみるとCSSに書いたスタイルが取れてないんですよ。
この記法だと要素に直接記述されたスタイルしか取れない。

結論、要素に書いたスタイル、それ以外のスタイルも含めて要素に適用されているスタイルをとるならgetComputedStyleを使おうぜって話。

developer.mozilla.org

const elm = document.getElementById('hoge');
const styles = getComputedStyle(elm);

これでCSSも含めてすべてのスタイルが適用された要素のスタイルがCSSStyleDeclarationという型のオブジェクトで返ってくる。
スタイルはそれぞれケバブケースからキャメルケースにした名前でその値が取得できる。

const elm = document.getElementById('hoge');
const style = getComputedStyle(element).backgroundColor; // rgb(0, 0, 0)

f:id:igatea:20190707004417p:plain

注意として色をblack#000としている場合にrgbに変換された値で出てくるので比較するならそれを配慮しなければいけない。

指定の要素から特定のスタイルが当たっている先祖要素を探す

再帰的に検索してあげればいい。
子孫要素から探すなら逆に再帰関数を書けばいける。

/**
 * @param {HTMLElement} element
 * @param {string} styleName
 * @param {string} styleValue
 */
function findHasStyleAncestorElement(element, styleName, styleValue) {
  if (!element) return null;
  const style = getComputedStyle(element)[styleName];
  if (style === styleValue) return element;
  return findHasStyleAncestorElement(
    element.parentElement,
    styleName,
    styleValue
  );
}

const elm = document.getElementById("c");
const blackBackgroundElm = findHasStyleAncestorElement(
  elm,
  "backgroundColor",
  "rgb(0, 0, 0)" // blackではない
);

Dapperでトランザクションを使用、トランザクション分離レベルを変更する方法のメモ

Dapperでトランザクションの分離レベルを変更するときにどういう挙動をするのかよく分かっていなかったので調べたメモ。
ついでにトランザクション周りのSQLも確認。

今回の環境

今回試しているのはSQLServerだが他のRDBでも方言の違いはあれど基本的に同じなはず。

SQL

まずSQLの確認から。

トランザクションの分離レベルの設定。 Serializableであれば下記。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

docs.microsoft.com

分離レベル オプションは一度に 1 つだけ設定でき、設定したオプションは明示的に変更されない限り、その接続で継続的に使用されます。 ステートメントの FROM 句内にあるテーブル ヒントで、テーブルに対して別のロック動作やバージョン管理動作が指定されない限り、トランザクションのすべての読み取り操作は、指定した分離レベルのルールに従って実行されます。

公式ドキュメントを見ると接続単位でトランザクション分離レベルが決まるらしい。

実際に今の分離レベルを確認するなら。

DBCC USEROPTIONS

docs.microsoft.com

このSQLを実行するとisolation levelの項目に今の分離レベルが表示される。

f:id:igatea:20190421204934p:plain

SSMSで確認すると切断、再接続をしてもずっと変更後の分離レベルになっているのでここらへんの挙動ははっきりわからない。
恐らくセッションが生きているようで、SSMS自体を再起動すると規定値に戻る。

MySQLで分離レベルを確認する場合はこんな感じらしい。(未検証)

SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

実際に分離レベルを設定してトランザクションを張るにはBEGIN TRAN、コミットはCOMMIT TRAN。

BEGIN TRAN
    /****** 実行する処理  ******/
COMMIT TRAN

実際にはSQLで全部やるならTRYCATCHしてROLLBACKの処理が入るだろう。

Dapper

次にアプリケーション側でどう書くか。
今回はDapperを使って書いてみる。
まずはusingでSqlConnection.BeginTransactionを呼び出す。
これでトランザクションを張ることが出来る。
BeginTransactionは第一引数で分離レベルを設定することが出来る。

docs.microsoft.com

実際に実行するコードはこんな感じに。 このSQLだと分離レベルを変える意味はないがご愛嬌。

using (var tran = conn.BeginTransaction(IsolationLevel.Serializable))
{
    var sql1 = @"
INSERT INTO Samples ( Id, Name )
VALUES ( @id, @name )";
    var sql2 = @"
INSERT INTO Samples ( Id, Name )
VALUES ( @id, @name + 'duplicate' )";

    try
    {
        await conn.ExecuteAsync(sql1, new { id = sample.Id, name = sample.Name }, tran);
        await conn.ExecuteAsync(sql2, new { id = sample.Id, name = sample.Name }, tran);
        tran.Commit();
        return true;
    }
    catch (SqlException e)
    {
        // log出力とか
        return false;
    }
}

usingでBeginTransactionを囲っておけばこのコードが終わった時にコミットされていなければロールバックしてくれる。
ここで分離レベルを指定しなかった場合、Dapperで実行するとそのコネクションプールが保持されている限り、その接続で前に使用されたトランザクションレベルが使用されてしまう。
・・・と思ったけどDBCC USEROPTIONS の結果は固定化されているが using (var tran = conn.BeginTransaction()) したときは一番最初のトランザクションレベルとなっている。

公式ドキュメントにはこのように記載があった。

分離レベルを指定しない場合は、既定の分離レベルが使用されます。 分離レベルを指定する、BeginTransactionメソッドを受け取るオーバー ロードを使用して、isoパラメーター (BeginTransaction)。 トランザクションの分離レベルは、接続が終了または破棄されるまで、トランザクションが完了した後に永続化します。 分離のレベルを設定スナップショットsnapshot 分離レベルが有効になっていないデータベースではない例外をスローします。 既定の分離レベルを使用して、トランザクションが完了します。

日本語訳が変だけど、以下も併せて読んでみるとどうやらREAD COMMITTEDがSQLServerでのデフォルトでになっており、それが使用されるらしい。

stackoverflow.com

ので、分離レベルはこんな感じに切り替わる。

using (var conn = CreateConnection())
{
    var t1 = conn.Query("DBCC USEROPTIONS"); // 前のトランザクションレベルが表示される
 
     conn.Execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); // BeginTransactionでは意味なし
 
    using (var tran = conn.BeginTransaction())
    {
        var t2 = conn.Query("DBCC USEROPTIONS", new { }, tran); // READ COMMITTEDが表示、既定のトランザクションレベル

        var sql1 = @"
INSERT INTO Samples ( Id, Name )
VALUES ( @id, @name )";
        var sql2 = @"
INSERT INTO Samples ( Id, Name )
VALUES ( @id, @name + 'duplicate' )";

        try
        {
            await conn.ExecuteAsync(sql1, new { id = sample.Id, name = sample.Name }, tran); // READ COMMITTEDで実行される
            await conn.ExecuteAsync(sql2, new { id = sample.Id, name = sample.Name }, tran);
            tran.Commit();
            return true;
        }
        catch (SqlException e)
        {
            // log出力とか
            return false;
        }
    }
    }
}

trasactionの引数でちょっとした罠があり、パラメータがなくてもQueryAsyncの第二引数に匿名オブジェクトを入れて、第三引数にトランザクションを入れなければいけない。
そうしないとIDbTransactionをオブジェクトとして認識してただのクエリに入れるパラメータと判断し、以下のエラーが出る。

InvalidOperationException: ExecuteReader requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.

分離レベルを変えて、Serializeレベルで行うならこんな感じになる。

using (var conn = CreateConnection())
{
    var t1 = conn.Query("DBCC USEROPTIONS"); // 前のトランザクションレベルが表示される

    using (var tran = conn.BeginTransaction(IsolationLevel.Serializable)) // 変わる箇所
    {
        var t2 = conn.Query("DBCC USEROPTIONS", new { }, tran); // Serializableが表示

        var sql1 = @"
INSERT INTO Samples ( Id, Name )
VALUES ( @id, @name )";
        var sql2 = @"
INSERT INTO Samples ( Id, Name )
VALUES ( @id, @name + 'duplicate' )";

        try
        {
            await conn.ExecuteAsync(sql1, new { id = sample.Id, name = sample.Name }, tran); // Serializableで実行される
            await conn.ExecuteAsync(sql2, new { id = sample.Id, name = sample.Name }, tran);
            tran.Commit();
            return true;
        }
        catch (SqlException e)
        {
            // log出力とか
            return false;
        }
    }
}

実行したソースはこちら。

https://github.com/igayamaguchi/OrmExample/tree/master/InsertDuplicate

調べている上で知ったこと

SQLServerへの接続を切る方法。

クエリ発行をするセッションは切れない。

docs.microsoft.com

切断。

KILL [セッションID]

セッション確認。

 SELECT conn.session_id, host_name, program_name,
     nt_domain, login_name, connect_time, last_request_end_time 
 FROM sys.dm_exec_sessions AS sess
 JOIN sys.dm_exec_connections AS conn
    ON sess.session_id = conn.session_id;

プライマリーキー、一意性違反の検知

SqlExceptionのNumberに2627という数字が入る。
これはSQLServerの重複違反のエラーコード。
使用するデータベースによって数字は異なる。

public enum CreateResult
{
    Success,
    Duplicate
}

try
{
    await conn.ExecuteAsync(sql, new { id = sample.Id, name = sample.Name }, tran);
    tran.Commit();
    return CreateResult.Success;
}
catch (SqlException e) when (e.Number == 2627)
{
    // log出力とか
    tran.Rollback();
    return CreateResult.Duplicate;
}

ORMの使う使わないについて

  • とあるコミュニティでORMを使う使わない、使い方の議論があった
  • 自分の考えを整理するためにも今自分がこうしたほうがいいなって運用方法を書き出してみる
  • 個人の好みによるものが大きいので一意見として
  • ここではサーバーアプリケーションでの文脈

ORMってそもそも何

前提知識としてORMとは

  • インピーダンスミスマッチを解消するもの
  • インピーダンスミスマッチとは
    • 概念モデルと論理モデルの違いを埋める
    • アプリケーションの要件にそった概念モデル(Entity)は、論理モデル(テーブル)と1対1になるとは限らない
    • こういったDB側の都合をアプリケーションで意識しないで済むようになるもの

ORMを使うか使わないか

でもDB側の都合を意識しないで済むって言うけど結局パフォーマンスとか考えたら意識しなくちゃいけないよね?
で、ORM使ってWhereとか書き始めたらそれSQL書いているだけだよね?ORMいらなくない?
っていうのが今回のORM使う使わない問題の根幹としてあると思う

サーバーアプリケーションからDBの値を引く

サーバーアプリケーションからプログラムを書いて、DBから値を読み込み、アプリケーションで使用する、その方法は大体こんな感じだと思う

  • SQLを直接書いてORMを用いずマッピング
  • ORMを使用するパターン
    • ORMの機能(クエリビルダーなど)を使用する
    • ORMとSQLを組み合わせる

個人的意見

個人の好みによる ORMでクエリビルダーを有効活用するのが自分の最適解

SQLを直接書いてORMを用いずマッピング

ここからは各方法を実際のコード(C#)で良いところ、悪いところを挙げていく
ORMを使用しないマッピングの場合、

  • SQL書く
  • 何かで実行、結果は配列みたいなものに入る
  • 自分で毎回マッピング
 var sql = $@"
 SELECT
  USER.NAME
  ARTICLE.TITLE
 FROM
  USER
 INNER JOIN
  ARTICLE ON ARTICLE.ID = USER.ID
 WHERE
  ID = @id
 ";
 
 return Connection.Query(sql, new { id });
 
 // 上の呼び出し元
 foreach(result in results)
 {
    var name = user["Name"]
    var title = user["Title"]
    
    // 何かの処理
 }

良いところ

  • クエリを直接かけるのでハイパフォーマンス
  • 特別構文解釈の負荷もかかりにくい

悪いところ

  • 取り回しが悪い

そのままSQLからしっかりデータベースのことを考えてチューニングできるのでいい
でもビジネス要件に耐えられるものではないかなあと思ってしまう
上記は単純なSQLだが複雑度が増し、その複雑度の増したSQLが画面やAPIによって若干の条件が変わるごとに同じSQLを書くことになったりして辛くなるのでは
サーバーアプリケーションにおいてはこれを用いることによって行えるパフォーマンス向上も一般的なサーバーアプリケーションでは早すぎる最適化なのではと思う

ORMとSQL書くパターン

前の直SQLだけの場合と比べるとマッピングが追加されただけ

 var sql = $@"
 SELECT
  USER.NAME
  ARTICLE.TITLE
 FROM
  USER
 INNER JOIN
  ARTICLE ON ARTICLE.ID = USER.ID
 WHERE
  ID = @id
 ";
 
 // Userクラスにマッピングされる
 return Connection.Query<User>(sql, new { id });

良いところ

  • クエリを直接かけるのでハイパフォーマンス

悪いところ

  • 取り回しが悪い

これも前述の取り回しの問題が解決できない

ORMでクエリビルダーで書くパターン

C#だとメソッドで書くパターンとクエリ式というもので書くパターンがある

  // メソッド形式
 var result1 = _context.Users
                .Join(
                _context.Articles,
                user => user.ID,
                article => article.UserId,
                (user, article) => new { user, article })
                .Where(m => m.user.ID == id)
                .Select(m => new { m.user.Name, m.article.Title }).ToArray();
 
 // クエリ式
 var result2 = (from user in _context.Users
                join article in _context.Articles
                on user.ID equals article.UserId
                where user.ID == 1
                select new { user.Name, article.Title }).ToArray();
  

良いところ

  • (静的解析であれば)補完が効く
  • 通化、拡張がしやすい

悪いところ

  • 独自構文、メソッドを覚えなくてはいけない
  • 発行されるSQLを把握しとく必要がある

これのいいところは取得するカラムの絞り込みを後から行いやすかったり、Whereの共通化、追加を行いやすい
JoinやWhereの部分を拡張メソッドとして切り出してあげることも可能

  public static IQueryable<User> HasArticle(this IQueryable<User> query)
 {
     return query.Where(user => user.Articles.Any());
 }
 
 var result = _context.Users
                .HasArtice()
                .ToArray();

みたいな
ここらへんはORMによりけり
C#のクエリ式はSQLそのままに近く、かつプログラミング言語の機能を生かせるのでかなりいいと思っている
リッチなORMであれば上記のようなクエリビルダーを使うこともないかもしれない
ここらへんは後でもう少し深堀したいところ

Vue.js スタイルガイドのすヽめ

概要

この記事は Vue.js #3 Advent Calendar 2018 の 10 日目の記事です。

この記事ではVue.jsのスタイルガイドを今一度皆さんにすすめたいと思います。

jp.vuejs.org

Vue.jsのスタイルガイドって?

Vue.jsでコードを書くときに命名や記述順序など細かい設計で議論を呼ばないように公式で公開されているスタイルガイドです。
HTML、JavaScriptのスタイルの言及ではなくVue.jsのスタイルの言及のみを行っています。
例えば、これから紹介するコンポーネントのファイル名だったりプライベートなプロパティ名の命名規則なんかが明記されています。

現実的なことが書いてある

このスタイルガイドは細かいことは議論をスキップできるという意味でいいのものです。
加えて特にいいポイントが、公式が現実的な解を示しているというところです。
この現実的な解というのは例えば昨今のエディタを意識していたりといったことです。

例えば 密結合コンポーネントの名前 の詳細な説明をみて欲しいです。

このスタイルは親コンポーネントと密結合した子コンポーネントは、親コンポーネントの名前をプレフィックスとして含めるというものです。
その中で以下のような記述があります。(一部省略)

この問題を、子コンポーネントを親コンポーネントの名前を元に命名したディレクトリの中に入れることで解決したいと思うかもしれません。
例えば:

components/
|- TodoList/
   |- Item/
      |- index.vue
      |- Button.vue
   |- index.vue

これは推奨されません。以下のような結果を生むからです:
同じような名前のファイルがたくさんできてしまい、コードエディタ上で素早くファイルを切り替えるのが難しくなります。
ネストしたサブディレクトリがたくさんできてしまい、エディタのサイドバーでコンポーネントを参照するのに時間がかかるようになります。

これの正しい例としては下記のようになります。

components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue

このスタイルガイドではこのように、現代のエディタに合わせて開発をしやすいように現実的な解答をしていたりします。

また、コンポーネント名における単語の順番 にあるようにコンポーネント名はそのコンポーネントとして重要な単語を最初にするということも書いてあります。

例えば検索関連のコンポーネントでは、以下のような自然言語のようなコンポーネント名ではなく

components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue

以下のように何に関するコンポーネントなのかを最初に明記するということを推奨しています。

components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputExcludeGlob.vue
|- SearchInputQuery.vue
|- SettingsCheckboxLaunchOnStartup.vue
|- SettingsCheckboxTerms.vue

一般的にエディタではファイルはアルファベット順に並ぶので、コンポーネント間のあらゆる重要な関連性はひと目ではっきりと分かります。

こういった現実的な解を定義しています。

他に

といったことが定義されています。
一部はeslintのプラグインを入れることで自動化が可能なので導入をおすすめします。

github.com

これで快適なVue.jsライフを!

Vue CLIのvue serveが便利

Vue CLIを触っていたらこんなものがあることを知らなかった。
単体でVueのコンポーネントを試したりできるらしい。

cli.vuejs.org

手順としては簡単。

  • npm install -g @vue/cli
  • npm install -g @vue/cli-service-global
  • vue serve [実行したい.vueファイル]

Vue CLIの基本的な設定(webpackやbabel,eslintなど)が適用されてビルドされている。
地味に -o オプションでいちいちコピペしなくてもブラウザが自動で開くか選択できるとか気が聞いている。

だからVueの構文試したいなとかなったらすぐに作ってすぐに試してが出来て便利。
こんな風にコンポーネントを作って。

App.vue

<template>
  <div>
    <h1>Hello!</h1>
    <ul>
      <list-item v-for="item in list" :value="item"/>
    </ul>
  </div>
</template>
<script>
import ListItem from './ListItem.vue';

export default {
  components: { ListItem },
  data() {
    return {
      list: [1,2,3]
    };
  },
};
</script>

ListItem.vue

<template>
  <li>{{ value }}</li>
</template>
<script>
export default {
  props: {
    value: {
      required: true,
      type: Number,
    },
  },
};
</script>

そのまま vue serve -o とするとApp.vueが実行されたブラウザが開かれる。

$ vue serve -o
 INFO  Starting development server...
 98% after emitting                                                           t
 DONE  Compiled successfully in 1146ms                                  11:38:35


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

  Note that the development build is not optimized.
  To create a production build, run npm run build.

JSも実行できるのでVue RouterとかVuexも使えそうかな?
用途としてはコンポーネント単体を試すくらいがちょうどいいかも。

.Net Core MVCでTag Helperを自作する

docs.microsoft.com

.Net Core MVCのRazorではHTML Helperとは別にTag Helperというものが使えるようになっている。
そのTag Helperを自作したときのメモ。

作り方

public class PriceTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "span";
    }
}

実質これだけ。
これでView側のcshtmlに@addTagHelper *,[アセンブリ名]と記述するだけで使用できる。
ちゃんと公式に書いてあるんだけど勝手にここを名前空間を指定するものと思ってハマった。

こんな感じ。

@addTagHelper *,SampleCoreWeb
<price>10000</price>

出力結果

<span>10000</span>

カスタマイズ

上記はただタグを差し替えているだけなのでこれだけじゃ使う意味はない。
なのでカスタマイズしていく。

例えばお金を扱うことにしよう。
よくある要件でお金の値を3桁ごとのカンマ区切りにして末尾に円を付けるとする。
実際どうするかって言うとこうなる。

public class PriceTagHelper : TagHelper
{
    public decimal Value { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "span";
        output.TagMode = TagMode.StartTagAndEndTag;
        
        var yen = Value.ToString("C").Substring(1);
        output.Content.SetContent($"{yen}円");
    }
}
<price value="10000" />

出力結果

<span>10,000円</span>

output.TagMode = TagMode.StartTagAndEndTagというのは<hoge />のような開始終了タグが一つになっているときに、HTMLでは開始終了タグを別にそれぞれ出力するために指定している。
TagHelperを継承したクラスにプロパティを宣言するとそのプロパティ名のケバブケースを属性として扱うことができる。
なのでここではvalue属性を使ってdecimalの値を入れることが出来る。

開始終了を単一のタグにするか分けるのか

今回のような値を入れて終わりという要件であれば開始終了が単一のタグの形式でいいのかなと思う。
開始終了のタグが別である場合というのは、中に文章など落とし込みたい時などで使えるのかな。
一応さらっと今回のケース(カンマ区切りはしてないけど)も載せておく。

public class PriceTagHelper : TagHelper
{
    public decimal Value { get; set; }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "span";
        var content = await output.GetChildContentAsync();
        output.Content.SetContent($"{content.GetContent()}円");
    }
}
<price>10000</price>

カンマ区切り以外は同じ結果が出力される。

<span>10,000円</span>

単一のタグに属性を付与する利点

  • 値を複数付与できる
  • モデルを入れたりも可能
  • 補完が効く

大体属性をうまく使ったほうが利点が大きい。
そもそも組み合わせることも可能なのでうまく使い分けたり組み合わせていきたいところ。

属性の補完が効くのはとてもいい。

f:id:igatea:20180531002111p:plain

Vue.js Tokyo v-meetup #7 に参加してきた

Vue.js Tokyo v-meetup #7 に参加してきました。
vuejs-meetup.connpass.com

募集開始が平日の12時で10分で一般参加枠もLT枠も埋まったのを見てVue.jsは人気なんだなと思いました。
しかも参加率99%と昨今のITイベントだと信じられないくらいの参加率・・・。

そんなイベントのレポートを自分なりにまとめたいと思います。

「結局Nuxt.jsってなにがいいの?」に対する回答

「結局Nuxt.jsって何がいいの?」に対する回答 by potato4d

@potato4d フリーランス

あまりはっきりとした回答がネット上に転がっていないのでそこらへんの話をすると

Nuxtとは

ReactでNext.jsがでて、それにインスパイアされてVue.jsでもできないかと開発が始まった
SSRフレームワークを目指して始まった
すでにSSRツールではなく統合開発ツールの面を持つようになっている
WebpackやBabelなどが準備されている

使うべき理由

開発の足回りを楽にすることができる

今からVue.jsの開発を始めるときになんでもできる
BabelやWebpackといったツールの設定、SSR環境などが揃っている

概念的な話

規約をフロントエンドに持ち込んだ

Nuxt.jsに限らない話・・・
「ここにこう配置したらうまくいくよ」ってもの
開発者はアプリケーションの本質だけに目を向けられるように
日本人的には仕組み化と言える
いわゆる ベストプラクティス勝手にやってくれるマン

規約の利点

オレオレアーキテクチャの排除ができる

こう言ったみんな似たようなことをやってるけど煩雑なものが人の手を離れる

コード品質の最低ラインを担保する

便利だからと作ったutilディレクトリとかcomponentのディレクトリの複雑さとか
plugins / middlewareなどを正しく使うことで使う人自身が楽できる設計に
layouts / pages / composnentsで分かれていたりしている

誰かの主観によって作られたルールはいつか壊れるので規約によって秩序を保つ

規約の良さとは、開発において避けられない開発者のレベル差を吸収すること

全くの初心者だけで書けるわけではない
うまくやってくれるから知らなくてもいいわけではない

規約は単なる頻出のベストプラクティス集
あくまで頻出設計を楽にしてくれるもの

React、Vue、Angularとそれぞれの特徴、規模感によっていい悪いと言われることについて

なぜVue.jsは中小規模向けか
フロントエンドにおける「ちゃんとしてないPHP」みたい
自由度が高すぎる

対してAngularは大規模向けか
Angular Wayに乗れば楽ができる
敷居は高いが人員をスケールさせやすい

これはだいたい「強い」規約

Vue.jsに統一規格を入れることによってレベル差を吸収する
= 人員をスケールさせやすい
= ルールに乗るとラクできる
= Vueの手軽さに堅牢性

Nuxt.jsは機能的なところばかり注目されるが、規約が存在する
規約の概念は大きなメリットと小さなデメリットをもたらす
ちゃんとVue.jsに詳しい人も必要
規約はAngularが近い概念だがこれまでなかった
ルール順守の世界観の影響力が強くなる

LT

最初の講演のあとはLTでした。

Vue.js + D3.jsでグラフを描く

Vue.js + D3.jsでグラフを描く // Speaker Deck

@hogesuke_1 さくらインターネット

コンポーネント分割 X軸、Y軸、パスに分けた

パス
SVGの要素をテンプレートに書く(path要素)
computedでD3のライン関数を用いて描画

X/Y軸
同じくテンプレートに書く(g要素) axisBottomやaxisLeftで同じように描画

アニメーション
CSS transitionを使ったがChromeでしか動かなかった
代わりにTweenLiteを使った
pathのd属性に用いることでアニメーション可能

VUE DESIGNER でコンポーネントGUI で開発する

Vue Designer でコンポーネントを GUI で開発する by katashin

@ktsn

XcodeとかでアプリはGUIで作るけどWebにはないのでそれを作ってみた

VSCodeコンポーネントで描画されるようなものを作った

github.com

拡大縮小したり文字を書き換えてもリアルタイムに反映されていく
プロパティの値を変えたりすることもできるもの
コンポーネントドラッグアンドドロップで入れられるようにもした
Chromeのdevツールで色をコピーしていたようなことも簡単にできるようにした

ロードマップ
1.0でエンジニアが使えるように
2.0でデザイナーが使えるように

(とても面白そうなプロジェクトでした!)

VUEX PLUGIN 101

Vueのプラグインを使うがVuexのプラグインを使ってる人は少ないイメージ
Vuexのプラグインは簡単に作れる
actionではミューテーションの更新が3秒待つといった簡単なものを作った
awesome VueのでもVuexのプラグインが紹介されている

SVG makes your components to testable

SVG makes your components to testable // Speaker Deck

@haribote_nobody

テストしているか HTMLを使ったグラフィカルなものは難しい 期待値はなんなのか

SVGはコードであり文字列、つまり期待値を定めやすい

Jestを使ってテストしていく

初回のこれが期待値となる 期待値が満たせるように裏のロジックを実装していく

Nuxt.js ファーストインプレッション

Nuxt.js ファーストインプレッション / Nuxt.js First Impression // Speaker Deck

@y_temp4 ALIS

フロントはReactかVue、おそらくVueになると思うと入社前に言われた
React経験があったのでVueに対して色々不安があった
触って見た結果Nuxt.js(Vue.js)がいいものだと気付いた

starter-templateの質が高い
vue-cliからNuxtの雛形を生成 そのまますぐに開発を始められる

.vueファイルが管理しやすい
HTML/CSS/JSが1つのファイルで触れる 圧倒的に楽

日本語ドキュメントの充実
全部日本語のドキュメントが揃っていて学習コストが低い

結論
Vueを使った新規プロジェクトでNuxtを使わない手はない 想像以上にVue.jsの敷居は低い

最後に
ALISのソースコードをオープンにしている

github.com

Vue.jsにありがとう

Vuejs meetup

@carotene4035

双方向データバインディングやリアクティブシステム
最近詐欺にあいかけてVue.jsも信用できなくなってきた
それの中身を読んで見た

dataオブジェクトはgetterとsetterとdep.notifyで算出プロパティに通知

Vueのコンポーネント実装パターン

Vue コンポーネント実装パターン // Speaker Deck

@sekikazu01 BizReach

Controlled Component
v-modelと:value="value", @input=this.\$emit('input', $event.target.value)と同じ

transparent Wrappers
公式にもラッパーコンポーネントを作れると書いてある

Building Real-time Vue App

Building Real-time Vue App // Speaker Deck

@joe_re ClassDo CTO

Socket.IO
双方向通信をサポートするイベント通信
Rooms and Namespaces
名前空間を機能ごとに実装

SocketIO with Vuex
SocketIOとVuexを組み合わせるプラグインを自作

github.com

最後に

どの発表もとても面白かったです。
懇親会でも話していてVue.jsを実際に使っている方以外にあまり使っていない方も参加していて、Vue.jsは注目されているなと感じました。
また参加したいと思います!