我们正在尝试切换到角度,但我们在路由方面存在很大的问题。我们当前的网站有10,000条独特的路线 - 永远的页面有一个独特的“.html”标识符。没有特定的约定允许我们将控制器分配给它们,所以我创建了一个查找API端点。
以下是我正在尝试创建的工作流程:
角度应用加载。设置了一条“其他”路线。
当有人点击链接时,我不知道该资源是产品还是类别,因此使用唯一的“.html”标识符对查找端点进行查询。端点返回两件事:资源名称和ID(例如“product”和“10”)。所以要清楚,他们点击了一个页面,“http://www.example.com/some-identifier.html,”我查询查找API以找出这是什么类型的资源,并得到像“产品”和“10”的结果 - 现在我知道它是产品控制器/模板,我需要产品ID 10的数据。
应用程序分配控制器和模板(“productController”和“product.html”),查询正确的数据端点(“/ api / product / 10”),并呈现模板。
我遇到的问题:
$ http在配置期间不可用,因此我无法点击查找表。
在配置完成之后添加路由最好 - 我已经成功地通过将$ routeProvider分配给一个全局变量并在事后做了它,但是伙计,这很难看。
加载所有路由似乎不切实际 - 对于很多连接/浏览器来说,文件的大小就相当大了。
我们现在无法改变惯例。我们有4年的搜索引擎优化和大量的自然流量来放弃我们的网址。
我觉得我可能会以错误的方式思考这个问题并且缺少某些东西。查找表确实是问题 - 不知道要加载什么类型的资源(产品,类别等)。我阅读this article关于动态加载路由,但同样,他没有进行外部查询。对我们来说,加载控制器不是问题,它正在解析路由,然后分配它们c
你会如何解决这个问题?
API结构
此配置至少需要两个端点:/api/routes/lookup/:resource_to_lookup:/
和/api/some_resource_type/id/:some_resource_id:/
。我们查询查找以找出它指向的资源类型以及资源的ID。这使您可以拥有漂亮干净的网址,例如“http://www.example.com/thriller.html”(单个)和“http://www.example.com/michaeljackson.html”(集合)。
在我的情况下,如果我查询类似“awesome_sweatshirt.html”的内容,我的查找将返回一个带有“{type:'product',id:10}”的JSON对象。然后我查询“/ api / product / id / 10”来获取数据。
“那不是很慢吗?”你问。前面有清漆,所有这些都发生在不到1秒的时间。我们在本地看到的页面加载时间少于20毫秒。来自慢速开发服务器的电线接近半秒钟。
app.js
var app = angular.module('myApp', [
'ngRoute'
])
.config(function($routeProvider, $locationProvider) {
$routeProvider
.otherwise({
controller: function($scope, $routeParams, $controller, lookupService) {
/* this creates a child controller which, if served as it is, should accomplish your goal behaving as the actual controller (params.dashboardName + "Controller") */
if ( typeof lookupService.controller == "undefined" )
return;
$controller(lookupService.controller, {$scope:$scope});
delete lookupService.controller;
//We have to delete it so that it doesn't try to load again before the next lookup is complete.
},
template: '<div ng-include="templateUrl"></div>'
});
$locationProvider.html5Mode(true);
})
.controller('appController', ['$scope', '$window', '$rootScope', 'lookupService', '$location', '$route', function($scope, $window, $rootScope, lookupService, $location, $route){
$rootScope.$on('$locationChangeStart', handleUniqueIdentifiers);
function handleUniqueIdentifiers (event, currentUrl, previousUrl) {
window.scrollTo(0,0)
// Only intercept those URLs which are "unique identifiers".
if (!isUniqueIdentifierUrl($location.path())) {
return;
}
// Show the page load spinner
$scope.isLoaded = false
lookupService.query($location.path())
.then(function (lookupDefinition) {
$route.reload();
})
.catch(function () {
// Handle the look up error.
});
}
function isUniqueIdentifierUrl (url) {
// Is this a unique identifier URL?
// Right now any url with a '.html' is considered one, substitute this
// with your actual business logic.
return url.indexOf('.html') > -1;
}
}]);
lookupService.js
myApp.factory('lookupService', ['$http', '$q', '$location', function lookupService($http, $q, $location) {
return {
id: null,
originalPath: '',
contoller: '',
templateUrl: '',
query: function (url) {
var deferred = $q.defer();
var self = this;
$http.get("/api/routes/lookup"+url)
.success(function(data, status, headers, config){
self.id = data.id;
self.originalPath = url;
self.controller = data.controller+'Controller';
self.templateUrl = '/js/angular/components/'+data.controller+'/'+data.controller+'.html';
//Our naming convention works as "components/product/product.html" for templates
deferred.resolve(data);
})
return deferred.promise;
}
}
}]);
productController.js
myApp.controller('productController', ['$scope', 'productService', 'cartService', '$location', 'lookupService', function ($scope, productService, cartService, $location, lookupService) {
$scope.cart = cartService
// ** This is important! ** //
$scope.templateUrl = lookupService.templateUrl
productService.getProduct(lookupService.id).then(function(data){
$scope.data = data
$scope.data.selectedItem = {}
$scope.$emit('viewLoaded')
});
$scope.addToCart = function(item) {
$scope.cart.addProduct(angular.copy(item))
$scope.$emit('toggleCart')
}
}]);
答案 0 :(得分:2)
尝试这样的事情。
在路由配置中,您可以为每种资源类型及其控制器,模板和解析设置定义:
$routeProvider.when('/products', {
controller: 'productController',
templateUrl: 'product.html',
resolve: {
product: function ($route, productService) {
var productId = $route.current.params.id;
// productService makes a request to //api/product/<productId>
return productService.getProduct(productId);
}
}
});
// $routeProvider.when(...
// add route definitions for your other resource types
然后你会听$locationChangeStart
。如果导航到的URL是“唯一标识符”,则查询查找。根据查找返回的资源类型,导航到上面定义的正确路由。
$rootScope.$on('$locationChangeStart', handleUniqueIdentifiers);
function handleUniqueIdentifiers (event, currentUrl, previousUrl) {
// Only intercept those URLs which are "unique identifiers".
if (!isUniqueIdentifierUrl(currentUrl)) {
return;
}
// Stop the default navigation.
// Now you are in control of where to navigate to.
event.preventDefault();
lookupService.query(currentUrl)
.then(function (lookupDefinition) {
switch (lookupDefinition.type) {
case 'product':
$location.url('/products');
break;
case 'category':
$location.url('/categories');
break;
// case ...
// add other resource types
}
$location.search({
// Set the resource's ID in the query string, so
// it can be retrieved by the route resolver.
id: lookupDefinition.id
});
})
.catch(function () {
// Handle the look up error.
});
}
function isUniqueIdentifierUrl (url) {
// Is this a unique identifier URL?
// Right now any url with a '.html' is considered one, substitute this
// with your actual business logic.
return url.indexOf('.html') > -1;
}
答案 1 :(得分:0)
答案 2 :(得分:0)
如果你有一个带有路由信息的json文件(如果没有安全问题)并迭代它以将路由附加到应用程序怎么办?
e.g。
JSON:
routes: [
{
controller: "Controller1"
path: "/path1"
templateUrl: 'partials/home/home.html'
},
{
controller: "Controller1"
path: "/path1"
templateUrl: 'partials/home/home.html'
}
]
然后迭代JSON的内容并将它们附加到$routeProvider.when
?
我不确定这是不是一个好主意,取决于JSON文件的大小,以及你是否不希望将所有路由暴露给可能的攻击者。
答案 3 :(得分:0)
来自the AngularJS documentation,
$ routeParams服务允许您检索当前的一组 路线参数。
依赖关系:
$route
示例看起来像
// Given:
// URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
// Route: /Chapter/:chapterId/Section/:sectionId
// Then
$routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
ngRouteModule.provider('$routeParams', $RouteParamsProvider);
function $RouteParamsProvider() {
this.$get = function() { return {}; };
}