javascript - 在控制台中获取消息但它不会更新 Rails + vuejs

标签 javascript ruby-on-rails vue.js vuejs2

我正在尝试使用 Rails (actioncable) 和 vuejs 进行聊天。

我从 actioncable 得到了正确的答案,但我无法更新前端的消息:您可以查看此图片:

enter image description here

这是我的 vue 代码:

<template>
  <div class="room-page">
    <div class="container page">
      <div class="row room-content">
        <div class="col-xs-12">
          <div>
            <h3>{{room.title}}</h3>
          </div>
        </div>
      </div>
      <hr/>
      <div class="row">
        <div class="col-xs-12 col-md-8 offset-md-2">
          <MessageEditor :id="id">
          </MessageEditor>
          <div class="card-messages">
            <Message v-for="(message, index) in filteredItems " :id="id" :message="message" :key="index">
            </Message>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import store from "@/store";
import MessageEditor from "@/components/Message/MessageEditor";
import Message from "@/components/Message/Message";
import { FETCH_ROOM, FETCH_MESSAGES } from "@/store/action-types";

import ActionCable from "actioncable";
var cable = ActionCable.createConsumer("ws://localhost:3000/cable");

export default {
  name: "Room",
  props: {
    id: {
      type: String,
      required: true
    }
  },
  components: {
    MessageEditor,
    Message
  },

  beforeRouteEnter(to, from, next) {
    cable.subscriptions.create("RoomChannel", {
      connected: function() {
        console.log("connected to rails actioncable Yay!");
      },
      disconnected: function() {
        console.log("disconnected");
      },
      received: (data) => this.messages.push(data)
    }),
      Promise.all([
        store.dispatch(FETCH_ROOM, to.params.id),
        store.dispatch(FETCH_MESSAGES, to.params.id)
      ]).then(data => {
        next();
      });
  },
  computed: {
    ...mapGetters(["room", "messages"]),
    filteredItems: function(messages) {
      return this.messages.slice(0, 20);
    }
  },
  watch: {
    messages(newMessage, oldMessage) {
      //muy atentos a cambios en el getter messages
      console.log("messages. We are be able to make a changes");
    }
  }
};
</script>

这是我的商店 vuex:

import {
  FETCH_ROOM,
  FETCH_MESSAGES,
} from "./action-types";
import { SET_MESSAGES } from "./mutation-types";
const initialState = {
  room: {
    title: ""
  },
  messages: []
};

export const state = Object.assign({}, initialState);

export const actions = {
  [FETCH_ROOM](context, roomId, prevRoom) {
    // avoid multiple network call if room exists
    if (prevRoom !== undefined) {
      return context.commit(SET_ROOM, prevRoom);
    }
    return RoomsService.get(roomId).then(({ data }) => {
      context.commit(SET_ROOM, data);
      return data;
    });
  },
  [FETCH_MESSAGES](context, roomId) {
    return MessagesService.get(roomId).then(({ data }) => {
      context.commit(SET_MESSAGES, data);
    });
  }
};

export const mutations = {
  [SET_ROOM](state, room) {
    state.room = room;
  },
  [SET_MESSAGES](state, messages) {
    state.messages = messages;
  }
};

const getters = {
  room(state) {
    return state.room;
  },
  messages(state) {
    return state.messages;
  }
};

export default {
  state,
  actions,
  mutations,
  getters
};

这是我的Message组件:

<template>
  <div class="card">
    <ul class="list-group list-group-flush">
      <li class="list-group-item">{{ message.content }}</li>
    </ul>
  </div>
</template>

<script>
  import {
    mapGetters
  } from "vuex";
  export default {
    name: "Message",
    props: {
      id: {
        type: String,
        required: true
      },
      message: {
        type: Object,
        required: true
      }
    }
  };
</script>

这是MessageEditor组件:

<template>
  <div>
    <list-errors :errors="errors">
    </list-errors>
    <form class="card message-form" v-on:submit.prevent="onSubmit(id, message)">
      <div class="card-block">
        <textarea class="form-control" v-model="message" placeholder="Write a message..." rows="3">
              </textarea>
      </div>
      <div class="card-footer">
        <button class="btn btn-sm btn-primary"> Post Message </button>
      </div>
    </form>
  </div>
</template>

<script>
  import {
    mapGetters
  } from "vuex";
  import ListErrors from '@/components/ListErrors/ListErrors'
  import {
    MESSAGE_CREATE
  } from '@/store/action-types'

  export default {
    name: 'MessageEditor',
    components: {
      ListErrors
    },
    props: {
      id: {
        type: String,
        required: true
      },
      content: {
        type: String,
        required: false
      },
    },
    data() {
      return {
        message: this.content || null,
        errors: {}
      }
    },

    methods: {
      onSubmit(id, message) {
        this.$store
          .dispatch(MESSAGE_CREATE, {
            id,
            message
          })
          .then(() => {
            this.message = null
            this.errors = {}
          })
          .catch(({
            response
          }) => {
            this.errors = response.data
          })
      }
    }
  }
</script>

更新了 @acdcjunior 代码,我得到: 无法读取未定义的属性“消息” 在 Subscription.received

今天早上还好好的,但是突然就坏了。 Rails Action 电缆服务器工作正常。

谢谢

最佳答案

考虑:

  beforeRouteEnter(to, from, next) {
    cable.subscriptions.create("RoomChannel", {
      connected: function() {
        console.log("connected to rails actioncable Yay!");
      },
      disconnected: function() {
        console.log("disconnected");
      },
      received: (data) => this.messages.push(data)
    }),
      Promise.all([
        store.dispatch(FETCH_ROOM, to.params.id),
        store.dispatch(FETCH_MESSAGES, to.params.id)
      ]).then(data => {
        next();
      });
  },

vue-router 的 beforeRouteEnter 钩子(Hook)在组件实例化之前执行,所以不会有 this (所以 收到:(data) => this.messages.push(data) 不起作用)。

我的建议是将加载从 beforeRouteEnter 移至 the created lifecycle hook组件的。

经过这些更改,上面的代码将变为:

created() {
   cable.subscriptions.create("RoomChannel", {
     connected: function() {
       console.log("connected to rails actioncable Yay!");
     },
     disconnected: function() {
       console.log("disconnected");
     },
     received: (data) => this.messages.push(data)
   }),
   store.dispatch(FETCH_ROOM, this.$route.params.id);
   store.dispatch(FETCH_MESSAGES, this.$route.params.id);
}

Promise.all() 已被删除,因为不再需要等待调度(因为现在不需要调用 next())。

关于javascript - 在控制台中获取消息但它不会更新 Rails + vuejs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49416762/

相关文章:

javascript - Json 合并左或右 Typescript

ruby-on-rails - Google Ruby API 客户端 redirect_uri_mismatch 错误

vue.js - vue-filter 不适用于 v-html

vue.js - 使用 vue 2、路由器和 vue-loader 进行引导

javascript - 使用对象文字和默认值创建 javascript 类的最佳方法

javascript - 每次值发生变化时,如何将更新的 prop 值传递给子进程?

ruby-on-rails - ruby on Rails rake db :migrate aborted

javascript - 显示搜索查询的点击次数 - vue - javascript

从 1970-01-01 查找毫秒数的 Javascript 方法?

ruby-on-rails - 带有标量字段和全文搜索的 Rails Sunspot Solr any_of