【问题标题】:How to refresh an angular tag如何刷新角度标签
【发布时间】:2014-11-06 20:17:22
【问题描述】:

我被请来修复几个月前起火的网站。我已经控制了大部分事情,我正在修复各种愿望清单项目。其中一个涉及一些我似乎无法做我想做的事情的角度代码。在某些页面上有视频,然后是一个简短的测验。我需要在每次活动后更新用户的分数。到目前为止,事实证明这很容易得到如下所示的总分:

 <a id="updateafterscore" href="~/user/leaderboard/" class="fill-div">
                                {{ profile.currentScore }}
                            </a>

然后更新了这个:

document.getElementById('updateafterscore').innerHTML = data.Data.CurrentScore;

到目前为止,一切都很好。然而,到目前为止,页面上的其他元素已被证明无法更新。这是页面上的内容:

我自己添加了“id="refreshvideo",因此我可以尝试更改标签。最后,这是 simple-circle 的 angular 模块(我省略了实际的绘图代码,因为它并不真正相关):

angular.module('thrive.shared').directive('simpleCircle', function() {

return{
    replace: true,
    template: '<canvas width="60" height="60" style="margin: -10px 0 0 -15px;"></canvas>',
    restrict: 'E',
    scope: {
        value: '@',
        color: '@',
        bgColor: '@',
        forecolor: '@',
        radius: '@'
    },
    link: function (scope, elem, attrs) {

        var multiplyLength = 1;
        var canvasElem = elem[0];
        var inMotion = false;

        if (scope.value <= 2) {
            multiplyLength = 5;
        }

        scope.$watch('value', function() {
            drawCircle(canvasElem, scope.color, scope.value * multiplyLength, scope.value, scope.name);
        });


        function drawCircle(canvas, color, calculatedPoints, displayPoints, name) {

那么,问题是:我到底要如何更新显示的数字?我尝试了各种方法:

document.getElementById('refreshvideo').setAttribute('value', data.Data.VideoWatchedCount);
document.getElementById('refreshvideo').setAttribute('data-value', data.Data.VideoWatchedCount);
$scope.profile.videosWatched = data.Data.VideoWatchedCount;

这些都不起作用。我在浏览器的源代码中检查了 canvas 元素,我可以看到 valuedata-value 标签更改为我设置的任何内容,但图像保持不变。我设置错了吗? (也许 $watch 正在观看)我是否必须强制对 canvas 元素进行某种重新绘制?

【问题讨论】:

  • 方法全错了。 Angular 将根据控制器和指令中范围模型变量的值更新实时 html
  • "approach is all wrong" 定义了这个项目。我没有创建它。尽管如此,我仍然需要对上面描述的内容做一些事情。从哪里开始快速解决此问题的线索会有所帮助。

标签: javascript jquery html angularjs canvas


【解决方案1】:

@charlietfl 表示您的解决方案实际上并未使用 AngularJS - 您完全绕过了它。 Angular 在 Javascript 数据和 HTML DOM 之间提供了双向数据绑定。您所要做的就是告诉它在哪里绘制数据,它会自动为您执行此操作,并从那时起随着数据的变化保持最新状态。

在 Angular 中,你永远不会调用 getElementById 并且肯定永远不会设置 innerHTML,因为那样你会阻止 Angular 做它的事情——在很多情况下你实际上会破坏它。这些实例中的每一个都会在“修补”另一个实例时引入一个新错误。

回到您的示例模板行:

<a ..attributes...>{{ profile.currentScore }}</a>

当它看到这一点时,Angular 将在 profile.currentScore 上创建它所谓的“观察者”。如果它现在的值为 '1',它会将其呈现为 &lt;a ...&gt;1&lt;/a&gt;

每个摘要周期,该观察者都会告诉它查看 profile.currentScore 以查看它是否发生了变化。这行代码在 JS 中非常典型:

profile.currentScore = 42;

Angular 将通过观察者“看到”这种情况,并自动更新渲染的模板。你什么都不做 - 如果你觉得你需要这样做,那几乎总是意味着 else 出了点问题。

如果您经常遇到这种情况,请尝试“标准快速修复”。我们经常看到那些没有正确构建应用程序的人,他们在 Angular 无法“看到”它们的摘要周期之外进行数据模型更新。尝试将更新代码包装在 $apply() 调用中:

$scope.$apply(function() {
    profile.currentScore = 42;
});

如果您要进行大量更新并且不想嵌套调用,您也可以作弊,如下所示:

// Lots of stuff...
profile.currentScore = 42;
// Lots more stuff...

$scope.$apply();

您会立即知道是否需要这样做。如果它有效,你需要这样做。 :) 如果您在控制台中收到一条错误消息,说明您已经处于摘要循环中,则无需执行此操作(这是另外一回事)。

【讨论】:

  • 顺便说一句,我回答了“数据未更新”的问题,因为这似乎是您的主要问题。但是,如果您的 CIRCLE 没有更新,那可能是另一回事。请注意,Angular 指令“链接”函数只执行一次。做对了,$watch 可以被重新触发...但是 multiplyLength 永远不会从 2 变回 1,例如,即使 $scope.value 变为 5... 你也可能对 '=' 范围绑定更满意而不是'@'...
  • sigh 我想问题是应该发生的是我首先尝试的。代码中有一个 $scope.profile 值,在调试它时,我看到其中包含现有且正确的数据。但是我更改了 $scope.profile.currentScore 并且页面上没有任何反应。我越来越清楚,我正在修改的“配置文件”不是 {{ 配置文件中使用的那个。? }} 在页面上。我目前不知道如何连接这些点。
  • 哦,谢谢您的回复。我主要是用角度来理解这些概念,你的 cmets 更有帮助,但我自己从来没有用它编码过任何东西。几个月前,一个程序员在这个项目上流氓,用角度版本替换了大量的界面......所有这些都没有受到管理层或其他程序员的任何监督。我现在只是涉水太多了。
  • 在你的更新下方扔一个 $scope.$apply() 看看会发生什么。
  • JavaScript 运行时错误:对象不支持属性或方法“应用”
【解决方案2】:

我提到我认为我可能修改了错误的 profile 变量,因此它没有令人耳目一新。所以我回顾了一下提供数字的代码:

angular.module('episodes').controller('episodeCtrl', ['$scope', '$rootScope', '$window', 'episode', 'relatedCourses', 'Video', 'episodeItems', 'profile', 'Profile',
function ($scope, $rootScope, $window, episode, relatedCourses, Video, episodeItems, profile, Profile) {
// stuff skipped....
                        onComplete: function () {
                            Video.complete({ videoId: item.item.id }).$promise.then(function () {
                                item.progress = "Completed";
                                $scope.loadNextItem();
                                $scope.profile = Profile.get();   // <<-- gotten from somewhere

                                $.ajaxSetup({ cache: false });
                                $.get('/user/getCurrentUserPointsModel', function (data) {
                                    if (data == "")
                                        return;
                                    $scope.profile.currentScore = data.Data.CurrentScore;
                                    $scope.profile.videosWatched = data.Data.VideoWatchedCount;
                                    $scope.profile.testTakenAndCorrectAnswerCount = data.Data.TestTakenAndCorrectAnswerCount;
                                    Profile.save();    // <-- added

$scope.profile 中的值是从 Profile 中提取的,但我不完全了解它是如何到达的。我想我需要弄清楚这一点,因为这些更新必须在另一个地方发生,但缺少 Profile 信息。无论如何,我添加了最后 4 行来代替:

document.getElementById('updateafterscore').innerHTML = data.Data.CurrentScore;

...一切都按计划进行。我想我稍后会在弄清楚数据如何到达控制器时处理另一部分。

【讨论】:

    【解决方案3】:

    你不能那样做。这不是 Angular 处理数据的方式。 阅读https://docs.angularjs.org/tutorial/step_04之前的文档 如果您需要使用文档修改您的 DOM.. 可能是您的代码有问题。

    顺便说一句。停止使用全局变量,例如:

    document.getElementById('updateafterscore')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-08
      • 2019-02-18
      • 2021-01-28
      • 2019-12-27
      • 1970-01-01
      • 2013-12-15
      • 2020-01-02
      相关资源
      最近更新 更多