【问题标题】:AngularJS - Pass parameters into Controller?AngularJS - 将参数传递给控制器​​?
【发布时间】:2015-09-13 16:31:52
【问题描述】:

我正在尝试使用 AngularJS 创建一个简单的博客网站。我刚刚开始,所以我认为我不是最好的方法,所以欢迎任何替代建议。

我有一个带有两个博客控制器的 controller.js 文件。一个显示博客文章列表,另一个通过包含 HTML 文件显示文章内容。

controller.js

myAppControllers.controller('BlogListCtrl', ['$scope', '$http', function ($scope, $http) {
    $http.get('articles/articles.json').success(function (articles) {
        $scope.articles = articles;
    });
}]);

myAppControllers.controller('BlogPostCtrl', ['$scope', '$routeParams', function ($scope, $routeParams) {
    $scope.includeFile = 'articles/' + $routeParams.blogPostId + '.html';
}]);

articles.json

[
{
    "id": "test-article-one",
    "title": "Test Article one",
    "author": "Gareth Lewis",
    "datePosted": "2015-06-23",
    "summary": "This is a test summary"
},
{
    "id": "test-article-two",
    "title": "Test article two",
    "author": "Gareth Lewis",
    "datePosted": "2015-06-23",
    "summary": "This is a test for article two"
}
]

app.js

when('/blog', {
            templateUrl: 'partials/blog-articles.html',
            controller: 'BlogListCtrl'
        }).
        when('/blog/:blogPostId', {
            templateUrl: 'partials/blog-post.html',
            controller: 'BlogPostCtrl'
        }).

blog-post.html

<ng-include src="'partials/header.html'"></ng-include>

<!-- Want to add title, author, datePosted information here... -->

<article class="content">
    <ng-include src="includeFile"></ng-include>
</article>

此博客列表工作正常。当我点击一篇博文时,它也会提供 HTML 文件中的内容。但是,我希望能够重用 blog-post.html 部分视图中所选文章的 titleauthordatePosted 属性。最好的方法是什么?我是否需要以某种方式将它们传递给控制器​​然后传递给视图?我真的不想将这些作为 routeParams 传递。或者我是否需要在articles.json 上执行$http.get 并遍历以找到所选文章,然后将属性值传递回视图?

感谢您的帮助。

【问题讨论】:

标签: javascript json angularjs model-view-controller


【解决方案1】:

你说欢迎提出建议,所以就这样吧。

1 - 将所有博客逻辑传输到服务;

2 - 提供解决路线的数据。这是在加载时间、404 秒等期间处理错误的更好方法。您可以为$routeChangeError 提供一个监听器并在那里处理它;

3 - 在下面声明的服务中,您有调用数据的方法和检索服务上缓存的列表的方法:

// services.js
myAppServices
    .service('BlogService', ['$http', '$q', function ($http, $q) {
        var api = {},
            currentData = {
                list: [],
                article: {}
            };

        api.getSaved = function () {
            return currentData;
        };

        api.listArticles = function () {
            var deferred = $q.defer(),
                backup = angular.copy(currentData.list);

            $http.get('articles/articles.json')
                .then(function (response) {
                    currentData.list = response;

                    deferred.resolve(response);
                }, function () {
                    currentData.list = backup;

                    deferred.reject(reason);
                });

            return deferred.promise;
        };

        api.getArticle = function (id) {
            var deferred = $q.defer(),
                backup = angular.copy(currentData.article),
                path = 'articles/' + id + '.html';

            $http.get(path, {
                cache: true
            })
                .then(function (response) {
                    currentData.article = {
                        path: path,
                        response: response
                    };

                    deferred.resolve(currentData.article);
                }, function (reason) {
                    currentData.article = backup;

                    deferred.reject(currentData.article);
                });

            return deferred.promise;
        };

        return api;
    }]);

BlogService.getSaved() 将在每次调用后检索存储的数据。

我也做了一个调用ng-include路径的方法,所以你可以验证它是否存在,使用cache === true,当在视图上再次调用它时,浏览器会保留它的副本。还制作了博客文章响应的副本,因此您可以在需要时访问其路径和响应。

在下面的控制器上,它们已经适应了当前的需求:

// controller.js
myAppControllers
    .controller('BlogListCtrl', ['$scope', 'articles',
        function ($scope, articles) {
            $scope.articles = articles;

            /* OTHER STUFF HERE */
        }
    ])
    .controller('BlogPostCtrl', ['$routeParams', '$scope', 'article' 'BlogService',
        function ($routeParams, $scope, article, BlogService) {
            // On `article` dependency, you have both the original response
            // and the path formed. If you want to use any of it.

            $scope.includeFile = article.path;

            // To get the current stored data (if any):
            $scope.articles = BlogService.getSaved().list;

            // Traverse the array to get your current article:
            $scope.article = $scope.articles.filter(function (item) {
                return item.id === $routeParams.id;
            });

            /* OTHER STUFF HERE */
        }
    ]);

并且在解析路由时更改了路由声明以加载数据。

// app.js
$routeProvider
    .when('/blog', {
        templateUrl: 'partials/blog-articles.html',
        controller: 'BlogListCtrl',
        resolve: {
            articles: ['BlogService', '$routeParams', function (BlogService, $routeParams) {
                return BlogService.listArticles();
            }]
        }
    })
    .when('/blog/:id', {
        templateUrl: 'partials/blog-post.html',
        controller: 'BlogPostCtrl',
        resolve: {
            article: ['BlogService', '$routeParams', function (BlogService, $routeParams) {
                return BlogService.getArticle($routeParams.blogPostId);
            }]
        }
    })

【讨论】:

  • 感谢您提供如此全面的答案!今晚我会有一些有趣的编码?
【解决方案2】:

这可能是 Angular 中的一个常见问题。您必须了解的是,Scope 是按控制器定义的...为了在控制器之间共享数据,您仍然可以选择使用 $scope.$parent$rootScope 来链接控制器,但我会使用那些小心点。

最好使用基于单例模式的 Angular 服务,因此您可以使用它们在控制器之间共享信息,我认为这将是一种更好的方法。

我发现这个问题之前已经讨论过了,这里有一些很好的例子:

AngularJS Service Passing Data Between Controllers

【讨论】:

  • 谢谢。我会检查那个链接。
【解决方案3】:

您可以使用全局范围来设置此数据,也可以使用服务在控制器之间进行通信。有很多方法可以解决这个问题,在下面的链接中阅读更多关于服务的信息,看看你是否能找到解决问题的方法。

AngularJS: Service vs provider vs factory

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多