我正在尝试使用 Rails (actioncable) 和 vuejs 进行聊天。
我从 actioncable 得到了正确的答案,但我无法更新前端的消息:您可以查看此图片:
这是我的 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/