【问题标题】:What's the AngularJS "way" of handling a CRUD resourceAngularJS 处理 CRUD 资源的“方式”是什么
【发布时间】:2013-08-01 19:41:21
【问题描述】:

我有兴趣将我客户的很多“逻辑”从 Rails 路由转移到 AngularJS。我对一个主题有点困惑,那就是链接。现在,我确实知道处理这个问题的方法不止一种,但是 AngularJS 社区在处理资源的 CRUD 时处理 URL 的常见做法是什么。想象一下,对于一名运动员,我们有一个如下所示的 URL 来列出所有运动员:

http://example.com/athletes

查看单个运动员:

http://example.com/athletes/1

编辑单个运动员:

http://example.com/athletes/1/edit

创建一个新的运动员:

http://example.com/athletes/new

在 AngularJS 中,重新路由到类似的 URL 以创建/编辑/更新是常见的做法吗?您是否只需要一个 URL 在一个界面中处理所有 CRUD 类型的操作而从不更改 URL?如果您要更改 URL,是否会通过 ng-click 进行处理,并且在 click 事件中您会使用 $location 对象来更改 URL 吗?我希望能够阅读诸如此类的常见做法,但很难在 AngularJS 上下文中找到有关它的最新文献。

** 注意 **

我完全明白,您仍然可以使用 RESTful 路由到后端,以便与服务器端资源进行交互。我的问题是,在客户端更新 URL 时推荐使用什么样式。您是否使用 AngularJS 为每个 CRUD 操作执行此操作?

【问题讨论】:

  • angular 有支持 CRUD 操作的 $resource (docs.angularjs.org/api/ngResource.$resource)。
  • 您能否澄清一下您是指前端还是 API?也就是AngularJS的$routeProvider URL或者你传递给$http/$resource的URL?
  • 我在这里真正想问的是,Angular 开发人员是否倾向于使用 $routeProvider 之类的工具来确保浏览器中的 URL(可能用于书签或链接目的)更新为与他们相同的 URL '通过 XHR 调用以与资源交互。

标签: javascript ruby-on-rails angularjs ruby-on-rails-4


【解决方案1】:

我肯定会为每个操作推荐单独的 URL(以启用直接链接)。你建议的看起来不错。

在 AngularJS 中,您可以结合使用 $route 服务和 ngView 指令来为每个操作加载适当的模板,并为您处理浏览器位置和历史机制。

Step 7 of the AngularJS tutorial 给出了一个使用视图、路由和模板的例子,我在这里描述的方式。以下是您的示例的简化版本:

定义路线

在您的主应用程序脚本中(例如 app.js):

angular.module('AthletesApp', []).
  config(['$routeProvider', function($routeProvider, $locationProvider) {
  // Configure routes
  $routeProvider.
      when('/athletes', {templateUrl: 'partials/athletes-list.html',   controller: AthleteListCtrl}).
      when('/athletes/:athleteId', {templateUrl: 'partials/athlete-detail.html', controller: AthleteDetailCtrl}).
      when('/athletes/:athleteId/edit', {templateUrl: 'partials/athlete-edit.html', controller: AthleteEditCtrl}).
      when('/athletes/:athleteId/new', {templateUrl: 'partials/athlete-new.html', controller: AthleteNewCtrl}).
      otherwise({redirectTo: '/athletes'});
  // Enable 'HTML5 History API' mode for URLs.
  // Note this requires URL Rewriting on the server-side. Leave this
  // out to just use hash URLs `/#/athletes/1/edit`
  $locationProvider.html5Mode(true);
}]);

我们还为 URL 启用“HTML 模式”,请参阅下面的注释。

2。在您的 HTML 中添加 ngView 指令

在您的主 index.html 中,您指定所选部分模板在整体布局中的位置:

<!doctype html>
<html ng-app="AthletesApp">
...
   <!-- Somewhere within the <body> tag: -->
   <div ng-view></div>
...
</html>

3。创建模板和控制器

然后为每个操作创建局部视图模板和匹配的控制器。例如。对于运动员详细信息视图:

partials/athelete-detail.html:

<div>
    ... Athete detail view here
</div>

athleteDetailCtrl.js:

angular.module('AthletesApp').controller('AtheleteDetailCtrl',
    function($scope, $routeParams) {
        $scope.athleteId = $routeParams.athleteId;
        // Load the athlete (e.g. using $resource) and add it
        // to the scope.
    }

您可以通过$routeParams 服务访问路由参数(在路由配置中使用:athleteId 定义)。

4。添加链接

最后一步是在您的 HTML 中实际添加链接和按钮以访问不同的视图。只需使用标准 HTML 并指定 URL,例如:

<a href="/athletes/{{athleteId}}/edit">Edit</a>

注意:标准 URL 与哈希 URL

在不支持 HTML5 History API 的旧版浏览器中,您的 URL 看起来更像 http://example.com/#/athleteshttp://example.com/#/athletes/1

$location 服务(由 $route 自动使用)可以为您处理这个问题,因此您可以在现代浏览器中获得干净的 URL,并在旧浏览器中回退到哈希 URL。您仍然如上所述指定您的链接,$location 将为旧客户处理重写它们。唯一的附加要求是您在服务器端配置 URL 重写,以便将所有 URL 重写到应用程序的主 index.html。有关详细信息,请参阅AngularJS $location Guide

【讨论】:

  • 快速提问。通常使用 New 和 Edit 模板和控制器会有很多重叠。有没有办法重用模板和/或控制器?因此,如果您添加了一个新字段,您就不必在两个地方进行更新了吗?
  • @uriDium 您只需将templateUrl 指向同一文件的editnew 路由,就可以重用整个模板。更常见的是,您可能需要视图之间的一些差异,在这种情况下,您可以将公共部分提取到单独的模板中,并使用 ngInclude 指令将它们包含在 new.htmlend.html 模板中。对于控制器,我将通用功能提取到 service 中,该服务可以注入到两个控制器中。
  • 这非常有帮助。谢谢德里克。
  • 不清楚的是用于新路线的运动员 id,当您创建新实体时,除非您通过代码生成 id,否则您仍然没有 id,并且是不建议在 javascript 上这样做,也许更好的方法是 /athletes/new 而不是 /athletes/:id/new
  • 如果我不想使用 Angular 路由而是使用简单的服务器端路由来处理请求怎么办?
【解决方案2】:

有角度的方式是宁静的方式:

GET all http://example.com/athletes
GET one http://example.com/athletes/1
POST new http://example.com/athletes
PUT edit http://example.com/athletes/1
DELETE remove http://example.com/athletes/1

请注意,$resource 还需要其他一些内容,例如资源 URL 不以斜杠结尾、PUT 请求返回更新的资源等。

如果您的 API 不符合这些标准,或者您只是需要更大的灵活性,您可以基于较低级别的 $http 服务构建自己的 $resource-like CRUD 服务。解释了后者的一种方法here

【讨论】:

  • 我使用了$resource 工厂来调用ServiceStack API。只是为了让您知道它是一个单独的模块,需要加载到您自己的应用程序模块中。 (它没有出现在默认的 angularjs 文件中
  • 我想补充一点——这与 REST 的关系并不像正确使用 HTTP 协议并使用正确的动词进行适当的操作一样多。
  • 在调用服务器端 API 之前,您使用什么来显式路由到这些 URL? $resource 主要用于服务器端通信。您是否首先明确使用 $routeProvider 更改为这些 URL?
  • 那么如果用户在 URL 中输入example.com/athletes/1,你是显示 GET 模板(用于显示)还是 PUT 模板(用于编辑)?您如何仅从 URL 中区分这两者?
  • @Prabhu 在浏览器中加载页面时,默认操作是 GET。要发送 PUT 请求,您需要使用某种 HTTP 客户端。
【解决方案3】:

选项 1:$http 服务

AngularJS 提供的 $http service 完全符合您的要求:使用 JSON(非常适合与 REST 服务对话)向 Web 服务发送 AJAX 请求并从它们接收数据。

举个例子(取自 AngularJS 文档并稍作修改):

$http({ method: 'GET', url: '/foo' }).
  success(function (data, status, headers, config) {
    // ...
  }).
  error(function (data, status, headers, config) {
    // ...
  });

选项 2:$resource 服务

请注意,AngularJS 中还有另一个服务,$resource service,它以更高级的方式提供对 REST 服务的访问(示例再次取自 AngularJS 文档):

var Users = $resource('/user/:userId', { userId: '@id' });
var user = Users.get({ userId: 123 }, function () {
  user.abc = true;
  user.$save();
});

选项 3:Restangular

此外,还有第三方解决方案,如Restangular。请参阅其documentation 了解如何使用它。基本上,它更具声明性,并从您那里抽象出更多细节。

【讨论】:

    【解决方案4】:

    在 AngularJS 中你绝对可以使用 RESTful 服务器端数据源,有一个名为 $resource 的内置服务。

    或者,您也可以使用restangular,它具有超过 $resource 的附加功能。

    如果您想完全控制,您可以随时使用$http 服务,它是用于与 http 交互的低级角组件。

    【讨论】:

      【解决方案5】:

      只需实现 RESTful 的东西,即 angularJS 方式。如果您不知道 RESTful 是什么,或者知道一点并想了解更多,那么我建议您阅读 this 文章。

      基本上,REST 被理解为 WEB URI 的直观实现,它还利用了所有 HTTP 动词,实际上它们的正确使用。 REST 是一种构建 Web 应用程序的方法和架构。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-03
        • 2014-03-04
        • 1970-01-01
        • 2020-06-26
        • 1970-01-01
        相关资源
        最近更新 更多