Vuetifyで画面サイズで変わるBreakpointsを使って表示するスタイルや文字数を制限した話

# 画面サイズ毎に表示する文字数制限したい！！

今回Vueitfyを使ってレスポンシブな細かいスタイル調整を行おうと思ったんですが
文字列の長さが不明確で且つ改行ありのデザインだったので少々手こずってしまいました。

Vuetifyでうまくやる方法があるのかも知れませんが、今回はこのような形で解決しました。

## 結論: $vuetify.breakpointとtruncateを使う

#### 概要

- `$vuetify.breakpoint`でlgやmdといったブレークポイントを取得
- `$vuetify.breakpoint`はtemplate上でも使える
- styleなどに必要な要素を変数に代入（computedで定義すると動的に変わる）
- truncateメソッドを使って文字切り捨て
- cssの`text-overflow`は改行無しなら使える！（veutifyのclassなら`text-truncate`）

※ templateにはVuetifyを使っているものとします

```vue

<template>
  <div>
    <!-- 高さをブレークポイントで動的に変える -->
    <v-card :height="bkPoint.cardHeight">
      <v-card-title>
        {{ title | truncate(bkpoint.titleLength) }}
      </v-card-title>
        <!-- 省略の末尾を指定する -->        
        {{ text | truncate(bkpoint.textLength, '...続き') }}
      </v-card-text>
      <v-card-text>
    </v-card>
  </div>
</template>

<script>
export default {
  filter: {
    /**
    * 文字を切り捨てる [色んな所で使うので共通化するといいよ！]
    * @param {String} text
    * @param {Number} length
    * @param {String} clamp
    */
    truncate (text, length, clamp) {
      text = text || ''
      clamp = clamp || '...'
      length = length || 30

      if (text.length <= length) return text
      return text.substring(0, length) + clamp
    }
  },
  data() {
    return {
       title: 'タイトルは長くても改行なしなら省略する方法が色々ある',
       text: 'テキストは改行ありだとcssだけで対処しきれないのでtrancate関数を作って対応する'
    }
  },
  computed: {
    bkPoint () {
      // $vuetify.breakpointでブレークポイントを取得
      const bkPt = this.$vuetify.breakpoint
      const point = { name: bkPt.name, cardHeight: 200, titleLength: 10, textLength: 15 }
      switch (bkPt.name) {
        case 'xl':
          point.titleLength = 30
          point.textLength = 100
          point.cardHeight = 150
          break
        case 'lg':
          point.titleLength = 20
          point.textLength = 80
          point.cardHeight = 150
          break
        case 'md':
          point.titleLength = 10
          point.textLength = 60
          point.cardHeight = 350
          break
        case 'sm':
          point.titleLength = 10
          point.textLength = 100
          point.cardHeight = 570
          break
        case 'xs':
          point.titleLength = 8
          point.textLength = 100
          point.cardHeight = 600
          break
        default:
          break
      }
      return point
  }
}
</script>
```

### truncateメソッドを共用で定義しよう

こんな感じの処理が書かれたファイルを定義して使いたいところで呼び出してあげよう。

```js
import Vue from 'vue'

/**
 * 文字数を制限して余分があれば省略して末尾...に置換する
 * @param {String} text
 * @param {Number} length
 * @param {String} clamp
 * @returns {String}
 */
Vue.filter('truncate', (text, length, clamp) => {
  text = text || ''
  clamp = clamp || '...'
  length = length || 30

  if (text.length <= length) { return text }
  return text.substring(0, length) + clamp
})
```

### $vuetify.breakpoint

https://vuetifyjs.com/en/customization/breakpoints/

このようにテンプレート内に直接書き込んでコードを書くことを放棄する方法も取れます。

```vue
<template>
  <v-dialog :fullscreen="$vuetify.breakpoint.xsOnly">
    ...
  </v-dialog>
</template>
```

このようにcomputedなどで動的に変動する値として使うこともできます

```vue

<script>
export default {
  computed: {
    breakpointName () {
      return this.$vuetify.breakpoint.name // ex: 'lg'
    }
  }
}
</script>
```