├── .babelrc ├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── test.js └── vue-nonreactive.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "eslint-config-itng" 5 | ], 6 | "env": { 7 | "es6": true, 8 | "node": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | .nyc_output 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directory 28 | node_modules 29 | 30 | # Optional npm cache directory 31 | .npm 32 | 33 | # Optional REPL history 34 | .node_repl_history 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '4' 5 | - '6' 6 | 7 | env: 8 | - VUE="vue@1" 9 | - VUE="vue@2" 10 | 11 | before_install: 12 | - if [[ `npm -v` != 4* ]]; then npm i -g npm@4; fi 13 | 14 | install: 15 | - npm install $VUE 16 | - npm install 17 | 18 | after_success: 19 | - npm run report-coverage 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ryan P Kilby 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-nonreactive 2 | 3 | [![Build Status](https://travis-ci.org/rpkilby/vue-nonreactive.svg?branch=master)](https://travis-ci.org/rpkilby/vue-nonreactive) 4 | [![codecov.io](https://codecov.io/github/rpkilby/vue-nonreactive/coverage.svg?branch=master)](https://codecov.io/github/rpkilby/vue-nonreactive?branch=master) 5 | 6 | 7 | Disable Vue reactivity for a given object. If you're using this, 8 | you may want to rethink your data model. However, this plugin is 9 | useful in a small subset of cases where you need to prevent Vue 10 | from walking nested properties that do not represent application 11 | state. eg, your model has a reference to a data store or cache. 12 | 13 | Example: 14 | 15 | ```js 16 | new Vue({ 17 | el: 'body', 18 | data() { 19 | const instance = postStore.fetch({include: ['author', 'comments.author']}) 20 | Vue.nonreactive(instance._cache) 21 | 22 | return {post: instance, }, 23 | }, 24 | ... 25 | }); 26 | ``` 27 | 28 | In the above case, the object `_cache` does not represent pure state 29 | and should not be observed. 30 | 31 | 32 | ## How this works 33 | 34 | When Vue observes an object, it walks each attribute and converts it into a 35 | reactive property. Any nested objects are then also observed. However, Vue 36 | will skip observation if it detects that the object is already observed. 37 | We can make an object non-reactive by assigning a dummy observer, duping 38 | Vue's observer detection. 39 | 40 | ## Release process 41 | 42 | ```shell 43 | $ npm version 44 | $ git push --follow-tags 45 | $ npm publish 46 | ``` 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-nonreactive", 3 | "version": "0.1.0", 4 | "description": "Vue.js plugin that allows you to disable reactivity on an object", 5 | "main": "vue-nonreactive.js", 6 | "scripts": { 7 | "test": "tap test.js --cov --nyc-arg=--require=babel-register", 8 | "report-coverage": "nyc report --reporter=lcov && codecov" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/rpkilby/vue-nonreactive.git" 13 | }, 14 | "keywords": [ 15 | "vue", 16 | "nonreactive", 17 | "unobserve" 18 | ], 19 | "author": "Ryan P Kilby ", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/rpkilby/vue-nonreactive/issues" 23 | }, 24 | "homepage": "https://github.com/rpkilby/vue-nonreactive#readme", 25 | "jspm": { 26 | "format": "esm" 27 | }, 28 | "devDependencies": { 29 | "babel-eslint": "^6.0.2", 30 | "babel-preset-es2015": "^6.6.0", 31 | "babel-register": "^6.7.2", 32 | "codecov": "^1.0.1", 33 | "eslint": "^2.7.0", 34 | "eslint-config-itng": "github:itng/eslint-config-itng#0.0.1", 35 | "tap": "^5.7.1", 36 | "vue": "*" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 2 | import tap from 'tap'; 3 | import Vue from 'vue'; 4 | import VueNonreactive from './vue-nonreactive'; 5 | 6 | Vue.use(VueNonreactive); 7 | 8 | 9 | function derived() { 10 | return this.obj.prop + 1; 11 | } 12 | 13 | 14 | const reactive = new Vue({ 15 | data() { 16 | return {obj: { 17 | sub: {}, 18 | prop: 0, 19 | }}; 20 | }, 21 | 22 | computed: { 23 | derived, 24 | }, 25 | }); 26 | 27 | 28 | const nonReactive = new Vue({ 29 | data() { 30 | const data = {obj: { 31 | sub: {}, 32 | prop: 0, 33 | }}; 34 | Vue.nonreactive(data.obj); 35 | 36 | return data; 37 | }, 38 | 39 | computed: { 40 | derived, 41 | }, 42 | }); 43 | 44 | tap.test('reactive data is reactive', t => { 45 | t.plan(6); 46 | 47 | const obj = reactive.$data.obj; 48 | 49 | // obj should retain attributes 50 | t.ok(obj.hasOwnProperty('sub')); 51 | t.ok(obj.hasOwnProperty('prop')); 52 | 53 | // all objects should be observed 54 | t.type(obj.__ob__, 'Observer'); 55 | t.type(obj.sub.__ob__, 'Observer'); 56 | 57 | // derived should update on prop update 58 | t.equal(reactive.derived, 1); 59 | reactive.obj.prop += 1; 60 | t.equal(reactive.derived, 2); 61 | }); 62 | 63 | 64 | tap.test('non-reactive data is not reactive', t => { 65 | t.plan(6); 66 | 67 | const obj = nonReactive.$data.obj; 68 | 69 | // obj should retain attributes 70 | t.ok(obj.hasOwnProperty('sub')); 71 | t.ok(obj.hasOwnProperty('prop')); 72 | 73 | // primary obj should remain observed 74 | // sub object should not be observed 75 | t.type(obj.__ob__, 'Observer'); 76 | t.type(obj.sub.__ob__, 'undefined'); 77 | 78 | // derived should not update on prop update 79 | 80 | // derived should update on prop update 81 | t.equal(nonReactive.derived, 1); 82 | nonReactive.obj.prop += 1; 83 | t.equal(nonReactive.derived, 1); 84 | }); 85 | -------------------------------------------------------------------------------- /vue-nonreactive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disable Vue reactivity for a given object. If you're using this, 3 | * you may want to rethink your data model. However, this plugin is 4 | * useful in a small subset of cases where you need to prevent Vue 5 | * from walking nested properties that do not represent application 6 | * state. eg, your model has a reference to a data store or cache. 7 | * 8 | * Example: 9 | * 10 | * new Vue({ 11 | * el: 'body', 12 | * data() { 13 | * const instance = postStore.fetch({include: ['author', 'comments.author']}) 14 | * Vue.nonreactive(instance._cache) 15 | * 16 | * return {post: instance, }, 17 | * }, 18 | * ... 19 | * }); 20 | */ 21 | 22 | 23 | /* eslint-disable no-param-reassign */ 24 | function install(Vue) { 25 | const Observer = (new Vue()).$data 26 | .__ob__ 27 | .constructor; 28 | 29 | Vue.nonreactive = function nonreactive(value) { 30 | // Set dummy observer on value 31 | value.__ob__ = new Observer({}); 32 | return value; 33 | }; 34 | } 35 | 36 | 37 | // auto install 38 | /* istanbul ignore if */ 39 | if (typeof window !== 'undefined' && window.Vue) 40 | window.Vue.use(install); 41 | 42 | 43 | export default install; 44 | --------------------------------------------------------------------------------