我被带到修复一个几个月前着火的网站。我已经控制了大部分事情,而且我还要修复各种愿望清单项目。其中一个涉及一些角度代码,我似乎无法做我想做的事情。在某些页面上有视频,然后是简短的测验。我需要在每次活动后更新用户的分数。到目前为止,事实证明这对于总得分来说已经足够容易了:
<a id="updateafterscore" href="~/user/leaderboard/" class="fill-div">
{{ profile.currentScore }}
</a>
这更新了:
document.getElementById('updateafterscore').innerHTML = data.Data.CurrentScore;
到目前为止,这么好。然而,到目前为止,页面上的其他元素无法更新。这是页面上的内容:
我添加了&#34; id =&#34; refreshvideo&#34;我自己也可以尝试改变标签。最后,这里是简单圆的角度模块(我已经省略了实际的绘图代码,因为它并不真正相关):
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 元素,我可以看到值和数据值标签更改为我设置的内容,但图像保持不变。我说错了吗? (或许 $ watch 正在观看)我是否必须强制重新绘制 canvas 元素?
答案 0 :(得分:2)
@charlietfl意味着你的解决方案实际上并没有使用AngularJS - 你完全绕过了它。 Angular提供Javascript数据和HTML DOM之间的双向数据绑定。您所做的就是告诉它在哪里绘制数据,它会自动为您完成,随着数据的变化使其保持最新状态。
在Angular中,你永远不会调用getElementById,并且肯定从不设置innerHTML,因为那时你阻止Angular做它的事情 - 在很多情况下你真的会破坏它。这些实例中的每一个都在“修补”另一个实例时引入了新的错误。
返回示例模板行:
<a ..attributes...>{{ profile.currentScore }}</a>
当它看到这一点时,Angular将在profile.currentScore上创建它所谓的“观察者”。如果它现在的值为'1',则会将其呈现为<a ...>1</a>
。
每个摘要周期,观察者都会告诉它查看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();
如果你需要这样做,你马上就会知道。如果它有效,你需要这样做。 :)如果你在控制台中收到一条错误消息,说你已经处于摘要周期,你不需要这样做(这是其他的)。
答案 1 :(得分:0)
我提到过,我想也许我正在修改错误的 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 信息。无论如何,我添加了最后4行代替:
document.getElementById('updateafterscore').innerHTML = data.Data.CurrentScore;
......所有人都按计划工作。当我弄清楚数据是如何进入控制器的时候,我想我后来处理了另一部分。
答案 2 :(得分:0)
你不能这样做。它不是处理数据的Angular方式。 在https://docs.angularjs.org/tutorial/step_04之前阅读文档 如果您需要使用文档修改DOM ..可能是您的代码错误。
顺便说一句。停止使用全局变量,如:
document.getElementById('updateafterscore')