如何使用 Tailwind 和 Vue.js 动态显示移动菜单?

Posted

技术标签:

【中文标题】如何使用 Tailwind 和 Vue.js 动态显示移动菜单?【英文标题】:How do I dynamically show a mobile menu with Tailwind and Vue.js? 【发布时间】:2020-01-29 03:36:44 【问题描述】:

我正在尝试使用 Tailwind CSS 和 Vue.js 构建响应式菜单。目前我有这个模板:

<template>
<nav class="flex items-center justify-between flex-wrap bg-pink-100 p-6">
    <div class="flex items-center flex-shrink-0  mr-6">
        <span class="font-semibold text-xl tracking-tight">Pixie</span>
    </div>
    <div class="block md:hidden" >
        <button @click='clickMenu' class="flex items-center px-3 py-2 border rounded" >
        <svg class="fill-current h-3 w-3" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>Menu</title><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>
        </button>
    </div>
    <div class="w-full flex-grow md:flex md:items-center md:w-auto" v-if="menuVisible">
        <div class="text-sm md:flex-grow">
        <a href="#responsive-header" class="block mt-4 md:inline-block md:mt-0 hover:text-white mr-4">
            Features
        </a>
        <a href="#responsive-header" class="block mt-4 md:inline-block md:mt-0  hover:text-white mr-4">
            Pricing
        </a>
        <a href="#responsive-header" class="block mt-4 md:inline-block md:mt-0  hover:text-white">
            Blog
        </a>
        </div>
        <div>
        <a href="#" class="inline-block text-sm px-4 py-2 leading-none border rounded  text-white bg-blue-500 hover:border-transparent mt-4 md:mt-0">Sign Up</a>
        <a href="#" class="inline-block text-sm px-4 py-2 leading-none border rounded  hover:border-transparent mt-4m d:mt-0">Log In</a>
        </div>
    </div>
</nav>
</template>

使用这个 javascript

<script>
export default 
    data: function() 
        return 
            menuVisible: true
        
    ,
    methods: 
        clickMenu: function() 
            this.menuVisible = !this.menuVisible
        
    


</script>

我想要做的只是当断点到达 Tailwind 上的“sm”时隐藏移动菜单。这意味着用户必须单击菜单按钮才能看到菜单,我认为这是移动设备上的预期行为。

我不想构建 2 个单独的菜单,它们会显示在不同的断点上,因为我想避免重复代码。有没有办法在 Vue.js 中访问 Tailwind 的当前断点?这意味着我可以将 menuVisible 设置为一个计算属性,该属性仅在断点是桌面或平板电脑或用户单击菜单时才允许它可见。

或者还有其他更好的方法吗?

感谢您的帮助!

【问题讨论】:

【参考方案1】:

实现此目的的一种方法是在您的tailwind.config.js 中配置TailwindCSS-breakpoints,然后重用该文件将断点值导入您的菜单组件。

这里我们根据the TailwindCSS documentation设置TailwindCSS断点。我们实际上只是设置了默认的 TailwindCSS 断点值,但是设置它们可以通过文件访问它们。

//tailwind.config.js

module.exports = 
  theme: 
    screens: 
      sm: '640px',
      md: '768px',
      lg: '1024px',
      xl: '1280px'
    
  

现在,在您的 Menu.vue 中,您可以从 TailwindCSS-config 中导入断点并编写必要的函数,以检查当前窗口大小是否小于md-断点。如果不是,您可以简单地返回true。如果是,您可以检查菜单是否已打开。

// Menu.vue
<script>
const tailwindConfig = require('tailwind.config.js')

export default 
  data() 
    return 
      windowWidth: 0,
      menuOpen: false,
      mdBreakpoint: Number(tailwindConfig.theme.screens.md.replace('px', ''))
    
  ,
  computed: 
    menuVisible() 
      return this.windowWidth > mdBreakpoint ? true : this.menuOpen

    
  ,
  methods: 
    updateWindowSize() 
      this.windowWidth = window.innerWidth
    ,
    clickMenu() 
      this.menuOpen = !this.menuOpen
    
  ,
  mounted() 
    this.updateWindowSize()
    window.addEventListener('resize', this.updateWindowSize)
  ,
  beforeDestroyed() 
    window.removeEventListener('resize', this.updateWindowSize)
  

</script>

【讨论】:

【参考方案2】:

你可以在你的应用程序中为它编写一个插件并导入它,我正在使用 nuxt,这对我有用

export default (context, inject) => 
  const burger = () => 
    const menu = document.querySelector("#menu");

    if (menu.classList.contains("hidden")) 
      menu.classList.remove("hidden");
     else 
      menu.classList.add("hidden");
    
  ;
  inject("burger", burger);
  context.$burger = burger;
;

【讨论】:

以上是关于如何使用 Tailwind 和 Vue.js 动态显示移动菜单?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Vue.js 和 Tailwind 基于数组中的元素有条件地将多个类添加到 <span>?

将 Tailwind.css 添加到 Vue.js 项目后,某些类没有效果

带有 Vue js 道具的反应式 Tailwind 类

如何在 Laravel InertiaJS 中使用 VueJS 配置 Tailwind + Postcss

OctoberCMS (Laravel) + Vue.js + Tailwind CSS 最佳设置

错误:加载 PostCSS 插件失败:令牌无效或意外(Vue.js、tailwind css)