AngularJS - 单独的控制器和 DOM 操作

Posted

技术标签:

【中文标题】AngularJS - 单独的控制器和 DOM 操作【英文标题】:AngularJS - Separate controller and DOM manipulation 【发布时间】:2016-09-01 11:24:48 【问题描述】:

我正在阅读角度文档:

https://docs.angularjs.org/guide/controller

它有一点说:

不要使用控制器来:

操纵 DOM — 控制器应该只包含业务逻辑。 将任何表示逻辑放入控制器会显着影响 它的可测试性。 Angular 对大多数情况和指令都有数据绑定 封装手动 DOM 操作。

所以我有以下运行良好的代码。

$scope.processForm = function() 
    // Get and reset the captcha, then check it was valid.
    response = grecaptcha.getResponse();
    $scope.recaptchaValid = false;
    grecaptcha.reset();

    if (response.length == 0) 
        alert("Not sure how you got here, but you shouldn't have. Go away!");
        return;
    

    // Update the user we are attempting to send the message.
    $(".contact-message").text("Sending message...").removeClass("hidden alert-danger").addClass("alert-success");
    $(".contact-container").addClass("hidden");

    // Add the recaptcha data to the form so we can send it to the server easier
    $scope.formData.captcha = response;

    $http(
        method : 'POST',
        url : '/api/sendEmail.php',
        data : $.param($scope.formData), // pass in data as strings
        headers : 
            // set the headers so angular passing info as form data (not request payload)
            'Content-Type' : 'application/x-www-form-urlencoded'
        
    ).success(function(data) 
        if (!data.success) 
            // If the server said there was an error, re-enable the form and display the error
            console.error(data);
            $(".contact-container").removeClass("hidden");
            $(".contact-message").text(data.message).removeClass("hidden alert-success").addClass("alert-danger");
         else 
            // If the server said all was good, display the message from the server
            $(".contact-message").text(data.message).removeClass("hidden alert-danger").addClass("alert-success");
        
    );
;

从像纯粹主义者这样的解释性禅宗看来,我看到后端 API 调用的处理可能应该在某处的服务中关闭(尽管不确定如何执行此操作),但我不确定我是如何做到的与 $scope 中的数据“正确”交互,在那里可以进行 DOM 操作吗?我在很大程度上减少了 DOM 操作来管理类,但发送设置更新,我认为应该是它自己的一个 div,它驱动了一些范围数据并使用 ng-hide。如果您选择语言,我认为这可能真的很有用,但在维护时会使 html 页面变得很大且很麻烦。

任何帮助表示赞赏。

编辑

根据我要去的地方和@C14L 的说明,我将 Angular 代码的代码更新为:

$scope.processForm = function() 
    // Get and reset the captcha, then check it was valid.
    response = grecaptcha.getResponse();
    $scope.recaptchaValid = false;
    grecaptcha.reset();

    if (response.length == 0) 
        alert("Not sure how you got here, but you shouldn't have. Go away!");
        return;
    

    // Update the user we are attempting to send the message.
    $scope.sendingMessage = true;

    // Add the recaptcha data to the form so we can send it to the server easier
    $scope.formData.captcha = response;

    $http(
        method : 'POST',
        url : '/api/sendEmail.php',
        data : $.param($scope.formData), // pass in data as strings
        headers : 
            // set the headers so angular passing info as form data (not request payload)
            'Content-Type' : 'application/x-www-form-urlencoded'
        
    ).success(function(data) 
        $scope.serverMessage = data.message;
        $scope.sendingStatus = data.success;
        $scope.sendingMessage = false; // no longer sending
    );
;

我不得不承认这确实工作得更好。不过 HTML 有点笨拙:

    <div class='sending-indicator alert alert-info' data-ng-hide="!sendingMessage">
        <p>Sending message...</p>
    </div>
    <div class="alert contact-message" 
            data-ng-class="sendingStatus?'alert-success':'alert-danger'" 
            data-ng-hide="serverMessage.length == 0">serverMessage</div>
    <div  class="contact-container" 
            data-ng-hide="sendingMessage || (sendingStatus && serverMessage.length > 0)">

...

【问题讨论】:

DOM 操作应该在指令内完成。还要避免调用 JQuery,因为您可以使用几乎所有的角度函数(Angular 使用 JQuery 的精简版,JQlite)。 指令,使用它们。您可以在视图中使用 ng-class 指令,而不是调用 addClass 是的,我可以看到发送的过程,但过程管理和服务器反馈呢?拥有服务器和查看器共享的错误消息列表似乎是一个非常古老的概念,但传输却一无所知。如果我在服务器上发明了新的检查或错误,我需要更新至少 2 个地方......这似乎是糟糕的 java 和 C# 的“未处理异常”诅咒 【参考方案1】:

以这几行为例

// Update the user we are attempting to send the message.
$(".contact-message").text("Sending message...").removeClass("hidden alert-danger").addClass("alert-success");
$(".contact-container").addClass("hidden");

你可以这样写。在模板中

<div class="contact-message" ng-if="sendingMessage">Sending message</div>
<div class="contact-container" ng-if="!sendingMessage">Not sending</div>

在控制器中

$scope.sendingMessage = true;  // now it shows "sending"
$scope.sendingMessage = false;  // now "not sending"

【讨论】:

这就是我认为我要去的地方,但我认为我更关心 $http 并管理各种步骤和错误。那是一个基于过程的东西......我想我还是老派......我应该在那里使用 $scope 变量吗? 没错。在您的 $http 解析中,将 data.message 分配给 $scope 上的变量,例如$scope.dataMessage = data.message;,然后用 dataMessage 显示在模板中。

以上是关于AngularJS - 单独的控制器和 DOM 操作的主要内容,如果未能解决你的问题,请参考以下文章

如果 DOM 元素被“删除”,AngularJS 控制器会被破坏?

AngularJS初步

Angularjs:如何更新使用我无法控制的外部代码所做的 DOM 更改?

AngularJS

Angular JS 在 textarea 中显示最后几行

AngularJS入门学习笔记一