ngSrc更新了ngClick,但没有更新keydown事件处理程序

时间:2018-04-19 13:59:40

标签: javascript angularjs

我正在开发一个实时地图类型的应用程序,它有一些导航按钮(例如平移,缩放等)。我添加了一个keydown事件处理程序以允许键盘控制。事件处理程序调用相同的方法。

我发现奇怪的是按钮在加载图像的响应中是活泼可靠的,但是keydown响应速度非常慢。现在,我实际上认为图像更新是由于$interval服务重复获取它而不是来自keydown事件。注意:我已经通过为url添加日期/时间等唯一数据来处理陈旧的缓存图像(这是一个单独的问题)。

我添加了控制台日志记录,以确保imgUrl实际上正在发生变化,确实如此。似乎按钮单击导致ngSrc使用更新的imgUrl重新渲染,但键盘事件不是。这是一个简化的测试应用程序,它使用按钮和't'键重新创建相同的行为,在这种情况下,它们是keydown事件:

Plunker

的javascript

var myApp = angular.module("myApp", ['ngMaterial'])
    .controller("myCtrl", function ($scope)
    {
        $scope.isToggled = false;

        $scope.Toggle = function ()
        {
            console.log("Toggle(Start): " + $scope.imgUrl);

            if ($scope.isToggled)
            {
                $scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Grassland_wiki.jpg/640px-Grassland_wiki.jpg";
            }
            else
            {
                $scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Monotropa_uniflora_03769.jpg/640px-Monotropa_uniflora_03769.jpg";
            }

            $scope.isToggled = !$scope.isToggled;

            console.log("Toggle(End): " + $scope.imgUrl);
        };

        $scope.ProcessKey = function (e)
        {
            if (e.key === "t")
            {
                $scope.Toggle();
            }
        };

        $scope.Toggle();
        document.addEventListener("keydown", $scope.ProcessKey);
    });

HTML

<div ng-controller="myCtrl" ng-app="myApp">
    <md-button class="md-raised" ng-click="Toggle()">Toggle</md-button>
    <img id="testImg" ng-cloak ng-src="{{imgUrl}}">
</div>

我在javascript和angularjs中遇到了支持C#应用程序的问题,这是我的大部分经验。

我不确定根本原因是什么。也许这与引用$scope函数变量/表达式的javascript事件监听器有关?部分依赖是在我的主应用程序中,我使用$http服务来获取图像。

我有这样的替代方式吗?有没有办法强迫图像重新渲染?

3 个答案:

答案 0 :(得分:2)

因为您在AngularJS之外添加了一个事件,所以Angular永远不会知道$scope属性已更改。所以你手动告诉Angular使用$scope.$apply()改变了一些东西。

var myApp = angular.module("myApp", [])
    .controller("myCtrl", function ($scope)
    {
        $scope.isToggled = false;

        $scope.Toggle = function ()
        {
            console.log("Toggle(Start): " + $scope.imgUrl);

            if ($scope.isToggled)
            {
                $scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Grassland_wiki.jpg/640px-Grassland_wiki.jpg";
            }
            else
            {
                $scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Monotropa_uniflora_03769.jpg/640px-Monotropa_uniflora_03769.jpg";
            }

            $scope.isToggled = !$scope.isToggled;

            console.log("Toggle(End): " + $scope.imgUrl);
        };

        $scope.ProcessKey = function (e)
        {
            if (e.key === "t")
            {
                $scope.Toggle();
                $scope.$apply();
            }
        };

        $scope.Toggle();
        document.addEventListener("keydown", $scope.ProcessKey);
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="myCtrl" ng-app="myApp">
    <button class="md-raised" ng-click="Toggle()">Toggle</button>
    <img id="testImg" ng-cloak ng-src="{{imgUrl}}">
</div>

答案 1 :(得分:1)

您可以使用$scope.apply(handler)

$scope.apply(function () {
    // Angular is now aware that something might of changed
    $scope.changeThisForMe = true;
});

答案 2 :(得分:0)

注意:我更喜欢$scope.apply();解决方案,因为它们不需要首先关注网站元素。

因为我很顽固,所以我找到了另一种解决方案,其目标是留在AngularJS,并认为我会提供完整性。

基于以下帖子: AngularJS ng-keydown directive only working for <input> context?

我从javascript中删除了以下行:

document.addEventListener("keydown", $scope.ProcessKey);

我使用ng-keydown对html进行了以下调整,之前我只能使用输入标记。我添加了tabindex,它允许项目处于焦点并解决输入标签问题:

<div ng-controller="myCtrl" ng-app="myApp" tabindex="0" ng-keydown="ProcessKey($event);">
    <md-button class="md-raised" ng-click="Toggle()">Toggle</md-button><br>
    <img id="testImg" ng-cloak ng-src="{{imgUrl}}">
</div>

请注意,我无法让它在body标签上工作。