{"id":13430526,"url":"https://github.com/vuejs/vue-rx","last_synced_at":"2025-05-13T19:16:33.643Z","repository":{"id":41262785,"uuid":"45409716","full_name":"vuejs/vue-rx","owner":"vuejs","description":"👁️ RxJS integration for Vue.js.","archived":false,"fork":false,"pushed_at":"2022-12-08T22:18:35.000Z","size":374,"stargazers_count":3356,"open_issues_count":21,"forks_count":190,"subscribers_count":73,"default_branch":"master","last_synced_at":"2025-05-13T02:03:19.710Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vuejs.png","metadata":{"files":{"readme":"README-CN.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-11-02T17:17:44.000Z","updated_at":"2025-05-09T12:10:17.000Z","dependencies_parsed_at":"2022-07-21T22:02:51.740Z","dependency_job_id":null,"html_url":"https://github.com/vuejs/vue-rx","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vuejs%2Fvue-rx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vuejs%2Fvue-rx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vuejs%2Fvue-rx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vuejs%2Fvue-rx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vuejs","download_url":"https://codeload.github.com/vuejs/vue-rx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010822,"owners_count":21999003,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T02:00:54.897Z","updated_at":"2025-05-13T19:16:33.614Z","avatar_url":"https://github.com/vuejs.png","language":"JavaScript","funding_links":[],"categories":["HTML","vue","JavaScript","Libraries and Plugins"],"sub_categories":["Other"],"readme":"# vue-rx [![Build Status](https://circleci.com/gh/vuejs/vue-rx/tree/master.svg?style=shield)](https://circleci.com/gh/vuejs/vue-rx/tree/master)\n\n[English](README.md) | 简体中文\n\n将 [RxJS v6+](https://github.com/ReactiveX/rxjs) 集成到 Vue.js。\n\n\u003e **相比 5.0 的不兼容变更**\n\u003e\n\u003e - vue-rx v6 现在默认只对 RxJS V6+ 生效。如果你想继续使用 RxJS v5 风格的代码，安装 `rxjs-compat`。\n\n### 安装\n\n#### NPM + ES2015\n\n**`rxjs` 需要作为 peer dependency 引入。**\n\n```bash\nnpm install vue vue-rx rxjs --save\n```\n\n```js\nimport Vue from 'vue';\nimport VueRx from 'vue-rx';\n\nVue.use(VueRx);\n```\n\nwebpack 打包默认会使用 `dist/vue-rx.esm.js`。这样引入最小数量的 Rx 操作符并且保证了最小的打包体积。\n\n#### 全局脚本\n\n如果要在浏览器环境使用，需要引入 UMD 构建版本 `dist/vue-rx.js`。在浏览器环境中的 UMD 构建版本会假设 `window.rxjs` 已经存在，因此你需要确保在 Vue.js 和 RxJS 之后引入 `vue-rx.js`。如果 `window.Vue` 存在的话，`vue-rx` 会自动安装。\n\n例子:\n\n```html\n\u003cscript src=\"https://unpkg.com/rxjs/bundles/rxjs.umd.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/vue/dist/vue.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"../dist/vue-rx.js\"\u003e\u003c/script\u003e\n```\n\n### 如何使用\n\n```js\n// 用 `subscriptions` 选项提供 Rx observables\nnew Vue({\n  el: '#app',\n  subscriptions: {\n    msg: messageObservable\n  }\n});\n```\n\n```html\n\u003c!-- 绑定到模板 --\u003e\n\u003cdiv\u003e{{ msg }}\u003c/div\u003e\n```\n\n`subscriptions` 选项也可以接受一个函数，这样就可以在每个组件实例中返回独一无二的 observables：\n\n```js\nimport { Observable } from 'rxjs'\n\nVue.component('foo', {\n  subscriptions: function () {\n    return {\n      msg: new Observable(...)\n    }\n  }\n})\n```\n\nObservables 会以 `vm.$observables` 的形式暴露：\n\n```js\nconst vm = new Vue({\n  subscriptions: {\n    msg: messageObservable\n  }\n});\n\nvm.$observables.msg.subscribe(msg =\u003e console.log(msg));\n```\n\n### `v-stream`：流式 DOM 事件\n\n`vue-rx` 提供 `v-stream` 让你向一个 Rx Subject 流式发送 DOM 事件。语法和 `v-on` 相似，指令参数对应事件名，绑定值对应 Rx Subject。\n\n```html\n\u003cbutton v-stream:click=\"plus$\"\u003e+\u003c/button\u003e\n```\n\n注意在渲染发生之前你需要在 vm 实例上声明一个 `rxjs.Subject` 实例 —— `plus$`，就像声明数据那样。你也可以在 `subscriptions` 函数中这样做。\n\n```js\nimport { Subject } from 'rxjs';\nimport { map, startWith, scan } from 'rxjs/operators';\n\nnew Vue({\n  subscriptions() {\n    // 声明接收的 Subjects\n    this.plus$ = new Subject();\n    // ...然后使用 Subjects 作为来源流创建订阅。\n    // 来源流以 `{ event: HTMLEvent, data?: any }` 的格式发送数据\n    return {\n      count: this.plus$.pipe(\n        map(() =\u003e 1),\n        startWith(0),\n        scan((total, change) =\u003e total + change)\n      )\n    };\n  }\n});\n```\n\n或者，使用 `domStreams` 简写选项：\n\n```js\nnew Vue({\n  // 需要传递 `Rx` 给 `Vue.use()` 暴露 `Subject`\n  domStreams: ['plus$'],\n  subscriptions() {\n    // 使用 `this.plus$`\n  }\n});\n```\n\n最后，使用另一种语法给流传递额外的数据：\n\n```html\n\u003cbutton v-stream:click=\"{ subject: plus$, data: someData }\"\u003e+\u003c/button\u003e\n```\n\n当你需要伴随诸如 `v-for` 迭代的临时模板变量一起传递，这就非常有用了。你可以直接从来源流撷取想要的数据。\n\n```js\nconst plusData$ = this.plus$.pipe(pluck('data'));\n```\n\n从 3.1 版本开始，你可以传入额外的选项(作为第三个参数一起传入原生的 `addEventListener`)：\n\n```html\n\u003cbutton v-stream:click=\"{\n  subject: plus$,\n  data: someData,\n  options: { once: true, passive: true, capture: true }\n}\"\u003e+\u003c/button\u003e\n```\n\n更具体的用法请查阅[实例](https://github.com/vuejs/vue-rx/blob/master/example/counter.html)。\n\n### `v-stream`：从子组件流式发送自定义事件\n\n跟流式 `DOM` 事件很相似，`v-stream` 也可以被用于组件，它会根据子组件触发的自定义事件创建 observables。运作方式跟 `v-on` 相似：\n\n```html\n\u003cdiv\u003e\n  \u003c!-- 自定义组件 --\u003e\n  \u003cpagination v-on:change=\"pageChanged()\"\u003e\u003c/pagination\u003e\n\n  \u003c!-- 在自定义组件上使用 `v-stream` --\u003e\n  \u003cpagination v-stream:change=\"pageChange$\"\u003e\u003c/pagination\u003e\n\u003c/div\u003e\n```\n\n### 其它 API 方法\n\n#### `$watchAsObservable(expOrFn, [options])`\n\n这是一个添加到实例的原型方法。你可以根据一个值的侦听器创建 observable。值会以 `{ newValue, oldValue }` 的格式触发：\n\n```js\nimport { pluck, map } from 'rxjs/operators';\n\nconst vm = new Vue({\n  data: {\n    a: 1\n  },\n  subscriptions() {\n    // 用 Rx 操作符声明式地映射成另一个属性\n    return {\n      aPlusOne: this.$watchAsObservable('a').pipe(\n        pluck('newValue'),\n        map(a =\u003e a + 1)\n      )\n    };\n  }\n});\n\n// 或者产生副作用...\nvm.$watchAsObservable('a').subscribe(\n  ({ newValue, oldValue }) =\u003e console.log('stream value', newValue, oldValue),\n  err =\u003e console.error(err),\n  () =\u003e console.log('complete')\n);\n```\n\n可选的 `options` 对象，接受的选项与 `vm.$watch` 一致。\n\n#### `$eventToObservable(event)`\n\n转化 `vue.$on` (包括生命周期事件) 到 Observables。值会以 `{ name, msg }` 的格式触发：\n\n```js\nimport { interval } from 'rxjs';\nimport { take, takeUntil } from 'rxjs/operators';\n\nconst vm = new Vue({\n  created() {\n    this.$eventToObservable('customEvent').subscribe(event =\u003e\n      console.log(event.name, event.msg)\n    );\n  }\n});\n\n// `vm.$once` 的 `vue-rx` 版本\nthis.$eventToObservable('customEvent').pipe(take(1));\n\n// 另一种取消订阅的方法：\nlet beforeDestroy$ = this.$eventToObservable('hook:beforeDestroy').pipe(\n  take(1)\n);\n\ninterval(500).pipe(takeUntil(beforeDestroy$));\n```\n\n#### `$subscribeTo(observable, next, error, complete)`\n\n这是一个添加到实例的原型方法。你可以用它订阅一个 observable，但是得让 VueRx 管理它的 dispose/unsubscribe。\n\n```js\nimport { interval } from 'rxjs';\n\nconst vm = new Vue({\n  mounted() {\n    this.$subscribeTo(interval(1000), function(count) {\n      console.log(count);\n    });\n  }\n});\n```\n\n#### `$fromDOMEvent(selector, event)`\n\n这是一个添加到实例的原型方法。可以用它根据实例内部元素的 DOM 事件创建 observable。与 `Rx.Observable.fromEvent` 类似，甚至在 DOM 渲染前，在 `subscriptions` 函数中使用都是有用的。\n\n`selector` 用来查找组件根元素的后代节点，如果你想监听根元素，传入 `null` 作为第一个参数。\n\n```js\nimport { pluck } from 'rxjs/operators';\n\nconst vm = new Vue({\n  subscriptions() {\n    return {\n      inputValue: this.$fromDOMEvent('input', 'keyup').pipe(\n        pluck('target', 'value')\n      )\n    };\n  }\n});\n```\n\n#### `$createObservableMethod(methodName)`\n\n转化函数调用为输出调用参数的 observable 队列。\n\n这是一个添加到实例的原型方法。用来根据函数名创建一个共享的，热的 observable。这个函数会被赋值到 vm 方法上去。\n\n```html\n\u003ccustom-form :onSubmit=\"submitHandler\"\u003e\u003c/custom-form\u003e\n```\n\n```js\nconst vm = new Vue({\n  subscriptions() {\n    return {\n      // 需要 `share` 操作符\n      formData: this.$createObservableMethod('submitHandler')\n    };\n  }\n});\n```\n\n你可以使用 `observableMethods` 选项使代码更加声明式：\n\n```js\nnew Vue({\n  observableMethods: {\n    submitHandler: 'submitHandler$'\n    // 或者使用数组简写: ['submitHandler']\n  }\n});\n```\n\n上面代码会自动在实例上创建两个东西：\n\n1.  一个是可以用 `v-on` 绑定到模板的 `submitHandler` 方法；\n2.  一个是可以流式调用 `submitHandler` 的`submitHandler$` observable。\n\n[例子](https://github.com/vuejs/vue-rx/blob/master/example/counter-function.html)\n\n### 注意事项\n\n你不能使用 `watch` 选项去侦听订阅 (subscriptions)，因为它在设置订阅之前就被处理完毕了。但是你可以在 `created` 钩子中使用 `$watch` 作为替代方案。\n\n### 示例\n\n到 `/examples` 目录查看一些简单示例。\n\n### License\n\n[MIT](http://opensource.org/licenses/MIT)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvuejs%2Fvue-rx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvuejs%2Fvue-rx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvuejs%2Fvue-rx/lists"}