使用导出默认值从另一个JavaScript模块检查变量状态

使用导出默认值从另一个JavaScript模块检查变量状态,javascript,Javascript,我有两个Javascript模块,一个用于导航,一个用于路线更改 如果要检查菜单是否可以打开,nav.js的内部很简单 const initNav = () => { const openMenu = () => { if (!menuIsOpen && isMobile) { navItems.classList.add("is-menu-open"); menuIsOpen = true; } else {

我有两个Javascript模块,一个用于导航,一个用于路线更改

如果要检查菜单是否可以打开,nav.js的内部很简单

const initNav = () => {
  const openMenu = () => {
    if (!menuIsOpen && isMobile) {
      navItems.classList.add("is-menu-open");
      menuIsOpen = true;
    } else {
      navItems.classList.remove("is-menu-open");
      menuIsOpen = false;
   }
 }
}

initNav();

export default initNav;
然后,在另一个模块的顶部,我导入

import initNav from './nav.js';
问题是,在我的另一个模块
route.js
中,我需要能够检查菜单是否打开,如果打开,则关闭它,因此我将使用:

 beforeLeave: function (data) {
    if (menuIsOpen) {
      navItems.classList.remove("is-menu-open");
      menuIsOpen = false;
    }
 }
但是,控制台显示未定义
menuIsOpen

我无法通过这种方式检查此变量的状态


我是否可以用另一种方式来实现这一点,而不是将两个模块组合成一个非常大的js模块

尝试getter/setter或导出变量menuIsOpen

 beforeLeave: (data) => {
    if (menuIsOpen) {
      navItems.classList.remove("is-menu-open");
      menuIsOpen = false;
    }
 } 

问题是您试图重新分配存在于多个模块中的变量,但导入的变量是-它们只能在其原始模块中重新分配。因此,您不能仅从
nav.js
导出
menuIsOpen
,因为不允许在
route.js
中重新分配它

您可以让
nav.js
导出一个函数,该函数在导出
menuisupen
的同时重新分配其
menuisupen
,但是,可重新分配的导出通常是不直观的——Javascript中没有任何其他地方会因为不同的模块重新分配绑定而进行类似于对原始值的引用的重新分配。门楣经常禁止它们

一个更好的选择是
menuIsOpen
的主要用户将setter和getter函数导出到
menuIsOpen
接口。例如,您可以执行以下操作:

// nav.js
export const getMenuIsOpen = () => menuIsOpen;
export const setMenuIsOpen = (newVal) => menuIsOpen = newVal;
// ...

对于任何需要在多个地方访问和可变的单个变量的复杂情况,可以考虑导出对象,例如:

// nav.js
export const navState = {
  menuIsOpen: false,
  // other properties
};
// ...
必须跨多个模块处理可变状态会使代码有点难看。我宁愿尽量避免。考虑到问题中的代码,由于您在两个模块中都已经有了对
navItems
的引用,如果您只需检查
navItems
类列表是否有
菜单打开
,就可以避免使用持久的
menuIsOpen
变量:

// nav.js
// ...
const openMenu = () => {
  // defining menuIsOpen as a standalone variable isn't necessary,
  // but you might find it makes the code more readable
  const menuIsOpen = navItems.classList.contains('is-menu-open');
  if (!menuIsOpen && isMobile) {
    navItems.classList.add("is-menu-open");
  } else {
    navItems.classList.remove("is-menu-open");
 }
}
// ...
如果在
nav.js
中确实需要一个独立的
menuIsOpen
变量,您可以让
nav.js
导出一个函数,该函数可以关闭菜单并将
menuIsOpen
设置为false:

// nav.js
// ...
export const closeMenu = () => {
  navItems.classList.remove("is-menu-open");
  menuIsOpen = false;
};
// ...

(如果在离开之前
beforeLeave
在实际代码中除了检查类是否存在并删除它之外没有做任何其他事情,那么您不需要首先检查类是否存在-您可以无条件地将其从类列表中删除-这也可以应用于答案中的所有其他片段)

您的
menuIsOpen
变量声明在哪里?您的
route.js
模块不必处理
menuIsOpen
变量、
navItems
或它们的类。它应该只需要调用一个
closeMenu()
函数,该函数应该与
openMenu
@MickaelB一起从导航模块导出。在我的nav.js文件中,使用本地存储来记住菜单打开,并从route.js获取它来检查您更改了什么以及为什么更改?在离开之前:(数据)=>{}我将normal函数改为arrow函数,menuIsOpen在函数之外(这意味着它被用作全局变量),因此它无法识别normal函数。改为arrow函数不会影响任何事情。在OPs代码中,
menuIsOpen
变量已经是全局变量(未在该函数中声明)?
// nav.js
// ...
const openMenu = () => {
  // defining menuIsOpen as a standalone variable isn't necessary,
  // but you might find it makes the code more readable
  const menuIsOpen = navItems.classList.contains('is-menu-open');
  if (!menuIsOpen && isMobile) {
    navItems.classList.add("is-menu-open");
  } else {
    navItems.classList.remove("is-menu-open");
 }
}
// ...
// route.js
// ...
beforeLeave: function (data) {
  const menuIsOpen = navItems.classList.contains('is-menu-open');
  if (menuIsOpen) {
    navItems.classList.remove("is-menu-open");
  }
}
// nav.js
// ...
export const closeMenu = () => {
  navItems.classList.remove("is-menu-open");
  menuIsOpen = false;
};
// ...
// route.js
import initNav, { closeMenu } from './nav.js';
// ...
beforeLeave: closeMenu