简体   繁体   中英

Vue.js: Implementing client-side restful router with vue-router and a store

I'm trying to implement a client-side restful api with vue.js and vue-router, where route params can be used to display a subset of a store's data into components. All of the data the client needs is loaded into the store on initialization (much of that isn't being shown, including listeners to be sure the data is ready).

For example, say my store is structured as:

export default {
    "state": {
        "foosArray": [
            {
                "fooId": 1,
                "foo1": "bar",
                "foo2": "bar2"
            },
            {
                "fooId": 2,
                "foo1": "barbar1",
                "foo2": "barbar2"
            }
        ]
    }
}

Now let's say that I have a route that would like to display one of the foo's, based on a fooId in the route param, into a component: /foo/:fooId

In my Foo.vue file:

<template>
    <h1>FooId: {{ fooId }}</h1><br>
    <h2>Foo1: {{ foo1 }}<h2><br>
    <h2>Foo2: {{ foo2 }}</h2>
</template>

<script>
    export default {
        "name": "Foo",
        data () {
            return {
                "fooId": -1,
                "foo1": "",
                "foo2": ""
            }
        }
    }
</script>

Question: what's the best way to achieve this? I've thought of a few options, but none seem very optimal.

Option #1 - Computed Data: this has the benefit of being reactive (the point of using a library like vue.js... yay!), but at the expense of being computationally expensive. EDIT - turns out I can't use underscore, but rather need to use a bunch of for loops to return the right data.

Foo.vue

<template>
    <h1>FooId: {{ myFooId }}</h1><br>
    <h2>Foo1: {{ myFoo1 }}<h2><br>
    <h2>Foo2: {{ myFoo2 }}</h2>
</template>

<script>
    import Store from '../store/store.js'
    import _ from "underscore"

    export default {
        "name": "Foo",
        data () {
            return {
                "sharedState": Store.state
            }
        },
        "computed": {
            "myFooId": function() {
                let oTempFoo = _.findWhere(this.sharedState.foosArray, { "id": this.$route.params.fooId });

                return oTempFoo ? oTempFoo["id"] : "";
            },
            "myFoo1": function() {
                let oTempFoo = _.findWhere(this.sharedState.foosArray, { "id": this.$route.params.fooId });

                return oTempFoo ? oTempFoo["foo1"] : "";
            },
            "myFoo2": function() {
                let oTempFoo = _.findWhere(this.sharedState.foosArray, { "id": this.$route.params.fooId });

                return oTempFoo ? oTempFoo["foo2"] : "";
            }
        }
    }
</script>

Option #2 - Using vue-router's data pipeline. This has the benefit of being computationally simpler, but I don't believe this will be reactive to changes on the store's state (so what's the point?).

<template>
    <h1>FooId: {{ fooId }}</h1><br>
    <h2>Foo1: {{ foo1 }}<h2><br>
    <h2>Foo2: {{ foo2 }}</h2>
</template>

<script>
    import Store from '../store/store.js'
    import _ from "underscore"

    export default {
        "name": "Foo",
        data () {
            return {
                "fooId": -1,
                "foo1": "",
                "foo2": ""
            }
        },
        "route": {
            data: function (transition) {
                let oTempFoo = _.findWhere(Store.state.foosArray, { "id": this.$route.params.fooId })
                transition.next(oTempFoo);
            }
        }
    }
</script>

Thanks!

I've implemented the following. It saves me from having to run computed data elements for each of my displayed values. I wish there was something simpler, like maybe a v-with="myFoo" that I could implement in UberFoo so I didn't need to use a sub-component.

UberFoo.vue

<template>
    <minor-foo :data="myFoo"><minor-foo>
</template>

<script>
    import Store from '../store/store.js'
    import MinorFoo from './MinorFoo.vue'

    export default {
        'name': 'UberFoo',

        data () {
            return {
                'sharedState': Store.foosArray
            }
        },

        'components': {
            'minor-foo': MinorFoo
        },

        'computed': {
            myFoo: function() {
                for ( var i = 0; i < this.sharedState.length; i++ ) {
                    if ( this.sharedState[i]["fooId"] == this.$route.params.fooId ) return this.sharedState[i];
                }

                return {
                    "fooId": null,
                    "foo1": null,
                    "foo2": null
                }
            }
        }
    }
</script>

MinorFoo.vue

<template>
    <h1>FooId: {{ data.fooId }}</h1><br>
    <h2>Foo1: {{ data.foo1 }}<h2><br>
    <h2>Foo2: {{ data.foo2 }}</h2>
</template>

<script>
    export default {
        'name': 'MinorFoo',

        'props': ['data']
    }
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM