简体   繁体   中英

Vote button with Vue and Axios

I have an vote button in my app to vote for articles or comments. I almost got that to work with ajax but the sync of clicks and counter is the big problem. I now try to do it with vue js because someone recommended to do so referring to Sync vote button with backend vote function .

I have to say I am new to vue js and hope that someone can help me to get this to work. A little specification how I want it to work. A user can toggle the vote button so it adds +1 or 0 and changes the color like here on stack but only with an up button.

What I have for now sends the request to the backend and stores the vote in the database but I dont know how to set up the counter and color properly. What I have so far.

<template>
  <div>
      <a class="vote" :class="{ active: hasVotes }" @click="vote"></a>
      <div class="points">{{ votes }}</div>
  </div>
</template>

<script>
    export default {
        data(){
            return{
                votes: this.voted
            }
        },

        props: {
            voted: {
                required: true,
                type: Number
            },
            article: {
                required: true,
                type: Object
            }
        },

        computed: {
            hasVotes() {
                return this.votes > 0;
            }
        },

        methods:{
            vote(){
                axios.post('/article/vote/' + this.article.id)
                    .then(function (response) {
                        console.log(response.data);
                        this.votes = response.count;
                    });
            }
        }
    }
</script>

What I have else to say is that it is an laravel 5.7 app with vue.js integrated. Maybe it is better to do it with components...?

Best

It would be easier to encapsulate this in a component because Vue is data driven and now you actually have to dive into the DOM and manipulate the arrow color for a specific arrow when your count is larger than 0.

I have changed and simplified your code example. The first thing you want to do is not have separate votes and voteCount properties because they are simply the same thing. You want to receive the initial votes from the backend via an article prop and update it via your XHR call.

I have mocked up a quick example which I have not tested but this should get you going in the proper direction.

Example:

<upvote-arrow :article="{{ $article }}"></upvote-arrow>

Component:

<template>
    <div>
        <a class="arrow" :class="{ active: hasVotes }" @click="vote"></a>
        <div class="points">{{ votes }}</div>
    </div>
</template>

<script>
    export default {
        data(){
            return{
                votes: this.article.votes
            }
        },

        props: {
            article: {
                required: true,
                type: Object
            }
        },

        computed: {
            hasVotes() {
                return this.votes > 0;
            }
        },

        methods:{
            vote(){
                axios.post('/article/vote/' + this.article.id)
                    .then(function (response) {
                        this.votes = response.count;
                    });
            }
        }
    }
</script>

<style lang="scss" scoped>
    .active {
        border-color: transparent transparent #1267dc transparent;
    }
</style>

An active class will get applied to the anchor with a computed property when you have more than 1 vote. With this style binding you can change the color of the arrow.

It is also a better idea to only change the votes when the XHR call is actually successful because it might fail for some reason and the proper state is not reflected in that case. Just update the vote with the response of the backend.

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