프론트엔드/Nuxt

Nuxt 채팅 구현하기 #pusher #nuxt #vue #laravel

짱구를왜말려? 2023. 4. 26. 22:55
반응형
SMALL

# What?

- nuxt에 pusher 세팅하기

 

# How?

npm install pusher-js
<template>
    <div>
        <div v-for="message in messages.data" :key="message.id">{{message.body}}</div>

        <form @submit.prevent="storeMessage">
            <input type="text" placeholder="내용을 입력하세요" v-model="form.body">
        </form>
    </div>
</template>
<script>
import Pusher from 'pusher-js';
import Form from "@/utils/Form";

export default {
    middleware: ["auth"],

    data(){
        return {
            form: new Form(this.$axios, {
                page: 1,
                chat_id: "",
                body: "",
            }),

            messages: {
                data: [],
                links: {},
                meta: {}
            },

            chat: null,
        }
    },

    methods: {
        setChannel(chat){
            let self = this;

            Pusher.logToConsole = true;

            let key = process.env.NODE_ENV === "production" ? "실서버용 키값" : "로컬용 키값";

            var pusher = new Pusher(key, {
                cluster: 'ap3'
            });

            var channel = pusher.subscribe('chats.' + chat.id);

            channel.bind('App\\Events\\MessageCreated', function(data) {
                self.messages.data.push(data.message);
            });
        },

        getChat(){
            this.$axios.get("/api/chats", {
                params: {
                    application_id: this.$route.query.application_id
                }
            }).then(response => {
                this.chat = response.data.data;

                this.getMessages(false, this.chat);

                this.setChannel(this.chat);
            });
        },

        getMessages(loadMore = false, chat){
            this.form.chat_id = chat.id;

            this.$axios.get("/api/messages", {
                params: this.form
            }).then(response => {
                if(loadMore)
                    return this.messages = {
                        ...response.data,
                        data: [...this.messages.data, ...response.data.data]
                    };

                this.messages = response.data;
            });
        },

        storeMessage(){
            this.form.post("/api/messages")
                .then(response => {
                    this.form.body = "";
                });
        }
    },

    mounted() {
        this.getChat();
    }
}
</script>

 

* 주의사항 laravel broadcastOn할 때 PrivateChannel 아닌 그냥 Channel 써야함

@ MessageCreated.php

<?php

namespace App\Events;

use App\Http\Resources\MessageMiniResource;
use App\Http\Resources\MessageResource;
use App\Models\Message;
use Carbon\Carbon;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class MessageCreated implements ShouldBroadcastNow
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Message $message)
    {
        $this->message = MessageResource::make($message);

        // $this->dontBroadcastToCurrentUser();
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('chats.'.$this->message->chat_id);
    }
}

 

@ channels.php

Broadcast::channel('chats.{chat}', function ($user, \App\Models\Chat $chat) {
    return $chat->users->contains($user->id);
});

 

@ .env 설정 (푸셔에 있는 내용으로)

LIST