├── .gitignore ├── README-CN.md ├── README.md ├── dist ├── client.0e30b849.js └── index.html ├── package.json ├── src ├── App.vue ├── Child1.vue ├── Child2.vue ├── Grandchild1.vue ├── Grandchild2.vue └── sharedState.mixin.js └── vue-build.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.log 3 | *.map 4 | node_modules 5 | -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | # Vue 另类状态管理 2 | 3 | 我们都知道 Vue 2.x 移除了 `.sync`(`v2.3` 又回来了一个[阉割版](https://vuejs.org/v2/guide/components.html#sync-Modifier)的) 4 | 尤其是对于 `props` 传递深度较浅的情况下,会多写一些冗余繁琐的代码 5 | 文档提到用 `v-model` 在组件上实现[双向绑定](http://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events),也实在是太鸡肋了 6 | 官方推荐使用 Vuex,但对于**独立封装**的组件,一般是不应该引入的 7 | 业界虽然推崇 `单向数据流` 最佳实践,但也要权衡开发效率、易维护性与直观性 8 | 9 | 在参阅了文档中的 10 | 11 | * [`data` 必须是函数](http://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function) 12 | * [状态管理](http://vuejs.org/v2/guide/state-management.html) 13 | 14 | 我们可以另辟蹊径,自行实现出简易另类的状态管理 15 | 16 | 先来看看 `src/sharedState.mixin.js`: 17 | 18 | ```js 19 | // The magic of state persistance is closure here 20 | export const sharedState = { 21 | todos: [], 22 | counter: 0 23 | } 24 | 25 | export const resetTodos = () => sharedState.todos = [] 26 | export const resetCounter = () => sharedState.counter = 0 27 | export const addTodo = (s) => sharedState.todos.push(s) 28 | export const inc = () => sharedState.counter++ 29 | export const dec = () => sharedState.counter-- 30 | 31 | /** 32 | * @exports.default {Mixin} 33 | */ 34 | export default { 35 | data: () => ({ 36 | sharedState 37 | }), 38 | methods: { 39 | resetTodos, 40 | resetCounter, 41 | addTodo, 42 | inc, 43 | dec 44 | } 45 | } 46 | 47 | /* 48 | 49 | You can access the shared state and methods 50 | not only within Vue component (as mixins) but also in common js files 51 | 52 | ※ e.g. 53 | import { sharedState, inc } from '/sharedState.mixin' 54 | 55 | console.info(sharedState.counter) // 0 56 | inc() 57 | console.info(sharedState.counter) // 1 58 | 59 | */ 60 | ``` 61 | 62 | 应用到如下组件树中: 63 | 64 | ``` 65 | App 66 |  ├─ Child1 67 |  | └─ Grandchild1 68 |  └─ Child2 69 |    └─ Grandchild2 70 | ``` 71 | 72 | 最终结果见[在线 demo](https://kenberkeley.github.io/vue-state-management-alternative/dist/) 73 | 74 | > 建议进入 [`src/`](./src) 了解如何使用 75 | > 本方式适用于 Vue 1.x / 2.x 76 | 77 | *** 78 | 79 | ### 本地测试 80 | 81 | ``` 82 | $ git clone https://github.com/kenberkeley/vue-state-management-alternative.git 83 | $ cd vue-state-management-alternative 84 | $ npm i 85 | $ npm start 86 | ``` 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alternative state management for Vue 2 | 3 | > [Chinese README - 中文说明](./README-CN.md) 4 | 5 | `.sync` is deprecated in Vue 2.x (**UPDATE:** a castration edition is back in `v2.3`) 6 | Especially for the case that `props` passed shallowly, you have to write more verbose code 7 | The docs mentioned using `v-model` as a [hack](http://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events) which sounds hardly elegant 8 | Also, the official solution `Vuex` is not suitable for independent components 9 | We all know **one-way data flow** is a best practice 10 | but development efficiency, maintainability, simple and straight-forward should all be taken into consideration 11 | 12 | After reviewing the below contents of the docs: 13 | 14 | * [`data` Must Be a Function](http://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function) 15 | * [State Management](http://vuejs.org/v2/guide/state-management.html) 16 | 17 | We can implement an awesome state management solution ourselves 18 | 19 | Firstly, Take a look at `src/sharedState.mixin.js`: 20 | 21 | ```js 22 | // The magic of state persistance is closure here 23 | export const sharedState = { 24 | todos: [], 25 | counter: 0 26 | } 27 | 28 | export const resetTodos = () => sharedState.todos = [] 29 | export const resetCounter = () => sharedState.counter = 0 30 | export const addTodo = (s) => sharedState.todos.push(s) 31 | export const inc = () => sharedState.counter++ 32 | export const dec = () => sharedState.counter-- 33 | 34 | /** 35 | * @exports.default {Mixin} 36 | */ 37 | export default { 38 | data: () => ({ 39 | sharedState 40 | }), 41 | methods: { 42 | resetTodos, 43 | resetCounter, 44 | addTodo, 45 | inc, 46 | dec 47 | } 48 | } 49 | 50 | /* 51 | 52 | You can access the shared state and methods 53 | not only within Vue component (as mixins) but also in common js files 54 | 55 | ※ e.g. 56 | import { sharedState, inc } from '/sharedState.mixin' 57 | 58 | console.info(sharedState.counter) // 0 59 | inc() 60 | console.info(sharedState.counter) // 1 61 | 62 | */ 63 | ``` 64 | 65 | Then, apply to the component tree below: 66 | 67 | ``` 68 | App 69 |  ├─ Child1 70 |  | └─ Grandchild1 71 |  └─ Child2 72 |    └─ Grandchild2 73 | ``` 74 | 75 | Finally we get an [online demo](https://kenberkeley.github.io/vue-state-management-alternative/dist/) 76 | 77 | > It's highly suggested to dive into [`src/`](./src) to learn about how to use it 78 | > This solution is applicable for Vue 1.x / 2.x 79 | 80 | *** 81 | 82 | ### Test it yourself 83 | 84 | ``` 85 | $ git clone https://github.com/kenberkeley/vue-state-management-alternative.git 86 | $ cd vue-state-management-alternative 87 | $ npm i 88 | $ npm start 89 | ``` 90 | -------------------------------------------------------------------------------- /dist/client.0e30b849.js: -------------------------------------------------------------------------------- 1 | !function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=20)}([function(t,e){t.exports=function(t,e,n,r){var o,i=t=t||{},a=typeof t.default;"object"!==a&&"function"!==a||(o=t,i=t.default);var s="function"==typeof i?i.options:i;if(e&&(s.render=e.render,s.staticRenderFns=e.staticRenderFns),n&&(s._scopeId=n),r){var c=s.computed||(s.computed={});Object.keys(r).forEach(function(t){var e=r[t];c[t]=function(){return e}})}return{esModule:o,exports:i,options:s}}},function(t,e,n){"use strict";var r={todos:[],counter:0},o=function(){return r.todos=[]},i=function(){return r.counter=0},a=function(t){return r.todos.push(t)},s=function(){return r.counter++},c=function(){return r.counter--};e.a={data:function(){return{sharedState:r}},methods:{resetTodos:o,resetCounter:i,addTodo:a,inc:s,dec:c}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(13),o=n(3),i=n.n(o);new r.a({el:"#app",render:function(t){return t(i.a)}})},function(t,e,n){var r=n(0)(n(15),n(8),null,null);t.exports=r.exports},function(t,e,n){var r=n(0)(n(16),n(12),null,null);t.exports=r.exports},function(t,e,n){var r=n(0)(n(17),n(11),null,null);t.exports=r.exports},function(t,e,n){var r=n(0)(n(18),n(10),null,null);t.exports=r.exports},function(t,e,n){var r=n(0)(n(19),n(9),null,null);t.exports=r.exports},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("fieldset",[n("code",[t._v(t._s(t.$data))]),t._v(" "),n("br"),t._v(" "),n("button",{on:{click:t.resetTodos}},[t._v("todos = []")]),t._v(" "),n("button",{on:{click:t.resetCounter}},[t._v("counter = 0")]),t._v(" "),n("br"),n("br"),t._v(" "),n("child1"),n("br"),t._v(" "),n("child2")],1)},staticRenderFns:[]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("fieldset",[n("code",[t._v(t._s(t.$data))]),t._v(" "),n("br"),t._v(" "),n("button",{on:{click:function(e){t.addTodo("grandchild2")}}},[t._v("todos.push('grandchild2')")]),t._v(" "),n("button",{on:{click:t.dec}},[t._v("counter--")])])},staticRenderFns:[]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("fieldset",[n("code",[t._v(t._s(t.$data))]),t._v(" "),n("br"),t._v(" "),n("button",{on:{click:function(e){t.addTodo("grandchild1")}}},[t._v("todos.push('grandchild1')")]),t._v(" "),n("button",{on:{click:t.inc}},[t._v("counter++")])])},staticRenderFns:[]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("fieldset",[n("code",[t._v(t._s(t.$data))]),t._v(" "),n("br"),t._v(" "),n("button",{on:{click:function(e){t.addTodo("child2")}}},[t._v("todos.push('child2')")]),t._v(" "),n("button",{on:{click:t.dec}},[t._v("counter--")]),t._v(" "),n("br"),n("br"),t._v(" "),n("grandchild2")],1)},staticRenderFns:[]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("fieldset",[n("code",[t._v(t._s(t.$data))]),t._v(" "),n("br"),t._v(" "),n("button",{on:{click:function(e){t.addTodo("child1")}}},[t._v("todos.push('child1')")]),t._v(" "),n("button",{on:{click:t.inc}},[t._v("counter++")]),t._v(" "),n("br"),n("br"),t._v(" "),n("grandchild1")],1)},staticRenderFns:[]}},function(t,e,n){"use strict";(function(t){function n(t){return null==t?"":"object"==typeof t?JSON.stringify(t,null,2):String(t)}function r(t){var e=parseFloat(t);return isNaN(e)?t:e}function o(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(n,1)}}function a(t,e){return Bn.call(t,e)}function s(t){return"string"==typeof t||"number"==typeof t}function c(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}function u(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n}function l(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function f(t,e){for(var n in e)t[n]=e[n];return t}function d(t){return null!==t&&"object"==typeof t}function p(t){return qn.call(t)===Wn}function v(t){for(var e={},n=0;n=0&&Sr[n].id>t.id;)n--;Sr.splice(Math.max(n,Ir)+1,0,t)}else Sr.push(t);Tr||(Tr=!0,lr(ht))}}function _t(t){Mr.clear(),yt(t,Mr)}function yt(t,e){var n,r,o=Array.isArray(t);if((o||d(t))&&Object.isExtensible(t)){if(t.__ob__){var i=t.__ob__.dep.id;if(e.has(i))return;e.add(i)}if(o)for(n=t.length;n--;)yt(t[n],e);else for(r=Object.keys(t),n=r.length;n--;)yt(t[r[n]],e)}}function gt(t,e,n){Nr.get=function(){return this[e][n]},Nr.set=function(t){this[e][n]=t},Object.defineProperty(t,n,Nr)}function bt(t){t._watchers=[];var e=t.$options;e.props&&Ct(t,e.props),e.methods&&Ot(t,e.methods),e.data?wt(t):O(t._data={},!0),e.computed&&xt(t,e.computed),e.watch&&St(t,e.watch)}function Ct(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$options._propKeys=[],i=!t.$parent;yr.shouldConvert=i;for(var a in e)!function(i){o.push(i);var a=U(i,e,n,t);S(r,i,a),i in t||gt(t,"_props",i)}(a);yr.shouldConvert=!0}function wt(t){var e=t.$options.data;e=t._data="function"==typeof e?$t(e,t):e||{},p(e)||(e={});for(var n=Object.keys(e),r=t.$options.props,o=n.length;o--;)r&&a(r,n[o])||g(n[o])||gt(t,"_data",n[o]);O(e,!0)}function $t(t,e){try{return t.call(e)}catch(t){return H(t,e,"data()"),{}}}function xt(t,e){var n=t._computedWatchers=Object.create(null);for(var r in e){var o=e[r],i="function"==typeof o?o:o.get;n[r]=new Pr(t,i,h,Lr),r in t||kt(t,r,o)}}function kt(t,e,n){"function"==typeof n?(Nr.get=At(e),Nr.set=h):(Nr.get=n.get?n.cache!==!1?At(e):n.get:h,Nr.set=n.set?n.set:h),Object.defineProperty(t,e,Nr)}function At(t){return function(){var e=this._computedWatchers&&this._computedWatchers[t];if(e)return e.dirty&&e.evaluate(),pr.target&&e.depend(),e.value}}function Ot(t,e){t.$options.props;for(var n in e)t[n]=null==e[n]?h:u(e[n],t)}function St(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var o=0;o-1:t instanceof RegExp&&t.test(e)}function pe(t,e){for(var n in t){var r=t[n];if(r){var o=fe(r.componentOptions);o&&!e(o)&&(ve(r),t[n]=null)}}}function ve(t){t&&(t.componentInstance._inactive||pt(t.componentInstance,"deactivated"),t.componentInstance.$destroy())}function he(t){for(var e=t.data,n=t,r=t;r.componentInstance;)r=r.componentInstance._vnode,r.data&&(e=me(r.data,e));for(;n=n.parent;)n.data&&(e=me(e,n.data));return _e(e)}function me(t,e){return{staticClass:ye(t.staticClass,e.staticClass),class:t.class?[t.class,e.class]:e.class}}function _e(t){var e=t.class,n=t.staticClass;return n||e?ye(n,ge(e)):""}function ye(t,e){return t?e?t+" "+e:t:e||""}function ge(t){var e="";if(!t)return e;if("string"==typeof t)return t;if(Array.isArray(t)){for(var n,r=0,o=t.length;r-1?ao[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:ao[t]=/HTMLUnknownElement/.test(e.toString())}function we(t){if("string"==typeof t){var e=document.querySelector(t);return e?e:document.createElement("div")}return t}function $e(t,e){var n=document.createElement(t);return"select"!==t?n:(e.data&&e.data.attrs&&void 0!==e.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function xe(t,e){return document.createElementNS(no[t],e)}function ke(t){return document.createTextNode(t)}function Ae(t){return document.createComment(t)}function Oe(t,e,n){t.insertBefore(e,n)}function Se(t,e){t.removeChild(e)}function Ee(t,e){t.appendChild(e)}function Te(t){return t.parentNode}function je(t){return t.nextSibling}function Ie(t){return t.tagName}function De(t,e){t.textContent=e}function Pe(t,e,n){t.setAttribute(e,n)}function Me(t,e){var n=t.data.ref;if(n){var r=t.context,o=t.componentInstance||t.elm,a=r.$refs;e?Array.isArray(a[n])?i(a[n],o):a[n]===o&&(a[n]=void 0):t.data.refInFor?Array.isArray(a[n])&&a[n].indexOf(o)<0?a[n].push(o):a[n]=[o]:a[n]=o}}function Ne(t){return void 0===t||null===t}function Le(t){return void 0!==t&&null!==t}function Re(t){return t===!0}function Ue(t,e){return t.key===e.key&&t.tag===e.tag&&t.isComment===e.isComment&&Le(t.data)===Le(e.data)&&Fe(t,e)}function Fe(t,e){if("input"!==t.tag)return!0;var n;return(Le(n=t.data)&&Le(n=n.attrs)&&n.type)===(Le(n=e.data)&&Le(n=n.attrs)&&n.type)}function Be(t,e,n){var r,o,i={};for(r=e;r<=n;++r)o=t[r].key,Le(o)&&(i[o]=r);return i}function Ve(t,e){(t.data.directives||e.data.directives)&&He(t,e)}function He(t,e){var n,r,o,i=t===uo,a=e===uo,s=ze(t.data.directives,t.context),c=ze(e.data.directives,e.context),u=[],l=[];for(n in c)r=s[n],o=c[n],r?(o.oldValue=r.value,We(o,"update",e,t),o.def&&o.def.componentUpdated&&l.push(o)):(We(o,"bind",e,t),o.def&&o.def.inserted&&u.push(o));if(u.length){var f=function(){for(var n=0;n-1?e.split(/\s+/).forEach(function(e){return t.classList.add(e)}):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function ln(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(/\s+/).forEach(function(e){return t.classList.remove(e)}):t.classList.remove(e);else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");t.setAttribute("class",n.trim())}}function fn(t){if(t){if("object"==typeof t){var e={};return t.css!==!1&&f(e,So(t.name||"v")),f(e,t),e}return"string"==typeof t?So(t):void 0}}function dn(t){No(function(){No(t)})}function pn(t,e){(t._transitionClasses||(t._transitionClasses=[])).push(e),un(t,e)}function vn(t,e){t._transitionClasses&&i(t._transitionClasses,e),ln(t,e)}function hn(t,e,n){var r=mn(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===To?Do:Mo,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout(function(){c0&&(n=To,l=a,f=i.length):e===jo?u>0&&(n=jo,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?To:jo:null,f=n?n===To?i.length:c.length:0),{type:n,timeout:l,propCount:f,hasTransform:n===To&&Lo.test(r[Io+"Property"])}}function _n(t,e){for(;t.length1}function $n(t,e){e.data.show||gn(e)}function xn(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){for(var i,a,s=0,c=t.options.length;s-1,a.selected!==i&&(a.selected=i);else if(m(An(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function kn(t,e){for(var n=0,r=e.length;n0,rr=tr&&tr.indexOf("edge/")>0,or=tr&&tr.indexOf("android")>0,ir=tr&&/iphone|ipad|ipod|ios/.test(tr),ar=tr&&/chrome\/\d+/.test(tr)&&!rr,sr=function(){return void 0===Un&&(Un=!Yn&&void 0!==t&&"server"===t.process.env.VUE_ENV),Un},cr=Yn&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,ur="undefined"!=typeof Symbol&&w(Symbol)&&"undefined"!=typeof Reflect&&w(Reflect.ownKeys),lr=function(){function t(){r=!1;var t=n.slice(0);n.length=0;for(var e=0;e1?l(n):n;for(var r=l(arguments,1),o=0,i=n.length;o1&&(e[n[0].trim()]=n[1].trim())}}),e}),wo=/^--/,$o=/\s*!important$/,xo=function(t,e,n){wo.test(e)?t.style.setProperty(e,n):$o.test(n)?t.style.setProperty(e,n.replace($o,""),"important"):t.style[Ao(e)]=n},ko=["Webkit","Moz","ms"],Ao=c(function(t){if(Gr=Gr||document.createElement("div"),"filter"!==(t=Vn(t))&&t in Gr.style)return t;for(var e=t.charAt(0).toUpperCase()+t.slice(1),n=0;nd?(u=Ne(n[m+1])?null:n[m+1].elm,h(t,u,n,f,m,r)):f>m&&_(t,e,l,d)}function b(t,e,n,r){if(t!==e){if(Re(e.isStatic)&&Re(t.isStatic)&&e.key===t.key&&(Re(e.isCloned)||Re(e.isOnce)))return e.elm=t.elm,void(e.componentInstance=t.componentInstance);var o,i=e.data;Le(i)&&Le(o=i.hook)&&Le(o=o.prepatch)&&o(t,e);var a=e.elm=t.elm,s=t.children,c=e.children;if(Le(i)&&d(e)){for(o=0;o 2 | 3 | 4 | 5 | Vue state management alternative 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-state-management-alternative", 3 | "version": "1.0.0", 4 | "description": "Alternative state management for Vue", 5 | "scripts": { 6 | "start": "vue build src/App.vue", 7 | "build": "vue build src/App.vue --prod --config vue-build.config.js" 8 | }, 9 | "devDependencies": { 10 | "vue-cli": "^2.8.1" 11 | }, 12 | "license": "MIT" 13 | } 14 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 12 | 24 | -------------------------------------------------------------------------------- /src/Child1.vue: -------------------------------------------------------------------------------- 1 | 11 | 22 | -------------------------------------------------------------------------------- /src/Child2.vue: -------------------------------------------------------------------------------- 1 | 11 | 22 | -------------------------------------------------------------------------------- /src/Grandchild1.vue: -------------------------------------------------------------------------------- 1 | 9 | 18 | -------------------------------------------------------------------------------- /src/Grandchild2.vue: -------------------------------------------------------------------------------- 1 | 9 | 18 | -------------------------------------------------------------------------------- /src/sharedState.mixin.js: -------------------------------------------------------------------------------- 1 | // The magic of state persistance is closure here 2 | export const sharedState = { 3 | todos: [], 4 | counter: 0 5 | } 6 | 7 | export const resetTodos = () => sharedState.todos = [] 8 | export const resetCounter = () => sharedState.counter = 0 9 | export const addTodo = (s) => sharedState.todos.push(s) 10 | export const inc = () => sharedState.counter++ 11 | export const dec = () => sharedState.counter-- 12 | 13 | /** 14 | * @exports.default {Mixin} 15 | */ 16 | export default { 17 | data: () => ({ 18 | sharedState 19 | }), 20 | methods: { 21 | resetTodos, 22 | resetCounter, 23 | addTodo, 24 | inc, 25 | dec 26 | } 27 | } 28 | 29 | /* 30 | 31 | You can access the shared state and methods 32 | not only within Vue component (as mixins) but also in common js files 33 | 34 | ※ e.g. 35 | import { sharedState, inc } from '/sharedState.mixin' 36 | 37 | console.info(sharedState.counter) // 0 38 | inc() 39 | console.info(sharedState.counter) // 1 40 | 41 | */ 42 | -------------------------------------------------------------------------------- /vue-build.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | html: { 3 | title: 'Vue state management alternative' 4 | }, 5 | webpack: { 6 | output: { 7 | publicPath: '' 8 | } 9 | } 10 | }; 11 | --------------------------------------------------------------------------------