※スマホ対応はしてません。

タグ: vue

配列の要素挿入、置き換えもsplice()で。Vue.jsでも大丈夫。(配列とかおれおれAdvent Calendar2018 – 07日目)

カテゴリー: JavaScript

LINDORのAdvent Calendar(本物)の7日目を開けたところ。
配列とかおれおれAdvent Calendar2018 – 07日目

削除を splice() でやれました。

同じく挿入も splice() を使ってやれます。

const arr = [11, 22, 33];

const index = 1;
const value = 99;
arr.splice(index, 0, value);
console.log(arr); // => [ 11, 99, 22, 33 ]

さらに置換もできます。

const arr = [11, 22, 33];

const index = 1;
const value = 99;
arr.splice(index, 1, value);
console.log(arr); // =>[ 11, 99, 33 ]

第2引数を 0 にするとただ挿入するだけ、 1 だと置き換えます。

仕様

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

昨日書いた通りだけど、 item1, item2, ... を挿入します。 複数可能。

Vue.jsで配列を置き換え

普通に置き換えたい場合は arr[i] = obj すれば十分なんだけど、Vue.jsの data で配列を持っている場合、それは「やってはいけないこと」です。

splice() でなら、それができます。

動かない例

ボタンを押すと配列要素のひとつを別のオブジェクトに置き換えるようにしました。

const index = 1;
const item = { text: "REPLACED", done: false };

this.todos[index] = item;

置換しても、次の再描画まで反映されない。

動く例

続いて splice() を使った、動くコード。

const index = 1;
const item = { text: "REPLACED", done: false };

this.todos.splice(index, 1, item);

置換するとすぐ反映される。

詳しくはVue.jsの公式文書をご確認くださいまし。

その他の変更

配列の要素全体じゃなくて要素のプロパティを変えるのはセーフ。

あと配列全体を代入しちゃうのもセーフ。

順序を変えるなら sort()

splice() で置き換えても良いけど、よっぽどの量でなければ sort() してできあがる配列全体をプロパティに設定してやるのが簡単で良いでしょう。

例

話をVue.jsからJavaScript全体に戻します。

配列を追加

追加する要素は第3引数だけでなく、第4、第5といくらでも与えられます。

配列をまるごと追加する場合、スプレッド構文 ... で展開してやりましょう。

const arr = [11, 22, 33];
const values = [99, 88];

const index = 1;
arr.splice(index, 0, ...values);
console.log(arr); // => [ 11, 99, 88, 22, 33 ]

配列をそのまま置くと、その配列自体が全体の配列の要素になっちゃいます。二重配列だ。

検索して置き換え

findIndex() と組み合わせます。

const users = [
  { id: '101', name: 'Alice' },
  { id: '102', name: 'Bob' },
  { id: '103', name: 'Charlie' },
];
const value = { id: '999', name: 'Zack' };

const id = '102';
const index = users.findIndex((v) => v.id === id);

users.splice(index, 1, value);
console.log(users);
// => [ { id: '101', name: 'Alice' },
//      { id: '999', name: 'Zack' },
//      { id: '103', name: 'Charlie' } ]

その他のメソッド

普通に置き換えるなら [index]

でいいよね。

末尾に追加するなら push()

これはこれでよく使う。

末尾に複数追加するなら concat()

ただし非破壊で、新しい配列を作ります。

const arr = [11, 22, 33];
const values = [99, 88];

const arr2 = arr.concat(values);
console.log(arr); // => [ 11, 22, 33 ]
console.log(arr2); // => [ 11, 22, 33, 99, 88 ]

values.concat(arr) にすれば先頭に追加したものが出てきます。

先頭に追加するなら unshift()

各要素のプロパティを置き換えるなら forEach()

うーん何というか、繰り返しながら更新するだけ。

const users = [
  { id: '101', name: 'Alice', active: true },
  { id: '102', name: 'Bob', active: true },
  { id: '103', name: 'Charlie', active: true },
];

users.forEach((user) => {
  user.active = false;
});

おしまい

関連

参考

CSS transformのmatrix()を一瞬で 完 全 理 解 できるやつ作ったよ。

カテゴリー: CSS

というわけでお探しの完全理解はこちらです。

スマホでも存分にご理解頂けます。

見た目

こんな感じ。

この動画だけでも十分理解できそう。

matrix() とは

動かして完全理解して頂きましたら、改めてこの関数を紹介したいと思います。

(さらに…)

Nuxt 1→2にしたらpug-loaderからpug-plain-loaderに変わったっぽい。

カテゴリー: JavaScript

結論

入れ替えましょう。

$ yarn remove pug-loader
$ yarn add pug-plain-loader

日記

Nuxt.jsのバージョンを1.4.0から2.1.0へ上げたら、 yarn dev で文句言われるようになった。

 Cannot find module './index.vue?vue&type=template&id=2a183b29&scoped=true&lang=pug&' 

エラー内容が謎すぎる。

諸事情により yarn build を試したところ、こっちは分かりやすいエラーが出てきてくれた。

ERROR in ./components/FooBar.vue
Module not found: Error: Can't resolve 'pug-plain-loader' in '/mnt/c/Users/ginpei/projects/sugoi-yatsu'
 @ ./components/FooBar.vue 1:0-105 10:2-8 11:2-17
 @ ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./components/AnalogClock.vue?vue&type=script&lang=js&
...

リリースノートの移行ガイドには載ってないけど、プリプロセッサを使うには?の最後の方にこうある。

これらのプリプロセッサを使うために Webpack のローダーをインストールする必要があります。

npm install --save-dev pug@2.0.3 pug-plain-loader coffeescript coffee-loader node-sass sass-loader

追っかけてないのでいつ変わったのか、なんで変わったのか知らないんだけど、 pug-loader ではないらしい。

試してみたら1系最新の1.4.2では pug-loader で動いて、2系最初の2.0.0では pug-plain-loader が必要だった。へー。

というわけで冒頭の結論の通り入れ替えて動きました。めでたし、めでたし。

Nuxt.js他で時計アプリ (PWA) を作ってみたよ。

カテゴリー: JavaScript

ええいや時計って……という感じはあるんだけど、とにかくNuxt.jsを使ってみたかったのです。あと自分では使う。

できあがったもの

アナログ時計が左に、デジタル時計が右に。あとポモドーロタイマー付き。

使った技術

ライブラリ、フレームワーク

ツール

ウェブ標準API

サービス

技術系感想

Nuxt.js

この記事の影響。

なんか久しぶりに「動くものがさくさく作れる」という快感を味わうことができたフレームワーク。Ruby on Railsにこなれてきた頃の快感を思い出しました。

vue-cli使って入れたんだけど、最初からディレクトリとか開発用サーバーとか、各種ビルドとか即時部分更新 (HMR) とか、追加のあれこれなしに書くだけですぐ動く。黒魔術的な感じなのもRailsっぽい。いや別にRailsと比べるものじゃないんだけど。

今回は静的HTML (SSR) でやったけど、そのうち動的なやつもやってみたい。Firebaseでホストすればできると聞いたような気がする? 未調査。別に # なURLでも構わないけども。

vue-cilで入れるやつのコマンド(公式ドキュメントより):

$ npx vue-cli init nuxt-community/starter-template my-project

Nuxt + PWA

こいつを yarn add するだけでわりとすぐ動いた。お手軽便利。これを導入するだけで用が済んでしまったので、ServiceWorkerも自前では書いてないです。

ドキュメントはあんまり親切じゃない感じがする。まだ使い方とかがあんまりわかってない。

Visual Studio Code

ずっとVimを使ってきたんだけど(最近はNeoVim)、ちょっと人に教えるのにこれはあれだよなーと思って「普通のエディター」として使い始めてみました。あらでも良いじゃない。

スクリーンショット。公式サイトから。

後発なうえに開発体制が盤石なだけあって、さすがに出来が良い。各種OSに対応している点、インストールしてすぐ使える点、プラグインが豊富かつ導入や管理も楽な点、日本語対応している点から、今後は人様にお勧めしていこうかなと思っております。

最初に導入してほしいプラグイン:

  • Code Spell Checker
  • EditorConfig
  • ESLint(JS系のひと向け)

ただ、スクロールがなかなかちょっと。これはCodeじゃなくてたぶんElectron for Windowsの問題で、Slack.exeなんかでも起こる。どうも onscroll で何かやってるとうまくスクロールが動かなくなるみたい。詳細未調査だけど、たしか自分が作ったアプリだとそんな感じだった。まあだいたいの人はMacだから問題ないね……。

あとVimプラグインはキー操作が衝突するんで、案の定アレでした。

CSS Grid

何度か使ったことあったかな。気がつけば一通りのブラウザサポートが揃っていたので。

CSS Gridは全てのモダンブラウザで動作する。画像はgrid-templateプロパティの場合。

今回複雑なレイアウトをしてはいないけれども、別にそんじょそこらの細かいところでも割と気軽に使えるので、今後はがしがし使って行きたい。

今回使ったのは右側半分。”T”の字に区切ってます。

GitHub Pages + Cloudflare

今回は全部静的ファイルなので、GitHub Pagesで公開してCloudflareでhttps化。

これも簡単にできて楽だったので、今後は同じようにサブドメインにどんどん生やしていく感じで色々作っていこうかなと思いました。

作業内容はこれ↓。

yarn

普段はnpmの方を使っているんだけど、今回はなんとなくこっちに。インストールが早いとかは聞いてるけれども、うーん特に不満はないけど利点を感じるほどでもなかった。npmも今はロックファイルあるし、普通にインストールしたら記録されるしなあ。

アプリの紹介

時計です。

ポモドーロのタイマー付きです。

おしまい

楽しかった。

Vue.jsで文字列が空のとき “Mismatching childNodes vs. VNodes” になった。

カテゴリー: JavaScript

Vue.jsで、こんなエラー(というか警告)が出た。

console.error()で &quot:[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content."

[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

再現コード

はこんな感じ。

<template>
  <section>
    <p><img />{{text}}</p>
  </section>
</template>

<script>
export default {
  data () {
    return {
      text: '',
    }
  },
}
</script>

たぶん、 <p> の直下には「 <img> 」と「 {{text}} から成るテキストノード」の二つがあるはずなんだけど、文字列が空だとそこにテキストノードが用意されないので、なんか予定と違うぞーと怒ってる感じだろうか。

解決策

とにかくテキストノードが存在していれば良いので、空白文字とか置いておこう。

text: '' を text: ' ' にするとか、同様に <template> の方にスペース追加するとか。

余白が嫌なら幅なしのやつ &zwnj; にしよう。

<template>
  <section>
    <p><img />&zwnj;{{text}}</p>
  </section>
</template>

とっぴんぱらりのぷう。