タイトルだけでは何を言ってるかわからないと思うんですが、親要素から
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 と二重管理になるので極力避けたいですよね。
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