teelou teelou - 2 years ago 323
jQuery Question

Vue.js + Socket.io - append an element in a real time app?

I'm new to Vue.js, so wonder how this can be done in Vue instead jQuery?

The socket.io and jQuery will

append
a
<li>
each time when someone has typed something on the browser.

<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});

socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>


How is this done in Vue?

I tried:

$(function () {
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});

var app = new Vue({
el: '#app',
data: {
message: "Hello World"
},
created: function() {
socket.on('chat message', function(data) {
this.message = data.message;
}.bind(this));
}
});
});


in my new HTML:

<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
<span id="app">{{ message }}</span>
</form>


It does not work obviously.

Any ideas?

Answer Source

You can do it the complete vuejs way even without using jquery like this:

html

<div id="app">  
    <form @submit.prevent="submitMsg">
      <input id="m" autocomplete="off" v-model="inputMsg"/>
      <button type="submit">Send</button>
      <span>
          <ul>
              <li v-for="message in messages">{{message}}</li>
          </ul>
      </span>
    </form> 
</div> 

script

var app = new Vue({
      el: '#app',
      data: {
          socket: null,
          inputMsg: '',
          messages: []
      },
      created: function() {
        this.socket = io();
        this.socket.on('chat message', function(msg) {
            this.messages.push(msg);
        }.bind(this));
      },
      methods:{
          submitMsg(){
               this.socket.emit('chat message', this.inputMsg);
               this.inputMsg = '';
          }
      }
    });

So what''s happening:

  • Wrapped the whole html with a div of id='app' so that it is controlled by vue

  • added a submit event on the form using @submit.prevent which calls the method submitMsg. The prevent modifier prevents form from being actually submitting

  • setup a v-model on the input which is two way data boun

  • now you can use the v-model which is inputMsg to get the value of the input and use it in the form submission method

  • after emitting the socket event setting the input value empty using this.inputMsg = '';

  • in crated lifecycle hook setup a socket event listener and push message to the data property messages:[] which is initialized as an empty array

  • loop trough the messages[] in your template using v-for='message in messages'which renders a <li> element for every item in messages[]

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download