最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to avoid the need of writing this.$store.state.donkey all the time in Vue? - Stack Overflow

programmeradmin1浏览0评论

I'm learning Vue and I noticed that I have the following syntax more or less everywhere.

export default {
  components: { Navigation, View1 },
  computed: {
    classObject: function() {
      return {
        alert: this.$store.state.environment !== "dev",
        info: this.$store.state.environment === "dev"
      };
    }
  }
}

It's a pain to write out this.$store.state.donkey all the time and it lowers the readability too. I'm sensing that I'm doing it in a less than optimal way. How should I refer to the state of the store?

I'm learning Vue and I noticed that I have the following syntax more or less everywhere.

export default {
  components: { Navigation, View1 },
  computed: {
    classObject: function() {
      return {
        alert: this.$store.state.environment !== "dev",
        info: this.$store.state.environment === "dev"
      };
    }
  }
}

It's a pain to write out this.$store.state.donkey all the time and it lowers the readability too. I'm sensing that I'm doing it in a less than optimal way. How should I refer to the state of the store?

Share Improve this question asked Dec 1, 2016 at 11:31 Konrad VilterstenKonrad Viltersten 39.1k84 gold badges284 silver badges506 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 23

you can set computed properties for both states & getters i.e.

computed: {
    donkey () {
        this.$store.state.donkey
    },
    ass () {
        this.$store.getters.ass
    },
    ...

Whilst you still need to call the $state.store once you can then reference a donkey or an ass on your vm...

To make things even easier you can pull in the vuex map helpers and use them to find your ass ... or donkey:

import { mapState, mapGetters } from 'vuex'

default export {

    computed: {

        ...mapState([
            'donkey',
        ]),

        ...mapGetters([
            'ass',
        ]),

        ...mapGetters({
            isMyAss: 'ass', // you can also rename your states / getters for this component
        }),

now if you look at this.isMyAss you'll find it ... your ass

worth noting here that getters, mutations & actions are global - therefore they are referenced directly on your store, i.e. store.getters, store.commit & store.dispatch respectively. This applies whether they are in a module or in the root of your store. If they are in a module check out namespacing to prevent overwriting previously used names: vuex docs namespacing. However if you are referencing a modules state, you must prepend the name of the module, i.e. store.state.user.firstName in this example user is a module.


Edit 23/05/17

Since the time of writing Vuex has been updated and its namespacing feature is now a go to when you work with modules. Simply add namespace: true to your modules export, i.e.

# vuex/modules/foo.js
export default {
  namespace: true,
  state: {
    some: 'thing',
    ...

add the foo module to your vuex store:

# vuex/store.js
import foo from './modules/foo'

export default new Vuex.Store({

  modules: {
    foo,
    ...

then when you are pulling this module into your components you can:

export default {
  computed: {
    ...mapState('foo', [
      'some',
    ]),
    ...mapState('foo', {
      another: 'some',
    }),
    ...

this makes modules very simple and clean to use, and is a real saviour if you are nesting them multiple levels deep: namespacing vuex docs


I have put together an example fiddle to showcase the various ways you can reference and work with your vuex store:

JSFiddle Vuex Example

Or check out the below:

const userModule = {

	state: {
        firstName: '',
        surname: '',
        loggedIn: false,
    },
    
    // @params state, getters, rootstate
    getters: {
   		fullName: (state, getters, rootState) => {
        	return `${state.firstName} ${state.surname}`
        },
        userGreeting: (state, getters, rootState) => {
        	return state.loggedIn ? `${rootState.greeting} ${getters.fullName}` : 'Anonymous'
        },
    },
    
    // @params state
    mutations: {
        logIn: state => {
        	state.loggedIn = true
        },
        setName: (state, payload) => {
        	state.firstName = payload.firstName
        	state.surname = payload.surname
        },
    },
    
    // @params context
    // context.state, context.getters, context.commit (mutations), context.dispatch (actions)
    actions: {
    	authenticateUser: (context, payload) => {
        	if (!context.state.loggedIn) {
        		window.setTimeout(() => {
                	context.commit('logIn')
                	context.commit('setName', payload)
                }, 500)
            }
        },
    },
    
}


const store = new Vuex.Store({
    state: {
        greeting: 'Welcome ...',
    },
    mutations: {
        updateGreeting: (state, payload) => {
        	state.greeting = payload.message
        },
    },
    modules: {
    	user: userModule,
    },
})


Vue.component('vuex-demo', {
	data () {
    	return {
        	userFirstName: '',
        	userSurname: '',
        }
    },
	computed: {
    
        loggedInState () {
        	// access a modules state
            return this.$store.state.user.loggedIn
        },
        
        ...Vuex.mapState([
        	'greeting',
        ]),
        
        // access modules state (not global so prepend the module name)
        ...Vuex.mapState({
        	firstName: state => state.user.firstName,
        	surname: state => state.user.surname,
        }),
        
        ...Vuex.mapGetters([
        	'fullName',
        ]),
        
        ...Vuex.mapGetters({
        	welcomeMessage: 'userGreeting',
        }),
        
    },
    methods: {
    
    	logInUser () {
        	
            this.authenticateUser({
            	firstName: this.userFirstName,
            	surname: this.userSurname,
            })
        	
        },
    
    	// pass an array to reference the vuex store methods
        ...Vuex.mapMutations([
        	'updateGreeting',
        ]),
        
        // pass an object to rename
        ...Vuex.mapActions([
        	'authenticateUser',
        ]),
        
    }
})


const app = new Vue({
    el: '#app',
    store,
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuex"></script>

<div id="app">

    <!-- inlining the template to make things easier to read - all of below is still held on the component not the root -->
    <vuex-demo inline-template>
        <div>
            
            <div v-if="loggedInState === false">
                <h1>{{ greeting }}</h1>
                <div>
                    <p><label>first name: </label><input type="text" v-model="userFirstName"></p>
                    <p><label>surname: </label><input type="text" v-model="userSurname"></p>
                    <button :disabled="!userFirstName || !userSurname" @click="logInUser">sign in</button>
                </div>
            </div>
            
            <div v-else>
                <h1>{{ welcomeMessage }}</h1>
                <p>your name is: {{ fullName }}</p>
                <p>your firstName is: {{ firstName }}</p>
                <p>your surname is: {{ surname }}</p>
                <div>
                    <label>Update your greeting:</label>
                    <input type="text" @input="updateGreeting({ message: $event.target.value })">
                </div>
            </div>
        
        </div>        
    </vuex-demo>
    
</div>

As you can see if you wanted to pull in mutations or actions this would be done in a similar way but in your methods using mapMutations or mapActions


Adding Mixins

To extend the above behaviour you could couple this with mixins and then you'd only have to set up the above computed properties once and pull in the mixin on the component that needs them:

animals.js (mixin file)

import { mapState, mapGetters } from 'vuex'

export default {

    computed: {

       ...mapState([
           'donkey',
           ...

your component

import animalsMixin from './mixins/animals.js'

export default {

    mixins: [
        animalsMixin,
    ],

    created () {

        this.isDonkeyAnAss = this.donkey === this.ass
        ...
发布评论

评论列表(0)

  1. 暂无评论