Ein Kanal ist ein serverseitiger Mechanismus, der sofortige Aktualisierungsfunktionen bietet. Stellen Sie die Datenroute ein und zeigen Sie die gesendeten Daten auf dem Client-Bildschirm an.
Wenn Sie die Datenroute festlegen oder JavaScript schreiben, um die gesendeten Daten anzuzeigen, können die gesendeten Daten asynchron angezeigt werden.
Führen Sie den folgenden Befehl im Terminal aus
% rails g channel comment
(Geben Sie den Namen der Datei, die Sie erstellen, in "Kommentar" ein.)
Es gibt mehrere Dateien, aber dieses Mal werden wir die folgenden zwei Dateien verwenden.
app/channel/comment_channel.rb
Eine Datei, die Client und Server verbindet.
app/javascript/channels/comment_channel.js Dies ist eine Datei zum Anzeigen der vom Server gesendeten Daten auf dem Client-Bildschirm.
class MessageChannel < ApplicationCable::Channel
def subscribed
stream_from "comment_channel"
end
def unsubscribed
end
end
Sie können den Server und den Client verbinden, indem Sie "stream_from" comment_channel "" schreiben.
Eine Beschreibung des Controllers. Da die nicht asynchrone Kommentarimplementierungsfunktion bereits abgeschlossen wurde, werden andere Erklärungen als die asynchrone Beschreibung weggelassen.
Die Daten, die ich dieses Mal in JS wiedergeben möchte, lauten wie folgt
Diese drei Informationen müssen vom Controller an JS übergeben werden.
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
@comment = Comment.new(comment_params)
@item = Item.find(params[:item_id])
@comments = @item.comments.includes(:user).order('created_at DESC')
if @comment.valid?
@comment.save
ActionCable.server.broadcast 'comment_channel', content: @comment, nickname: @comment.user.nickname, time: @comment.created_at.strftime("%Y/%m/%d %H:%M:%S"), id: @item.id
else
render "items/show"
end
end
private
def comment_params
params.require(:comment).permit(:text).merge(user_id: current_user.id, item_id: params[:item_id])
end
end
In dieser Implementierung wurde nur der folgende Satz hinzugefügt.
ActionCable.server.broadcast 'comment_channel', content: @comment, nickname: @comment.user.nickname, time: @comment.created_at.strftime("%Y/%m/%d %H:%M:%S"), id: @item.id
Da in JS "Inhalt", "Benutzer", "Zeit" und "ID" verwendet werden, habe ich sie definiert.
content
Definiert durch @comment: text, die Textspalte der Kommentartabelle, dh der von Ihnen eingegebene Kommentar.
user
Der Spitzname des mit @comment verknüpften Benutzers wird abgerufen. (Wir haben eine Assoziation mit Kommentar und Benutzer.)
time
Die Spalte created_at der Kommentartabelle. Jede Datums- und Uhrzeiteinstellung kann durch Schreiben von "strftime ("% Y /% m /% d% H:% M:% S ")" angezeigt werden. Ich habe auf den folgenden Artikel verwiesen.
Ich kann mich nicht an Strftime (Ruby) erinnern
item
JS muss nur auf der Seite des Elements ausgelöst werden, das Sie gerade anzeigen. Verwenden Sie es also, um dies zu bestimmen.
Dieses Mal werden wir es im receive ()
Teil von app / javascript / channel / comment_channel.js
beschreiben.
app/javascript/channels/comment_channel.js
received(data) {
}
Durch Schreiben von "Daten" in () kann der von der Steuerung definierte Wert erhalten werden. "empfangen" bedeutet empfangen. Wenn Sie also die Daten empfangen, führen Sie das darin beschriebene JS aus! Es bedeutet das. Jetzt werde ich JS darin beschreiben!
app/javascript/channels/comment_channel.js
//Rufen Sie die URL der aktuell geöffneten Seite ab
let url = window.location.href
//Schrägstrich(/)Extrahieren Sie jeweils Elemente
let param = url.split('/');
//Bei dieser App befindet sich die Element-ID ganz am Ende der URL und wird als paramItem definiert.
let paramItem = param[param.length-1]
//Parameter-ID(Die in der URL enthaltene ID)Vom Controller gesendet`data.id`Bestimmen Sie, ob
if (paramItem == data.id) {}
Die bedingte Verzweigung erfolgt mit der if-Anweisung. Als nächstes werde ich den Inhalt des Prozesses in den bedingten Zweig schreiben. Der zu beschreibende Inhalt ist
--Erstelle ein div-Element
Es ist wie ein Fluss.
app/javascript/channels/comment_channel.js
//Holen Sie sich die ID des Div des anzuzeigenden Ortes
const comments = document.getElementById('comments');
//Erstellen Sie ein div, das mit einer vorhandenen Ansichtsdatei identisch ist
const textElement = document.createElement('div');
textElement.setAttribute('class', "comment-display");
const topElement = document.createElement('div');
topElement.setAttribute('class', "comment-top");
const nameElement = document.createElement('div');
const timeElement = document.createElement('div');
const bottomElement = document.createElement('div');
bottomElement.setAttribute('class', "comment-bottom");
Verwenden Sie die Methode createElement, um ein div-Element zu erstellen, und geben Sie jeden erforderlichen Klassennamen mit der Methode setAttribute an.
Die Ansicht zum Anzeigen von Kommentaren ist übrigens wie folgt
<div id='comments'>
</div>
<% @comments.each do |comment| %>
<div class='comment-display'>
<div class='comment-top'>
<div><%= comment.user.nickname %></div>
<div><%= l comment.created_at %></div>
</div>
<div class='comment-bottom'>
<p><%= comment.text %></p>
</div>
</div>
<% end %>
Ich habe ein div-Element generiert, aber es ist im Browser noch nicht sichtbar. Lassen Sie es uns im Browser anzeigen und eine Eltern-Kind-Beziehung erstellen.
app/javascript/channels/comment_channel.js
//Zeigen Sie das generierte HTML-Element im Browser an
comments.insertBefore(textElement, comments.firstElementChild);
textElement.appendChild(topElement);
textElement.appendChild(bottomElement);
topElement.appendChild(nameElement);
topElement.appendChild(timeElement);
Verwenden Sie die insertBefire-Methode und die appendChild-Methode. Übergeordnetes Element.insertBefore (Element zum Hinzufügen, wo hinzugefügt werden soll) Übergeordnetes Element .appendChild (Element zum Hinzufügen) InsertBefire kann also ein Element an einer beliebigen Stelle einfügen, und appendChild kann ein Element am Ende der übergeordneten Klasse einfügen.
Wenn Sie etwas mehr Details sehen möchten, sehen Sie bitte unten [JavaScript] Unterschied zwischen appendChild und insertBefore
Lassen Sie uns nach dem Erstellen des div-Elements die Informationen anzeigen, die angezeigt werden sollen.
app/javascript/channels/comment_channel.js
const name = `${data.nickname}`;
nameElement.innerHTML = name;
const time = `${data.time}`;
timeElement.innerHTML = time;
const text = `<p>${data.content.text}</p>`;
bottomElement.innerHTML = text;
Die anzuzeigenden Informationen werden in jede Variable eingefügt. Daten sind die Daten für "empfangen (Daten) {}". Dies ist der in der Steuerung definierte Wert. Sie haben "Inhalt", "Spitzname" bzw. "Zeit" definiert. Überschreiben Sie vorhandene Elemente mit innerHTML.
Die Anzeige ist bis zu diesem Punkt vollständig! Bei dieser Rate gibt es jedoch zwei Probleme.
app/javascript/channels/comment_channel.js
const newComment = document.getElementById('comment_text');
newComment.value='';
Es ist eine Beschreibung, dass die ID des Kommentareingabefelds abgerufen und der Wert dort geleert wird.
app/javascript/channels/comment_channel.js
const inputElement = document.querySelector('input[name="commit"]');
inputElement.disabled = false;
Sie können mehrmals darauf klicken, indem Sie das Namensattribut der Schaltfläche "Kommentar" abrufen und als "deaktiviert = falsch" festlegen.
app/javascript/channels/comment_channel.js
import consumer from "./consumer"
consumer.subscriptions.create("CommentChannel", {
connected() {
},
disconnected() {
},
//↓ Wenn Sie die Daten erhalten, führen Sie sie aus.
received(data) {
let url = window.location.href
let param = url.split('/');
let paramItem = param[param.length-1]
if (paramItem == data.id) {
const comments = document.getElementById('comments');
const comment = document.getElementsByClassName('comment-display');
//Erstellen von Elementen zur Verwendung
const textElement = document.createElement('div');
textElement.setAttribute('class', "comment-display");
const topElement = document.createElement('div');
topElement.setAttribute('class', "comment-top");
const nameElement = document.createElement('div');
const timeElement = document.createElement('div');
const bottomElement = document.createElement('div');
bottomElement.setAttribute('class', "comment-bottom");
//Zeigen Sie das generierte HTML-Element im Browser an
comments.insertBefore(textElement, comments.firstElementChild);
textElement.appendChild(topElement);
textElement.appendChild(bottomElement);
topElement.appendChild(nameElement);
topElement.appendChild(timeElement);
//Generieren Sie den anzuzeigenden Text
const name = `${data.nickname}`;
nameElement.innerHTML = name;
const time = `${data.time}`;
timeElement.innerHTML = time;
const text = `<p>${data.content.text}</p>`;
bottomElement.innerHTML = text;
//Lassen Sie nach dem Senden eines Kommentars das Kommentarfeld leer
const newComment = document.getElementById('comment_text');
newComment.value='';
//Ermöglicht das mehrmalige Drücken der Taste
const inputElement = document.querySelector('input[name="commit"]');
inputElement.disabled = false;
}
}
});
Ich dachte, es sei abgeschlossen, aber zum Zeitpunkt des Schreibens fand ich eine Reihe von Fehlern und einige unklare Beschreibungen. Ich verstehe, wie wichtig Refactoring ist. Es mag falsche Aussagen geben, aber ich hoffe, es hilft jemandem.
Recommended Posts