パンくずコンポーネントと範囲選択するコンポーネントについて


本当は vue-test-loader× jest の記事について書きたかったのですが間に合いませんでしたので、最近自分で作って地味に便利だと感じたSFC(単一ファイルコンポーネント)の紹介をしたいと思います。

クリック時に範囲選択するコンポーネント

最近ではコピーボタンが主流ですが、個人的にはぱっと見て気づかないことが多く直感的じゃないと思う時があります。
そのためついつい直接対象をドラッグしてコピーしがちです。
以下のようにコンポーネントを定義し、対象をクリックするだけでコンポーネントで囲った範囲を直接選択できるようにしコピーしやすいコンポーネントを作成しました。
やっていることはクリックイベント時にDOMレンジを使って対象範囲を選択するシンプルなものです。

demo TodoListのタスクをクリックすると選択します。

  1. 範囲選択するコンポーネントを定義(今回はLineSelector.vue と定義しています)
// LineSelector.vue
<template>
  <span @click="clickedSelect" ref="selectText">
  <slot />
  </span>
</template>

<script>
export default {
    methods: {
        clickedSelect () {
      const range = document.createRange()
      range.selectNodeContents(this.$refs.selectText)
      const selection = window.getSelection()
      selection.removeAllRanges()
      selection.addRange(range)
        }
    }
}
</script>
  1. 定義したコンポーネントを読み込み、選択範囲を<line-selector>で囲みます。
    以下のコードではTodoList のtextをコピーできるようにしております。
<template>
  <li>
    <line-selector>{{ todo.text }}</line-selector>
    <button @click="$emit('remove', todo.id)">
      X
    </button>
  </li>
</template>

<script>
import LineSelector from './LineSelector.vue'

export default {
    components: {
        LineSelector
    },
  props: {
    todo: {
      type: Object,
      required: true
    }
  }
}
</script>

パンくずコンポーネント

vueでパンくずを用いる場合、既にvue-breadcrumbsといったpluginが既にあるのですがより柔軟に対応する必要があったため、以下のようにコンポーネントを作成しました。

  1. パンくずコンポーネントを定義
// Breadcrumb.vue
<template>
  <ul :class="$style.list">
    <li :class="$style.item" v-for="(crumb, key) in breadcrumbs" :key="name">
      <span v-if="crumb.path"><nuxt-link :to="crumb.path" >{{ crumb.name }}</nuxt-link></span>
      <span v-else>{{ crumb.name }}</span>
    </li>
  </ul>
</template>

<script>
export default {
  props: {
    breadcrumbs: {
      type: Array
    }
  }
}
</script>

<style>
.list {
  list-style: none;
  text-align: left;
  margin: 0;
}
.item {
  display: inline-block;
}
.item::after {
  content: '>';
  display: inline-block;
}
.item:last-child::after {
  content: none;
}
</style>

  1. 定義したコンポーネントを読み込み、pathと表示名を持ったオブジェクトをpropsで渡すとパンくずリストが表示されます。以下の場合だとほげ > ふが といった表示をします
<breadcrumb :breadcrumbs="breadcrumbs" />
<script>
import Breadcrumb from './Breadcrumb.vue'

export default {
  components: {
    Breadcrumb,
  },
  data: function () {
    return {
      breadcrumbs: [
        {
          name: 'ほげ',
          path: '/hoge'
        },
        {
          name: 'ふが'
        }
      ]
    }
  },

}
</script>

まとめ

Vue.jsに触れて半年くらいになりますが、SFCは柔軟すぎると思えるくらいとても便利です。
今後はvue-i18nと連携してブロックで定義したものをそのままパンくずとして表示して使えるようにした
Nuxt,Vueプラグインがあると便利だよねという話が出たので勉強のためにも是非作ってみたいと思いました。