Vue コンポーネントのスタイルを MediaQuery のブレイクポイントごとに切り替える指定を親コンポーネントから渡す

タイトルだけでは何を言ってるかわからないと思うんですが、親要素から

```vue:Parent.vue
<template>
  <Child
    :transforms="{
      pc: 'large',
      tb: 'medium',
      sp: 'small',
    }"
  />
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import Child from '~/Child.vue'

export default defineComponent({
  components: {
    Child,
  },
})
</script>
```

のような感じでブレイクポイントごとに特定のキーを渡してあげることで、「このページの要素A の中にある Child は PC が `large`、SP が `small`。要素B の中にある Child は PC が `medium`、SP が `small`」みたいなことが指定できるようになります。

スクリプトで CSS のメディアクエリみたいな処理を書くのでもいいんですが、CSS と二重管理になるので極力避けたいですよね。


```vue:Child.vue
<template>
  <div
    class="example"
    :data-transform-pc="dataTransformPc"
    :data-transform-tb="dataTransformTb"
    :data-transform-sp="dataTransformSp"
  >
    <p>ほげ</p>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'

const TRANSFORM_CODE_S = 'small'
const TRANSFORM_CODE_M = 'medium'
const TRANSFORM_CODE_L = 'large'

type TransformCodes =
  | typeof TRANSFORM_CODE_S
  | typeof TRANSFORM_CODE_M
  | typeof TRANSFORM_CODE_L

type Transforms = {
  pc: TransformCodes
  tb: TransformCodes
  sp: TransformCodes
}

export default defineComponent({
  props: {
    transforms: {
      type: Object as PropType<Transforms>,
      required: true,
    },
  },
  setup(props) {
    const dataTransformPc = computed(() => props.transforms.pc)
    const dataTransformTb = computed(() => props.transforms.tb)
    const dataTransformSp = computed(() => props.transforms.sp)

    return {
      dataTransformPc,
      dataTransformTb,
      dataTransformSp,
    }
  },
})
</script>

<style lang="scss" scoped>
$size-width-tb: 480px;
$size-width-pc: 768px;

@mixin is-sp-screen() {
  @media screen and (max-width: #{$size-width-tb - 1}) {
    @content;
  }
}

@mixin is-tb-screen() {
  @media screen and (min-width: $size-width-tb) and (max-width: #{$size-width-pc - 1}) {
    @content;
  }
}

@mixin is-pc-screen() {
  @media screen and (min-width: $size-width-pc) {
    @content;
  }
}

@mixin small {
  width: 240px;
  height: 240px;
  background: #eee;
}

@mixin medium {
  width: 360px;
  height: 360px;
  background: #ccc;
}

@mixin large {
  width: 480px;
  height: 480px;
  background: #aaa;
}

.example {
  &[data-transform-pc='small'] {
    @include is-pc-screen() {
      @include small;
    }
  }
  &[data-transform-tb='small'] {
    @include is-tb-screen() {
      @include small;
    }
  }
  &[data-transform-sp='small'] {
    @include is-sp-screen() {
      @include small;
    }
  }

  &[data-transform-pc='medium'] {
    @include is-pc-screen() {
      @include medium;
    }
  }
  &[data-transform-tb='medium'] {
    @include is-tb-screen() {
      @include medium;
    }
  }
  &[data-transform-sp='medium'] {
    @include is-sp-screen() {
      @include medium;
    }
  }

  &[data-transform-pc='large'] {
    @include is-pc-screen() {
      @include large;
    }
  }
  &[data-transform-tb='large'] {
    @include is-tb-screen() {
      @include large;
    }
  }
  &[data-transform-sp='large'] {
    @include is-sp-screen() {
      @include large;
    }
  }
}
</style>
```

ブラウザで画面幅を変えると、スタイルが一緒に変わります。
ただ、この方法だと子コンポーネント自体を切り替える　みたいなことはできません。

※ 実際は tb, sp の指定は任意で、指定がなければ pc を受け継ぐみたいな処理を書いてますが、割愛してます。
※ Vue.js 以外にも、React とかでもアイデアは流用できると思います。

-----

`@mixin is-xx-screen() {}` については https://qiita.com/les-r-pan/items/202cc75bd4da5170fe10