You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何重新初始化依赖localStorage的已加载自定义模块?

解决模块单例导致hash值不更新的问题

首先,咱们得先搞清楚问题出在哪:ES模块是单例模式的——当你第一次导入myModule的时候,模块里的代码就只执行一次,那个包含hash: null的对象会被缓存起来。之后哪怕用户输入了新的hash并存在localStorage里,其他模块拿到的还是那个初始化时的旧对象,自然读不到新值。

最优解决方案:用Getter属性动态获取最新值

最简洁高效的办法,是把myModule里的hash改成一个访问器属性(getter),这样每次你访问myModule.hash的时候,它都会重新去localStorage里取最新的数值,完全不需要重新初始化模块。

修改后的myModule.js

const myModule = {
  get hash() {
    return localStorage.getItem('hash');
  }
};
export default myModule;

这样改了之后,不管是one.js还是two.js,只要在需要用到hash的时候访问myModule.hash,就能拿到用户刚输入的最新值,根本不用刷新页面。而且这个方案完全保留了模块的单例特性,代码也最简洁。

备选方案(适合复杂场景)

如果你的业务逻辑需要更复杂的状态同步,比如要监听hash变化并自动触发后续操作,可以试试下面两种方案:

方案1:工厂函数生成实例(适合需要独立状态的场景)

把模块改成一个工厂函数,每次调用都返回一个包含当前hash的新对象:

export default function createMyModule() {
  return {
    hash: localStorage.getItem('hash')
  };
}

然后在one.jstwo.js里这样用:

// one.js
import createMyModule from './myModule';
const myModule = createMyModule();
somethingAction(myModule);

// 用户输入hash后,重新生成实例
const updatedModule = createMyModule();
somethingAction(updatedModule);

不过这个方案会生成多个实例,如果你的one.jstwo.js需要共享同一个状态,这个就不太合适了。

方案2:事件监听+状态订阅(适合需要主动通知的场景)

如果需要在hash更新时自动通知所有依赖模块,可以在myModule里实现一个简单的订阅机制:

const myModule = {
  _hash: localStorage.getItem('hash'),
  get hash() {
    return this._hash;
  },
  _subscribers: [],
  // 订阅hash变化事件
  subscribe(callback) {
    this._subscribers.push(callback);
  },
  // 更新hash并通知订阅者
  updateHash() {
    this._hash = localStorage.getItem('hash');
    this._subscribers.forEach(cb => cb(this._hash));
  }
};

// 监听localStorage的全局变化(跨标签页也能触发)
window.addEventListener('storage', (e) => {
  if (e.key === 'hash') {
    myModule.updateHash();
  }
});

export default myModule;

然后在one.js里订阅变化:

import myModule from './myModule';

// 初始化时执行一次
somethingAction(myModule);

// 订阅hash更新,自动触发后续操作
myModule.subscribe((newHash) => {
  somethingAction(myModule);
});

当用户输入hash并保存到localStorage后,调用myModule.updateHash()就能自动通知所有订阅的模块更新状态。

总结

如果只是需要获取最新的hash值,Getter属性的方案是最优的——它最简洁,不需要额外的逻辑,直接解决核心问题。如果有更复杂的状态同步需求,再考虑后面的备选方案。

内容的提问来源于stack exchange,提问作者zili

火山引擎 最新活动