javascript - 在 AngularJS 中使用范围和 Controller 时发生冲突

标签 javascript angularjs node.js socket.io

我有一个使用 AngularJS 和 NodeJS 后端的简单网站。

它有多个页面,如主页、登录/注册页面等。

我想实现一个“聊天”页面,您可以在其中使用 socket.io 向其他客户端发送消息。我已经让那部分工作了,使用本地 Controller (本地,我的意思是在单个页面上激活 - 聊天页面)。

问题是,我希望聊天系统是全局的(即客户端可以在主页上接收消息,但它们仍然只会在返回聊天页面时显示)。


我在设置全局聊天 Controller (在所有页面上都处于事件状态)时遇到问题。

下面是我如何包含它:

<body ng-controller="AppCtrl"> <!-- include main controller -->
    <div ng-include="'header.tpl.html'"></div>
    <div ng-controller="ChatCtrl" class="page"> <!-- include global Chat controller -->
        <div ng-view class="container"></div>
    </div>
    <div ng-include="'footer.tpl.html'"></div>
    <!-- ...etc. -->
</body>

这工作得很好,但似乎我无法从我的聊天页面访问值。从 Chat Controller 声明的函数仍然可以调用,但“$scope.message”值(包含正在键入的消息)始终为空。


这是我的聊天 Controller (实际上称为 TravelCtrl)

angular.module('base').controller('TravelCtrl', //['$scope', 'security',
  function($rootScope, $scope, security, NgMap, $geolocation, socket){

    $scope.messages = [];

    // Socket listeners
    // ================

    socket.on('init', function (data) {
      $scope.name = data.name;
      $scope.users = data.users;
    });

    socket.on('send:message', function (message) {
      $scope.messages.push(message);
    });

    socket.on('change:name', function (data) {
      changeName(data.oldName, data.newName);
    });

    socket.on('user:join', function (data) {
      $scope.messages.push({
        user: 'Server',
        text: 'User ' + data.name + ' has joined.'
      });
      $scope.users.push(data.name);
    });

    // add a message to the conversation when a user disconnects or leaves the room
    socket.on('user:left', function (data) {
      $scope.messages.push({
        user: 'chatroom',
        text: 'User ' + data.name + ' has left.'
      });
      var i, user;
      for (i = 0; i < $scope.users.length; i++) {
        user = $scope.users[i];
        if (user === data.name) {
          $scope.users.splice(i, 1);
          break;
        }
      }
    });

    // Private helpers
    // ===============

    var changeName = function (oldName, newName) {
      // rename user in list of users
      var i;
      for (i = 0; i < $scope.users.length; i++) {
        if ($scope.users[i] === oldName) {
          $scope.users[i] = newName;
        }
      }

      $scope.messages.push({
        user: 'Server',
        text: 'User ' + oldName + ' has been authenticated as ' + newName + '.'
      });
    }

    // Methods published to the scope
    // ==============================

    $scope.changeName = function () {
      socket.emit('change:name', {
        name: $scope.newName
      }, function (result) {
        if (!result) {
          alert('There was an error changing your name');
        } else {

          changeName($scope.name, $scope.newName);

          $scope.name = $scope.newName;
          $scope.newName = '';
        }
      });
    };

    $scope.sendMessage = function () {

      socket.emit('send:message', {
        message: $scope.message
      });

      // add the message to our model locally
      $scope.messages.push({
        user: $scope.name,
        text: $scope.message
      });

      // clear message box
      $scope.message = '';

    };

    // ================

    var init = function () {
      $scope.newName = security.currentUser.username;
      $scope.changeName();
    }

    if ($rootScope.hasLoaded() && $scope.name != security.currentUser.username) {
      init();
    } else {
      $rootScope.$on('info-loaded', init);
    }

  }
  //]
);

以及聊天页面本身。奇怪的是,连接的用户和消息显示正确,但 Controller 似乎无法检索键入的消息。

<div class='col'>
  <h3>Users</h3>
  <div class='overflowable'>
    <p ng-repeat='user in users'>{{user}}</p>
    </div>
</div>

<div class='col'>
    <h3>Messages</h3>
    <div class='overflowable'>
    <p ng-repeat='message in messages' ng-class='{alert: message.user == "chatroom"}'>{{message.user}}: {{message.text}}</p>
    </div>
</div>

<div class='clr'>
  <form ng-submit='sendMessage()'>
    Message: {{message}}<br/>
    <input size='60', ng-model='message'/>
    <input type='submit', value='Send as {{name}}'/>
    </form>
</div>

当按下“发送”按钮时,AngularJS 成功调用了 sendMessage 函数,但检索到的“消息”值是一个空字符串,导致它发送一个空的 socket.io 消息。


我是 AngularJS 的新手,所以我的方法可能完全荒谬。我确信我遗漏了一些明显的东西,但在再次阅读文档后,我似乎真的找不到什么。

这是组织 AngularJS 应用程序的正确方法吗?

预先感谢您的帮助。

最佳答案

最近构建了一个大型 Angular/Socket.IO 应用程序,我强烈建议您将所有 Socket 实现放入一个服务中。该服务将维护您所有的套接字状态,并允许您将其注入(inject)任何所需的 Controller 。这将允许您拥有聊天的主页,但仍然能够在应用程序的其他区域显示通知、聊天用户信息等。

关于javascript - 在 AngularJS 中使用范围和 Controller 时发生冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34425274/

相关文章:

javascript - 带有本地存储的下拉 CSS

javascript - Array.prototype.flatMap() JS 在测试用例和 repl.it 片段中表现奇怪,但在浏览器控制台中则不然

javascript - 使用 $(function 等启动 javascript 代码

javascript - Eloquent Javascript,局部变量是参数?

javascript - 来自 JSON 的每个元素的动态 CSS

javascript - Angularjs 使用 ng-repeat 和 <th> 标签来重复列标题

javascript - 仅更改一个跨度以在 ng-repeat 内输入

javascript - 如何在 Node.js 上编写快速排序

node.js - 使用 Nightwatch 进行拖放

node.js - 平均堆栈 - 平均 init 抛出错误