You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否脱离React使用MobX?原生JS使用遇错求解决方案

在原生JavaScript中使用MobX的问题与解决方案

好问题!先直接给你结论:是的,你写的这种MobX语法确实没法在无打包/转译的原生JS环境下直接运行,不过咱们可以通过调整使用方式来解决,或者换用更适合原生环境的替代方案。

先说说你遇到的两个错误原因

1. @observable 引发的语法错误

@observable 属于ES装饰器语法,目前绝大多数浏览器还未原生支持这个特性(只有部分浏览器开启实验性标志后才能用,完全不适合生产环境),所以直接写会被浏览器判定为非法字符。

2. exports is not defined 错误

你引用的CDN版本是针对Node.js环境的CommonJS模块格式,而浏览器不认识Node.js的exports/require模块语法,自然会抛出这个错误。

不用打包/转译,也能在原生JS里用MobX

其实MobX提供了适合浏览器的UMD/ES模块版本,只要调整引入方式和写法,就能直接用:

步骤1:引入正确的MobX CDN版本

选择UMD格式的CDN链接(比如MobX 6.x的UMD版本),在HTML中这样引入:

<script src="https://cdn.jsdelivr.net/npm/mobx@6.10.0/dist/mobx.umd.min.js"></script>

这个版本会把MobX挂载到全局的mobx对象上,浏览器能直接识别。

步骤2:改用非装饰器语法定义Store

放弃@observable装饰器,改用MobX提供的makeAutoObservable或makeObservableAPI手动定义可观察对象,示例代码:

class MyStore {
  data = 'foo';

  constructor() {
    // 自动将类的属性和方法转为可观察/动作
    mobx.makeAutoObservable(this);
  }
}

const myStore = new MyStore();

// 测试可观察性
console.log(myStore.data); // 输出 'foo'

// 修改数据要放在动作里(或runInAction)
mobx.runInAction(() => {
  myStore.data = 'bar';
});

console.log(myStore.data); // 输出 'bar'

这样就完全避开了装饰器和模块语法的问题,在原生浏览器环境下就能正常运行。

替代方案:轻量响应式库

如果觉得MobX还是有点重,或者不想调整写法,这些轻量库更适合原生JS环境:

1. Vue Reactivity 模块

Vue的响应式系统可以单独抽离出来使用,体积小、API简洁,支持ES模块引入:

<script type="module">
  import { reactive, watch } from 'https://unpkg.com/@vue/reactivity@3.3.4/dist/reactivity.esm-browser.js';

  // 创建响应式对象
  const myStore = reactive({ data: 'foo' });

  // 监听数据变化
  watch(() => myStore.data, (newVal) => {
    console.log('数据更新了:', newVal);
  });

  // 修改数据
  myStore.data = 'bar'; // 会触发watch的回调
</script>

2. 手写简易响应式

如果需求非常简单,自己用Proxy写个发布订阅式的响应系统也不难,核心逻辑就是用Proxy监听对象变化,通知订阅者:

function reactive(obj) {
  const subscribers = new Set();

  return new Proxy(obj, {
    set(target, key, value) {
      target[key] = value;
      // 通知所有订阅者
      subscribers.forEach(cb => cb(target[key]));
      return true;
    },
    get(target, key) {
      return target[key];
    }
  });
}

// 使用示例
const store = reactive({ data: 'foo' });

// 订阅变化
store.subscribe = (cb) => subscribers.add(cb);
store.subscribe((newVal) => console.log('数据变了:', newVal));

store.data = 'bar'; // 触发订阅回调

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:49:06