为什么在jquery触发器动态更新后socket.emit会重复?

时间:2017-09-06 15:35:22

标签: javascript jquery html node.js socket.io

我试图更新(或更改)客户端代码中显示的div(" display-holder")的内容,这个div包含调用外部函数的html和jQuery使用socket.emit的div,但是一旦我替换了这个div内容,socket.emit的函数会多次触发,我也会使用off()和unbind()函数,但是他们不会这样做。似乎工作。有没有办法动态替换div(显示持有者)内容并让socket.emit只触发一次?

客户端

<!DOCTYPE html>
<html>
<head>
    <title>Help!</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="/socket.io/socket.io.js"></script>
    <script>
    //Globals
    var displayCounter = 1;

    //Socket.io client side

      var socket = io('http://localhost');


      socket.on('news', function (data) {
        console.log(data);
        $('#message-displayer').append("<b> Server says: </b>"+data.msg+"<br>");

      });
      socket.on('client-answer', function (data) {
        console.log(data);
        $('#message-displayer').append("<b> Server says: </b>"+data.msg+"<br>");
        socket.emit('message', { msg: 'my data from client' });
      });

      //emitter function
      function sendData(data){
        socket.emit("client-message", { msg:data });
      }
    </script>

    <style> 

        #display-holder{
          position: absolute;
          margin: auto;
          top: 0;
          right: 0;
          bottom: 0;
          left: 0;
          width: 500px;
          height: 300px;
          background-color: #ccc;
          border-radius: 3px;
          text-align:center
        }
        .display-holder-nodes{
         display: inline-block;
         border: 1px solid black;
         width: 95%;
        }
        button, input{ 
         width: auto;
         height: auto; 
         padding: 10px; 
         margin-top: 16px;
        }
        #message-displayer{ height:70%; overflow-y: scroll;}
        #control-panel{ height:25%; text-align:center;}

    </style>

</head>
<body>
    <div id="display-holder">
        <div id="message-displayer" class="display-holder-nodes"></div>
        <div id="control-panel" class="display-holder-nodes">
            <input type="text" id="clientInput">
            <button id="sendMessage">Send message</button>
            <button id="changeDisplay">Change display</button> 
        </div>
        <script>
        //jQuery handlers (will be replace when clicking "#changeDisplay" btn)

            $(document).on('click', '#sendMessage', function(){
                 $('#message-displayer').append("<b> You said: </b>"+$('#clientInput').val()+"<br>");
                sendData($("#clientInput").val());
                 $('#clientInput').val('');
            });

        </script>
    </div>


<script>
    //jQuery handlers 

    $(document).on('click', '#changeDisplay', function(){
        displayCounter++;
        //html and jquery to be inserted dynamically
        $("#display-holder").empty().off().unbind().html('  <div id="display-holder">'+
        '<div id="message-displayer" class="display-holder-nodes"><h3>Dislplay #'+displayCounter+'</h3></div>'+
        '<div id="control-panel" class="display-holder-nodes">'+
            '<input type="text" id="clientInput">'+
            '<button id="sendMessage">Send message</button>'+
            '<button id="changeDisplay">Change display</button> '+
        '</div>'+
        '<script>'+
            '$(document).on("click", "#sendMessage", function(){'+
                ' $("#message-displayer").append("<b> You said: </b>"+$("#clientInput").val()+"<br>");'+
                 'sendData($("#clientInput").val());'+
                ' $("#clientInput").val("");'+
            '});'+
        '</sc'+'ript>'+
    '</div>');
    });



</script>

</body>
</html>

服务器侧

var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');

app.listen(80, function(){
    console.log('App listening on port 80');
});

function handler (req, res) {

  fs.readFile(__dirname + '/public/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}



io.on('connection', function (socket) {

  socket.emit('news', { msg: 'hello client' });


  socket.on('message', function (data) {
    console.log('Client says: ', data);

  });

  socket.on('client-message', function (data) {
    console.log('Client says: ', data);
    socket.emit('client-answer', { msg: 'You sent me: '+data.msg });
  });

});

1 个答案:

答案 0 :(得分:0)

您要将活动附加到document并删除附加到display_holder的活动。

documentation

所述
  

.on()方法将事件处理程序附加到当前选定的集合   jQuery对象中的元素

.on()更改为$("#display_holder").on('click'