Vuejs:组件聚合

时间:2017-07-18 11:06:07

标签: vue.js vue-component

从以下简单的类似reddit的示例开始:https://jsfiddle.net/coligo/g7mu5ndz/

Vue.component('post', {
  template: "#post-template",
  props: ['post'],
  data: function () {
    return {
      upvoted: false,
      downvoted: false
    };
  },
  methods: {
    upvote: function () {
      this.upvoted = !this.upvoted;
      this.downvoted = false;
    },
    downvote: function () {
      this.downvoted = !this.downvoted;
      this.upvoted = false;
    }
  },
  computed: {
    votes: function () {
      if (this.upvoted) {
        return this.post.votes + 1;
      } else if (this.downvoted) {
        return this.post.votes - 1;
      } else {
        return this.post.votes;
      }
    }
  }
});

var vm = new Vue({
  el: "#app",
  data: {
    posts: [{
        title: "A post for our reddit demo starting at 15 votes",
        votes: 15
      },
      {
        title: "Try out the upvoting, it works, I promise",
        votes: 53
      },
      {
        title: "coligo is the bomb!",
        votes: 10
      }]
  }
});

我想:

  • a)显示upvotes的总数(在帖子列表中,在#app div
  • 中)
  • b)对于每个帖子,显示已获得的总投票的百分比

如果不管理父母中的每个帖子状态,这是否可行?

1 个答案:

答案 0 :(得分:0)

需要对代码进行太多的重构,这里不能解释。所以这是working fiddle

我只是指出关键变化:

  • 您正在对组件添加和减去投票,但您通过道具获取数据,因此您应该通过发出事件来更新父级。有用的链接:custom eventsprops are one-way

  • 您可以使用计算属性来计算父屁股中的总投票数现在是upvotes,而downvotes正在对父项中存在的主要数据进行更改

  • 将总票数从父组件传递给子组件作为道具来计算百分比票数

        Vue.component('post', {
      template: "#post-template",
      props: ['post', 'total'],
      data: function () {
        return {
          upvoted: false,
          downvoted: false,
    
        };
      },
      computed:{
          percentVotes(){
            return (this.post.votes/this.total * 100).toFixed(2)
          }
      },
      methods: {
        upvote: function () {
          if(!this.upvoted){
              this.upvoted = true;
              this.downvoted = false;
              this.$emit('upvoted');
          }
    
        },
        downvote: function () {
          if(!this.downvoted){
              this.downvoted = true;
              this.upvoted = false;
              this.$emit('downvoted');
          }
        }
      }
    });
    
    var vm = new Vue({
      el: "#app",
      data: {
        posts: [{
                    title: "A post for our reddit demo starting at 15 votes",
                    votes: 15
                },
                {
                    title: "Try out the upvoting, it works, I promise",
                    votes: 53
                },
                {
                    title: "coligo is the bomb!",
                    votes: 10
                }]
      },
      methods: {
          upvoted(post){
              post.votes = post.votes +1;
          },
          downvoted(post){
              post.votes = post.votes - 1;
          }
      },
      computed:{
          totalVotes(){
            var postVotes = this.posts.map((post) => {
                  return post.votes;
              });
    
              var getTotal = function (total, num) {
                return total + num;
             }
             return postVotes.reduce(getTotal);
          }
      }
    });