Vue 和 Bootstrap:如何根据媒体断点显示不同的组件?最新的共识是什么?

red*_*ift 3 vuejs2 bootstrap-vue

我正在对应用程序执行我的第一个“移动优先”方法(通常从桌面开始,过去使用 CSS 媒体查询按我的方式工作),并想知道在当今响应式开发环境中处理以下场景的最佳方法是什么:

我有一个像这样的组件:

<b-form-spinbutton id="sb-vertical" v-model="value" inline></b-form-spinbutton>
Run Code Online (Sandbox Code Playgroud)

我希望上面的组件仅在设备低于某个断点时显示(假设低于 720px)。

然后,任何大于我想显示以下组件的视口:

<b-form-spinbutton id="sb-vertical" v-model="value" vertical></b-form-spinbutton>
Run Code Online (Sandbox Code Playgroud)

注意上面代码中的verticalinline道具。

这些最好留给传统的 CSS 媒体查询,还是我们能够使用模板条件(即 v-if?等)。

我想我会达成共识,因为我将根据收到的对此问题的任何反馈从头开始构建我的应用程序。谢谢!

Hiw*_*iws 5

我写了一个基本的 util(有改进的空间),它创建了一个对象。可以导入并在模板中使用。当您想根据当前断点重新更改道具时。

该对象包含各种断点,如果它是当前活动的断点。同样,它包含一个嵌套的lt(小于)和gt(大于)对象,当您希望在某个断点之上或之下显示某些内容时,可以使用该对象。

请注意,这尚未针对 SSR(Nuxt 和 simliar)进行测试,并且可能无法正常工作,因为它访问window.

BreakpointsUtil.js

import Vue from "vue";

const state = Vue.observable({
  screen: {}
});

/* This assumes you're using default bootstrap breakpoint names */
/* You need to hardcode the breakpoint values if you want to support IE11 */
const style = getComputedStyle(document.body);
const xs = style.getPropertyValue("--breakpoint-xs").replace("px", "");
const sm = style.getPropertyValue("--breakpoint-sm").replace("px", "");
const md = style.getPropertyValue("--breakpoint-md").replace("px", "");
const lg = style.getPropertyValue("--breakpoint-lg").replace("px", "");
const xl = style.getPropertyValue("--breakpoint-xl").replace("px", "");

function onResize() {
  const width = window.innerWidth;

  /* Not really sure how to properly define gt or lt */
  state.screen = {
    xs: width >= xs && width < sm,
    sm: width >= sm && width < md,
    md: width >= md && width < lg,
    lg: width >= lg && width < xl,
    xl: width >= xl,
    /* Greater than */
    gt: {
      xs: width >= xs,
      sm: width >= sm,
      md: width >= md,
      lg: width >= lg,
      xl: width >= xl
    },
    /* Less than */
    lt: {
      xs: width < sm,
      sm: width < md,
      md: width < lg,
      lg: width < xl,
      xl: width < 9999
    }
  };
}

/* Might want to debounce the event, to limit amount of calls */
window.onresize = onResize;
onResize();

export default state;
Run Code Online (Sandbox Code Playgroud)

然后可以像这样导入(找不到更好的方法将其公开给模板并保持反应性)

随机组件.vue

<template>
 <!-- Some HTML -->
</template>

<script>
import breakpoints from "@/utils/breakpoints";

export default {
  computed: {
    breakpoints: () => breakpoints.screen
  }
};
</script>
Run Code Online (Sandbox Code Playgroud)

示例代码段(稍微重写以适合代码段)

/* BreakpointUtil.js */
const state = Vue.observable({
  screen: {}
});

/* This assumes you're using default bootstrap breakpoint names */
/* You need to hardcode the breakpoint values if you want to support IE11 */
const style = getComputedStyle(document.body);
const xs = style.getPropertyValue("--breakpoint-xs").replace("px", "");
const sm = style.getPropertyValue("--breakpoint-sm").replace("px", "");
const md = style.getPropertyValue("--breakpoint-md").replace("px", "");
const lg = style.getPropertyValue("--breakpoint-lg").replace("px", "");
const xl = style.getPropertyValue("--breakpoint-xl").replace("px", "");

function onResize() {
  const width = window.innerWidth;

  /* Not really sure how to properly define gt or lt */
  state.screen = {
    xs: width >= xs && width < sm,
    sm: width >= sm && width < md,
    md: width >= md && width < lg,
    lg: width >= lg && width < xl,
    xl: width >= xl,
    /* Greater than */
    gt: {
      xs: width >= xs,
      sm: width >= sm,
      md: width >= md,
      lg: width >= lg,
      xl: width >= xl
    },
    /* Less than */
    lt: {
      xs: width < sm,
      sm: width < md,
      md: width < lg,
      lg: width < xl,
      xl: width < 9999
    }
  };
}

/* Might want to debounce the event, to limit amount of calls */
window.onresize = onResize;
onResize();
/* BreakpointUtil.js END */

new Vue({
  el: "#app",
  computed: {
    screen: () => state.screen 
  }
});
Run Code Online (Sandbox Code Playgroud)
<link href="https://unpkg.com/bootstrap@4.5.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.15.0/dist/bootstrap-vue.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.15.0/dist/bootstrap-vue.js"></script>

<div id="app">
  <b-card no-body>
    <b-tabs pills card :vertical="screen.lt.sm">
      <b-tab title="Tab 1" active>
        <b-card-text>Tab contents 1</b-card-text>
      </b-tab>
      <b-tab title="Tab 2"><b-card-text>Tab contents 2</b-card-text></b-tab>
      <b-tab title="Tab 3"><b-card-text>Tab contents 3</b-card-text></b-tab>
    </b-tabs>
  </b-card>
</div>
Run Code Online (Sandbox Code Playgroud)