vuejs / vuex Goto Github PK
View Code? Open in Web Editor NEW🗃️ Centralized State Management for Vue.js.
Home Page: https://vuex.vuejs.org
License: MIT License
🗃️ Centralized State Management for Vue.js.
Home Page: https://vuex.vuejs.org
License: MIT License
Could you please give an example in Coffeescript or plain JavaScript? Thanks!
I have an computed property that is expensive to process, and is used in many different components. Using a shared getter as described in http://vuex.vuejs.org/en/state.html works, but the getter gets called once for every instance of the component, even though it's returning the same data.
The only way I can think of doing this with the existing functionality is to manually set a watch on the relevant data, then dispatch a mutation when it changes to update a property in the state object... or just put a getter in a parent component and pass the data down as a prop. In my case I ended up going with the latter, but I would think there should be an easier way. Thoughts?
I am looking at Voie as a really good alternative to vue-router. I like the approach, syntax and simplicity.
I managed to use Vuex with Voie's example app by loading the data inside each component instead of passing the data into the component from the outside, in this case from Voie's state manager.
Voie routes have a method called enter()
that allows to load data before rendering the component, and then pass it trough, assuring the component is loaded after the data has arrived. When using Vuex actions this is harder to do as the action does not return a promise, and the component is renderd before the data arrived.
The approach I want to achieve is to pass Vuex data/state from the router into a component after the data has loaded.
I opened an issue there inca/voie#5 , but it's also related to this issue here #11 about getting it to work with vue-router.
Thanks.
It is pretty clear how to use the Vuex with single page app with only one active view.
But how do I manage states in more complex app with different views?
Should I override v-link behavior and run a mutation to change the view?
It would be awesome if you could provide an example for this case, thanks!
I'm new to the flux pattern. Since components are not supposed to mutate state directly. How would a component designer use v-model directive easily within their app?
I tried inside a mutation to to state.obj = defaultStateBuilder()
that return a fresh object with the initial default state but it doesn't work as the docs say it should. In the end I had to do this:
_.pairs(newState).map((x) => Vue.set(state, x[0], x[1]))
But I would assume that state.obj = newState
should work according to the section "Mutations Follow Vue's Reactivity Rules" in http://vuex.vuejs.org/en/mutations.html
Introduce a getter consolidation like that of mutations to pass through the state object.
export function isPasswordInvalid({user}) {
if (user.password < minPasswordLength) return false;
return false;
}
I tried to return some value in actions. But i found out that the value received in components is always undefined. (For some reason I don't want to use states here.) Is it a bug?
I am working on a reusable widget which will be used in a SPA based on vue/vuex. I found it a little bit tricky to expose the mutation/action/state of the widget to the SPA. I had to transform the original mutation/action/state to some form that could be composed together (https://github.com/blu3gui7ar/b9-modeler/blob/develop/src/store/index.js#L36). But I think there should be some official recommendations.
In redux, reducer composition is considered as the fundamental pattern of building Redux apps. The combineReducers(reducers) API helps composite reusable widgets together.
What should I do inside a mutation? Can it change other store values, or should I restrict it to changing only the main value? Because if it is the latter I see a redundancy between mutations and actions, actions could access the store directly instead of reinventing the wheel calling a mutation that triggers the "true" change of state.
I'm really liking the Fetch API and I'm having a difficult time imagining how it could be cleanly written for Vuex.
Hello,
The problem:
Mutation or otherwise action which fires the mutation does not fire predictably.
The circumstances:
Having:
An input element with @focus
and @blur
event listeners that trigger the visibility a <div>
element on the page.
The <div>
contains an <ul>
with each <li>
having an @click
event listener which fires a store action.
Expected behavior when clicking on the <li>
The store action should be called.
The mutation should be fired by the action and change the application state.
The <div>
should disappear as the input lost focus on clicking the <li>
.
Actual behavior when clicking on the <li>
Sometimes
The store action is not called.
The mutation as a consequence is not fired.
The <div>
does disappear as the input lost focus on clicking the <li>
.
Sometimes it acts as expected.
Using Vue.nextTick (needlessly) on data change had no effect as expected.
Having the <div>
always visible eliminates the problem and actions fire as expected.
This would be useful for i18n. I wouldn't need to pass down a computed property consuming the store to every component.
export default {
[type.GET_PAPERS] (state, force = false) {
fetch(`${apiUrl}/api/paper`).then(r => r.json())
.then(data => state.papers = data) // Error: [vuex] Do not mutate vuex store state outside mutation handlers.
// state.papers = [1, 2, 3, 4] // ok
}
}
Uncaught Error: [vuex] Do not mutate vuex store state outside mutation handlers.
use Vuex.createLogger
when I change the state in an setTimeout
function in mutation
like this:
import { SET_MSGTIP } from '../mutation-types'
// initial state
// shape: [{ id, quantity }]
const msgTipInitialState = {
text:''||'😂',
show:false,
timer:0
}
// mutations
const msgTipMutations = {
[SET_MSGTIP]({ msgTip }, text) {
clearTimeout(msgTip.timer)
msgTip.text = text
msgTip.show = true
msgTip.timer = setTimeout(() => {
msgTip.show = false
},2500)
},
}
export { msgTipInitialState, msgTipMutations }
Is unable to change state in the setTimeout method ?
https://github.com/vuejs/vuex/blob/master/docs/zh-cn/forms.md
最后一段Vuex 并强制要求所有的状态都必须放在 Vuex store 中
似乎应为Vuex 并非强制要求....
I'll be that guy.
0.5.0 won't work with my code I've written with 0.2.0.
through out my application I'm accessing my store actions like:
// application/store/index.js
import vuex from 'vuex';
import store from './store';
import mutations from './mutations';
import actions from './actions';
import middlewares from './middlewares';
const store = new Vuex.Store({
state,
mutations,
actions,
middlewares,
});
export default store;
application/states/root.vue
<template>
<input type="text" v-model="foo">
</template>
<script>
import store from 'application/store';
export default {
computed: {
foo: {
get () { store.state.Foo; },
set (value) { store.actions.updateFoo(value); } ,
}
}
};
</script>
This throws:
TypeError: Cannot read property 'updateFoo' of undefined
I would have only expected this when moving to 1.x.x
Some breaking changes currently being considered.
Currently, all components that need to display store state or invoke store actions import the store directly. This makes the component definitions rely on a global singleton, and leads to the following drawbacks:
So the first thing we can do, is instead of directly importing the store in child components, we only import it at the root component and "inject" it into all child components:
// Vue.use(Vuex) teaches Vue instances to handle the `store` option
import store from '../store'
import App from '../components/App.vue'
// render root
new Vue({
el: '#app',
store, // provide store, and inject to all children
components: { App }
})
Now, the store will automatically be available to all children as this.$store
(similar to how this.$router
is injected to all components enabled by vue-router). However, this makes things a bit more verbose and repetitive:
// example component after the change
export default {
computed: {
someState () {
return this.$store.state.someState
},
computedState () {
const { valueA, valueB } = this.$store.state
return valueA + valueB
}
},
methods: {
someAction (...args) {
this.$store.actions.someAction(...args)
}
}
}
So, the idea is introducing a vuex
option:
import { someAction } from '../store/actions'
export default {
vuex: {
state: {
someState: state => state.someState,
computedState: ({ valueA, valueB }) => valueA + valueB
},
actions: {
someAction, // becomes available as a method `this.someAction`
// ad-hoc inline action
inlineAction: ({ dispatch }, ...args) => dispatch('SOME_MUTATION', ...args)
}
}
}
Note what's happening here:
vuex.state
is basically sugar for computed properties. The difference is that the getters will get passed the store's state as the argument.vuex.actions
is sugar for mapping actions to methods. Note **we are no longer exposing the actions on the store itself. Now the store is only concerned with state and mutations. Actions are simply functions that take store as the first argument and dispatch mutations on it. What the vuex.actions
option does, is essentially binding raw action functions to this.$store
, and then defining it as a directly callable method on the component. Here we are using the Object literal shorthand, so the method name will be the same (someAction
). You can of course use a method name different from the imported function.Now, why do we no longer expose actions on the store? Several reasons:
store.actions
. By directly importing actions where needed, this problem no longer exists.actions.js
file). For example you can split them up into store modules, and don't need to worry about not knowing which module an action is defined in.Because actions are defined without directly depending on the store (instead takes it as an argument), importing them doesn't cause the singleton problem. When they are bound by vuex.actions
internally, they just use whatever store the component has.
Currently, module composition is a bit awkward:
import * as moduleA from './modules/a'
import * as moduleB from './modules/b'
export default new Vuex.Store({
state: {
a: moduleA.state,
b: moduleB.state
},
mutations: [moduleA.mutations, moduleB.mutations]
})
This can get annoying when there are many modules. Also, mutations inside modules always get the whole state tree. This leads to:
Here's an idea for a better composition API:
// a module
const state = {
count: 0
}
const mutations = {
INCREMENT: state => state.count++, // receives only the sub tree owned by this module
DECREMENT: state => state.count--
}
export default {
state,
mutations
}
// composing modules
import counter from './modules/counter'
const inlineModule = {
state: { n: 123 },
mutations: { INCREMENT: state => state.n++ }
}
export default new Vuex.Store({
state, // global state...
mutations, // global mutations...
modules: {
counter, // adds and manages `store.state.counter`
inline: inlineModule
}
})
So modules essentially become "sub stores" that manages a sub tree of the state.
Actions still get the entire store. Which means if an action is shipped within a module, it has no way to know how to resolve its local state.
How is one supposed to set nested keyPaths in state mutations, given that mutations only receive state and not store and therefore by implication no $set() method?
Take for instance the following, in the examples:
[DECREMENT] (state) {
state.count--
}
.. which is fine if you need to set or replace a root level keyPath
... but what when you need to set something nested, eg:
[UPDATE] (state, keyPath, value) {
// keyPath = state.user.userData.presence.status
}
What's the 'vue-y' way to change the value?
Using Baobab, we could set a cursor to that point or using the $set () method we could specify the dot notation keypath ... but when we only have the state object ... ?
As the title suggests, vuex
harshly handles global props.
When doing
new Vuex.Store({
state,
mutations
})
I get the following warning:
[Vue warn]: Props will not be compiled if no `el` option is provided at instantiation.
And I have a global mixin
with props
defined like this:
Vue.mixin({
props: {
id: {},
}
})
Stacktrace kindly pins the origin of issue:
// use a Vue instance to store the state tree
this._vm = new Vue({
data: state
});
Any information on the subject is much appreciated.
Using with coffeescript:
Vue = require 'vue'
Vuex = require 'vuex'
Vue.use Vuex
ES6 import works fine, but if I require Vuex, it throw out this error :)
shopping-cart 里面的Cart.vue文件store找不到 store.getters 方法 项目启动不了 报错
<input v-model="message">
// ...
computed: {
message: {
get: function () {
return store.state.message
},
set: function (newValue) {
store.dispatch("CHANGE_MESSAGE", newValue)
}
}
}
//...
essentially, waitFor
between stores.
Hello @yyx990803, do you plan to release a dist build for vuex ?
I use tonicdev at the moment as a playground but would love to see vuex integrated in cdnjs to embed it as an external resource on JSFiddle/Codepen.
Thanks in advance 👍
The project failed on install for me. After cloning the repos:
$ npm install
> [email protected] prepublish /Users/xxx/yyy/aaa/bbb/vuex
> babel src --out-dir lib --presets es2015 --plugins add-module-exports
The CLI has been moved into the package `babel-cli`. See http://babeljs.io/docs/usage/cli/
From package.json [scripts]:
"prepublish": "babel src --out-dir lib --presets es2015 --plugins add-module-exports",
This fails with an error ... but works with npm install -g babel babel-cli
Additionally, the index.js file shows:
let Vue
// then in constructor
this._vm = new Vue({
data: state
})
Generates an error in console at runtime:
Uncaught TypeError: Vue is not a function
was going to give this a go with Alt Flux, any immediate issues I should look out for?
如题.
I am getting this error:
Uncaught TypeError: Vue is not a function
At this specific line: https://github.com/vuejs/vuex/blob/master/src/index.js#L32
I am using the webpack template.
I was able to reproduce the issue applying these minimal changes to the initial template:
https://github.com/jbruni/vuex-webpack-issue/commit/50af38cfbb94dc27a6d48082d0e7ecd6d0650366
Please, take a look... I believe the solution for this issue is very simple.
(I was not sure if I should open the issue at webpack template repo or here. It seems a Vuex issue to me, so I opened here. Thank you.)
Note: the same error happens both using npm run dev
as well as building with npm run build
and HTTP serving the static build.
Is browser history supposed to work properly in the todomvc example as it currently stands? Because it doesn't seem to. Or would fully functioning browser history require integrating vue-router, or something else entirely?
As i've understood the concept all our actions have to be merged in one object.
So what with action's name isolation (namespaces) when i'm using one store with many submodule actions?
Hi,
I am very interested in getting vue to work with data coming into the client from a GraphQL server. Would vuex be the place to start working on that? Or would I need to code my own module to support and fill vue with data queried via GraphQL? I'd really like to be able to add GraphQL queries in vue components directly, similar to how it is done with React.
Thanks for any help on a proper direction.
Scott
I'm reviewing frameworks and watching videos and I noticed that Vuex is based upon Flux which from my beginner perspective is being phased out for Redux. Is there a reason why Flux is being pushed?
Imagine I have a simple login.vue component with a username and password field.
I attempt a login by calling store.actions.login(this.username, this.password)
I want to be able to hide a loading overlay, close the login screen, and provide reasons for login failure.
列子:视图 A B 是通过 vue router 来切换的。 视图A 本来有一部分内容是 隐藏的。
state : {
isShowAnything : false
}
再通过 action 改变了 sate的状态 isShowAnything = true 的时候, view a 中内容被显示。
这个时候 切换view 到 b, 再切换回 a...
默认被隐藏的内容仍是显示状态(因为是通过vue router切换的,所以 view 肯定是被销毁了, 我在 vue devtools里看 view的 props data已经重置)
这里的问题就很像 component 被 keep-alive了。
我不清楚 vuex 设计的时候 就是这样的,还是我使用中理解错了。还请解答一下,谢谢。
PS:因为英文组织能力较差,怕用英文提issues描述的更混乱,所以用中文提问,还请谅解。
Hi, is there any reason why vuex isn't registered with Bower?
If not, I can perfectly well do a merge request for a Bower.json.
Thanks!
After fresh npm and vuex installs while using browserify, creating new Vue.store continuely throws calendar_component.js:10205Uncaught TypeError: Cannot read property 'config' of undefined.
Opening up the error reveals this code:
function Store() {
var _this = this;
var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var _ref$state = _ref.state;
var state = _ref$state === undefined ? {} : _ref$state;
var _ref$mutations = _ref.mutations;
var mutations = _ref$mutations === undefined ? {} : _ref$mutations;
var _ref$modules = _ref.modules;
var modules = _ref$modules === undefined ? {} : _ref$modules;
var _ref$middlewares = _ref.middlewares;
var middlewares = _ref$middlewares === undefined ? [] : _ref$middlewares;
var _ref$strict = _ref.strict;
var strict = _ref$strict === undefined ? false : _ref$strict;
babelHelpers.classCallCheck(this, Store);
this._dispatching = false;
this._rootMutations = this._mutations = mutations;
this._modules = modules;
// bind dispatch to self
var dispatch = this.dispatch;
this.dispatch = function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
dispatch.apply(_this, args);
};
// use a Vue instance to store the state tree
// suppress warnings just in case the user has added
// some funky global mixins
var silent = Vue.config.silent;
Vue.config.silent = true;
this._vm = new Vue({
data: state
});
Vue.config.silent = silent; \\---------------> this is the line of the error here\\
this._setupModuleState(state, modules);
this._setupModuleMutations(modules);
this._setupMiddlewares(middlewares, state);
// add extra warnings in strict mode
if (strict) {
this._setupMutationCheck();
}
}
I have no idea why this is happening, i tried to reinstall both but continue with this error. Here is my root vue instance where i am trying to start the vuex store.
// browserify entrypoint
var Vue = require('vue');
import Vuex from 'vuex';
import calendarHeader from './components/Header.vue';
import calendarSettings from './components/Settings.vue';
import calendarContent from './components/Contents.vue';
const state = {
count: 0
}
const mutations = {
INCREMENT (state) {
state.count++
}
}
const store = new Vuex.Store({
state,
mutations
});
new Vue({
store,
el: '#calendar',
components: { calendarHeader, calendarSettings, calendarContent},
ready: function() {
console.log('Ready too go!');
console.log(store.state.count) // -> 1
},
methods: {
parallax: function() {
var velocity = 0.4;
var pos = $('#calendar').scrollTop();
var scr = Math.round((0 - pos) * velocity);
$('.current_day_header .header_window').css('backgroundPosition', '0 ' + scr + 'px');
if(scr < -200){
scr = -200;
}
}
}
});
How do i resolve this error? so fare i removed everything and narrowed it down to this line
const store = new Vuex.Store({
Can someone help me?
A couple things at once here, sorry. Hopefully I'm posting this in the correct location, apologies if not – I'm not a seasoned github user.
This is best shown by example. The following code, which is a module in my vuex store, doesn't work as expected (i.e. the changes aren't tracked by vue).
Note: this module is called "comments", the state variable in the mutation is named comments just because that's exactly what it is.
// "comments" module
const state = {};
const mutations = {
/**
* Stores the data from an ajax request into the state of comments
* @param comments [the state variable]
* @param data [the ajax data from server, an object containing a 'comments' property, which it itself is an object
**/
COMMENT_SETDATA (comments, data){
comments = data.comments;
},
};
export default {
state,
mutations
};
If I were to change this to comments.all = data.comments it would work, but just assigning this top level variable itself doesn't.
[Updated]: Clarified the situation a bit better.
The use of the this.$store
is not available when using Vuex and vue-router. This may be an issue with vue-router rather than Vuex.
I was trying to watch for the change of the store, I relied on the very hacky store._vm.$watch
. Does it make sense to use this?
If there is no better way to do it, would you accept a PR what exposes $watch in the public API?
hi all,
我们项目中最近准备引用vuex,但是发现一个问题:当我刷新浏览器地址的时候,state里面保存的数据被清空了。请指导一下怎么解决。
Hi
I am using NeDB in my project and also vuex. I am having issue to set initial data using promise since nedb returns value inside callback.
So how do we set initial state Data if we have a callback or either using a promise.
Not sure if I explained myself in the title... For example:
// actions.js
export default {
addMessage: 'addMessage', // This is the actual, which is OK.
removeMessage: null, // This is equivalent to removeMessage: 'removeMessage'
};
This would allow to greatly simplify direct actions (at least to me). What do you think?
cd examples/shopping-cart && webpack-dev-server --inline --hot --config ../webpack.shared.config.js
I am trying to test it out. I am running this on ubuntu 14.10 . on running npm install warning is " [email protected] requires a peer of babel-runtime@^5.8.0 but none was installed."
on running : npm run cart
i am getting the following error
events.js:85
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE
at exports._errnoException (util.js:746:11)
at Server._listen2 (net.js:1129:14)
at listen (net.js:1155:10)
at net.js:1253:9
at GetAddrInfoReqWrap.asyncCallback as callback
at GetAddrInfoReqWrap.onlookup as oncomplete
any help please
Hi !
I see a lot of comments talking about multi-language / vue-router and vuex.
#1 #2 #3
Internationalisation is missing in Vue.
And I think, it should be in the core system.
We have some good plugins like i18n
But it's not mature to be used in production see
I can't figure it out, what is the best way to do this?
Shouldn't this useful example be in the roadmap ?
To resume, we need
This is my first approach but i know i'm wrong (using vue-router and vue-i18n).
import Vue from 'vue'
import p404 from './pages/404/404.vue'
import Home from './pages/home/Home.vue'
import About from './pages/about/About.vue'
import Work from './pages/work/Work.vue'
import Contact from './pages/contact/Contact.vue'
module.exports = function(router){
router.map({
'*': { component: p404 },
'/': { name: 'home-en', component: Home, lang: 'en' },
'/about': { name: 'about-en', component: About, lang: 'en' },
'/work': { name: 'work-en', component: Work, lang: 'en' },
'/contact-us': { name: 'contact-en', component: Contact, lang: 'en' },
'/accueil': { name: 'home-fr', component: Home, lang: 'fr' },
'/a-propos': { name: 'about-fr', component: About, lang: 'fr' },
'/travaux': { name: 'work-fr', component: Work, lang: 'fr' },
'/contactez-nous': { name: 'contact-fr', component: Contact, lang: 'fr' }
})
router.beforeEach(function (transition) {
Vue.config.lang = transition.to.lang
transition.next()
})
}
<template>
<div class="Navigation">
<div class="Navigation__link-wrapper">
<a class="Navigation__link"
v-for="btn in menu"
v-link="{ name: btn.route, activeClass: 'Navigation__link--active' }">
{{ $t(btn.name) }}
</a>
<a href="#" @click.prevent="changeLang">
toggle lang
</a>
</div>
</div>
</template>
<script>
import Vue from 'vue'
export default {
data() {
return {
lang: Vue.config.lang
}
},
computed: {
menu() {
return [
{ route: 'about-' + this.lang, name: "navigation.about" },
{ route: 'work-' + this.lang, name: 'navigation.work' },
{ route: 'contact-' + this.lang, name: 'navigation.contact' },
]
}
},
methods: {
changeLang() {
this.lang = (this.lang == 'fr') ? 'en' : 'fr'
},
}
}
</script>
Any help will be appreciate !
Suddenly we are already at version 0.6.1
(at least at the moment I'm writing this)...
Is there a place (maybe a forum thread) where the latest changes are announced?
Please, let me know. I want to be using latest version, but I'm not sure if there are significant or breaking changes, or not.
Thank you!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.