Conditional v-if is working only for the first tim

2019-08-07 03:40发布

问题:

I have this in my view:

<div class="already_voted" v-if="already_voted" >
    <p>You already voted or your are not allowed to vote</p>
  </div>

This is my method :

 upvote: function(com_id) {

              var comment_id = {
                comment_id :com_id
              }
              this.$http.post('/blog/article/comment/upvote', comment_id).then(function(response){
                upvote_total= response.data.upvote_value;
                  this.already_voted = response.data.already_voted;
                  this.$dispatch('child-msg', this.already_voted);
                $('.upvote_class_' + com_id ).text(upvote_total);
                $('.isDisabledUpvote_' + com_id).addClass('disabled');
                 $('.isDisabledDownvote_' + com_id).removeClass('disabled');
              },function(response){

              });

          },

Im getting value on click and if its true it need to show this div. Problem is that this div is showed only for first time when already_voted is true and thats it. Next time when its true nothing happend. Any suggestion?

回答1:

It looks like you are mixing jQuery and Vue, which should be avoided unless you have a specific reason to do so. Instead you should bind attributes to data. As a basic version of what you are doing you could bind both the disabled attribute and the message to a voted flag:

Markup

<div id="app">
  <div v-if="voted">
    You have already voted!
  </div>
  <button v-bind:disabled="voted" @click="vote()">
  Vote
  </button>
    <button v-bind:disabled="!voted" @click="removeVote()">
  Un-Vote
  </button>
</div>

View Model

new Vue({
  el: '#app',
  methods: {
    vote(){
      this.voted = true;
    },
    removeVote(){
      this.voted = false;
    }
  },
  data: {
    voted: false
  }
});

Here I'm simply binding the disabled attribute using v-bind to the voted flag to disabled the buttons and am using v-if to show a message if the voted flag is true.

Here's the JSFiddle: https://jsfiddle.net/05sbjqLL/

Also be aware that this inside an anonymous function refers to the anonymous function itself, so either assign this to something (var self = this) outside the function or use an arrow function if using ES6.

EDIT

I've updated the JSFiddle to show you how you might handle your situation based on you comments:

https://jsfiddle.net/umkvps5g/

Firstly, I've created a directive that will allow you to initiate your variable from your cookie:

Vue.directive('init', {
  bind: function(el, binding, vnode) {
    vnode.context[binding.arg] = binding.value;
  }
})

This can now be used as:

<div v-init:voted="{{ $request->cookie('voted') }}"></div>

I simply disabled the button to show you how to bind attributes to data, there's loads more that can be done, for example showing the message after a user clicks the button, I've just added a click counter and bound thev-if to that instead, so the message doesn't show until a user clicks the button:

<div v-if="vote_attempts">
  You have already voted!
</div>

Then in vote() method:

vote() {
    this.voted = true;
    this.vote_attempts++;
  },

Then data:

  data: {
    voted: false,
    vote_attempts: 0
  }