Angular ui-具有 url 查询参数的路由器包含 "dot"
Angular ui-router with url query parameter containing a "dot"
在我们的 Angular 应用程序中,我们必须处理包含 "dot" 的 ID。例如:
book = {
id: '123.456'
}
我们在使用 id 作为 url 参数时遇到问题。如果通过 "Angular" 进行导航,则一切正常,即单击调用 $state.go('bookDetails', {bookId: book.id});
的 link。但是重新加载页面时事情不起作用
"Cannot GET /bookDetails?bookId=123.456"
在控制器中:
$scope.viewBookDetails = function() {
$state.go('bookDetails', {bookId: book.id});
}
在视图中
<a href="" ng-click="viewBookDetails(); $event.stopPropagation();">
在路由器中:
.state('bookDetails', {
url: '/bookDetails?bookId'
}
在浏览器中:
https://example.com/bookDetails?bookId=123.456
如果在浏览器中将 "dot" 替换为 %2E
,则 link 有效。
我们试图在 $state.go()
的参数中用“%2E”替换 "dot"
$scope.viewBookDetails = function() {
$state.go('bookDetails', {bookId: book.id.split('.').join('%2E')});
}
但不起作用,因为“%”是自动编码的,浏览器中的 "dot" 被替换为“%252E”
https://example.com/bookDetails?bookId=123%252E456
我完全修改了代码。我可以很好地使用点,所以请分叉 plunker 以显示您在哪里出错。
http://plnkr.co/edit/Ct09Q9uoc282JuWdsO1s?p=preview
console.log("Scripts loading... ");
// Here's a skeleton app. Fork this plunk, or create your own from scratch.
var app = angular.module('demonstrateissue', ['ui.router']);
app.controller('myController', function($scope, $state){
$scope.book = {
id: '123.456'
};
$scope.viewBookDetails = function() {
console.log('new id');
$state.go('bookDetails', {bookId: 456.3456});
}
});
// Empty config block. Define your example states here.
app.config(function($stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider) {
$stateProvider.state('bookDetails', {
url: '/bookDetails:bookId',
controller: function($scope, $stateParams) {
$scope.book = {
id: $stateParams.bookId
};
},
template: "<h3>book: {{book}}</h3>"
});
$urlRouterProvider.otherwise("/bookDetails/91.23");
});
// Adds state change hooks; logs to console.
app.run(function($rootScope, $state, $location) {
$rootScope.$state = $state;
$rootScope.$location = $location;
function message(to, toP, from, fromP) {
return from.name + angular.toJson(fromP) + " -> " + to.name + angular.toJson(toP);
}
$rootScope.$on("$stateChangeStart", function(evt, to, toP, from, fromP) { console.log("Start: " + message(to, toP, from, fromP)); });
$rootScope.$on("$stateChangeSuccess", function(evt, to, toP, from, fromP) { console.log("Success: " + message(to, toP, from, fromP)); });
$rootScope.$on("$stateChangeError", function(evt, to, toP, from, fromP, err) { console.log("Error: " + message(to, toP, from, fromP), err); });
});
body {
margin-top: 6em;
}
.link {
text-decoration: underline;
color: blue;
}
.link:hover {
cursor: pointer;
}
.header {
position: fixed;
right: 0;
top: 0;
height: 6em;
width: 100%;
border-bottom: 1px solid gray;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://code.angularjs.org/1.2.25/angular.js"></script>
<script src="https://rawgit.com/angular-ui/ui-router/0.2.13/release/angular-ui-router.js"></script>
<script src="main.js"></script>
<link rel="stylesheet" href="styles.css" />
<title>Plunk demonstrating ui-router issue</title>
</head>
<body ng-app="demonstrateissue">
<div ui-view>ui-view not populated</div>
<div class="header">
Current URL: <b>{{$location.url() }}</b> <br>
Current State: <b>{{$state.current.name }}</b> <br>
Current Params: <b>{{$state.params | json }}</b><br>
</div>
<br/>
<br/>
<div ng-controller="myController">
{{book}}
<br/>
<a ui-sref="bookDetails({bookId: 6789.1011})">Change params to book with dot</a><br/>
<button ng-click="viewBookDetails()">View Book Details</button>
</div>
</body>
</html>
我使用包含 'dot' 的 url 查询参数遇到的刷新问题是服务器问题。
这是由我在 grunt 服务器设置
中处理 html5mode(重定向到 index.html 如果不是静态资源)的方式引起的
// The original grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
require('connect-modrewrite')(['^[^\.]*$ /index.html [L]']), //Matches everything that does not contain a '.' (period) and causes the problem
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect().use(
'/app/styles',
connect.static('./app/styles')
),
connect.static(appConfig.app)
];
}
}
},
我改了
require('connect-modrewrite')(['^[^\.]*$ /index.html [L]']),
至
require('connect-modrewrite')([
'!\.html|\.js|\.css|\.svg|\.jp(e?)g|\.png|\.gif|\.ttf$ /index.html'
]),
如果你用的是connect-history-api-fallback on your server (like lite-server,带点的URL默认不重写
connect-history-api-fallback code
if (parsedUrl.pathname.indexOf('.') !== -1) {
logger(
'Not rewriting',
req.method,
req.url,
'because the path includes a dot (.) character.'
);
return next();
}
从 connect-history-api-fallback
版本开始 1.2.0 URLs with dots are allowed and you can solve this problem by using a a rewrite roule
例子
如果您的带点的 URL 是 /api/test/:id
(例如 /api/test/123.34
)并且您的 angular 应用位于 index.html
页面中,您可以添加将规则重写为 connect-history-api-fallback 像这样
rewrites: [
{
from: /^\/api\/test\/[0-9]+\.[0-9]+$/,
to: 'index.html'
}
}
]
在我们的 Angular 应用程序中,我们必须处理包含 "dot" 的 ID。例如:
book = {
id: '123.456'
}
我们在使用 id 作为 url 参数时遇到问题。如果通过 "Angular" 进行导航,则一切正常,即单击调用 $state.go('bookDetails', {bookId: book.id});
的 link。但是重新加载页面时事情不起作用
"Cannot GET /bookDetails?bookId=123.456"
在控制器中:
$scope.viewBookDetails = function() {
$state.go('bookDetails', {bookId: book.id});
}
在视图中
<a href="" ng-click="viewBookDetails(); $event.stopPropagation();">
在路由器中:
.state('bookDetails', {
url: '/bookDetails?bookId'
}
在浏览器中:
https://example.com/bookDetails?bookId=123.456
如果在浏览器中将 "dot" 替换为 %2E
,则 link 有效。
我们试图在 $state.go()
的参数中用“%2E”替换 "dot"$scope.viewBookDetails = function() {
$state.go('bookDetails', {bookId: book.id.split('.').join('%2E')});
}
但不起作用,因为“%”是自动编码的,浏览器中的 "dot" 被替换为“%252E”
https://example.com/bookDetails?bookId=123%252E456
我完全修改了代码。我可以很好地使用点,所以请分叉 plunker 以显示您在哪里出错。
http://plnkr.co/edit/Ct09Q9uoc282JuWdsO1s?p=preview
console.log("Scripts loading... ");
// Here's a skeleton app. Fork this plunk, or create your own from scratch.
var app = angular.module('demonstrateissue', ['ui.router']);
app.controller('myController', function($scope, $state){
$scope.book = {
id: '123.456'
};
$scope.viewBookDetails = function() {
console.log('new id');
$state.go('bookDetails', {bookId: 456.3456});
}
});
// Empty config block. Define your example states here.
app.config(function($stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider) {
$stateProvider.state('bookDetails', {
url: '/bookDetails:bookId',
controller: function($scope, $stateParams) {
$scope.book = {
id: $stateParams.bookId
};
},
template: "<h3>book: {{book}}</h3>"
});
$urlRouterProvider.otherwise("/bookDetails/91.23");
});
// Adds state change hooks; logs to console.
app.run(function($rootScope, $state, $location) {
$rootScope.$state = $state;
$rootScope.$location = $location;
function message(to, toP, from, fromP) {
return from.name + angular.toJson(fromP) + " -> " + to.name + angular.toJson(toP);
}
$rootScope.$on("$stateChangeStart", function(evt, to, toP, from, fromP) { console.log("Start: " + message(to, toP, from, fromP)); });
$rootScope.$on("$stateChangeSuccess", function(evt, to, toP, from, fromP) { console.log("Success: " + message(to, toP, from, fromP)); });
$rootScope.$on("$stateChangeError", function(evt, to, toP, from, fromP, err) { console.log("Error: " + message(to, toP, from, fromP), err); });
});
body {
margin-top: 6em;
}
.link {
text-decoration: underline;
color: blue;
}
.link:hover {
cursor: pointer;
}
.header {
position: fixed;
right: 0;
top: 0;
height: 6em;
width: 100%;
border-bottom: 1px solid gray;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://code.angularjs.org/1.2.25/angular.js"></script>
<script src="https://rawgit.com/angular-ui/ui-router/0.2.13/release/angular-ui-router.js"></script>
<script src="main.js"></script>
<link rel="stylesheet" href="styles.css" />
<title>Plunk demonstrating ui-router issue</title>
</head>
<body ng-app="demonstrateissue">
<div ui-view>ui-view not populated</div>
<div class="header">
Current URL: <b>{{$location.url() }}</b> <br>
Current State: <b>{{$state.current.name }}</b> <br>
Current Params: <b>{{$state.params | json }}</b><br>
</div>
<br/>
<br/>
<div ng-controller="myController">
{{book}}
<br/>
<a ui-sref="bookDetails({bookId: 6789.1011})">Change params to book with dot</a><br/>
<button ng-click="viewBookDetails()">View Book Details</button>
</div>
</body>
</html>
我使用包含 'dot' 的 url 查询参数遇到的刷新问题是服务器问题。
这是由我在 grunt 服务器设置
// The original grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
require('connect-modrewrite')(['^[^\.]*$ /index.html [L]']), //Matches everything that does not contain a '.' (period) and causes the problem
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect().use(
'/app/styles',
connect.static('./app/styles')
),
connect.static(appConfig.app)
];
}
}
},
我改了
require('connect-modrewrite')(['^[^\.]*$ /index.html [L]']),
至
require('connect-modrewrite')([
'!\.html|\.js|\.css|\.svg|\.jp(e?)g|\.png|\.gif|\.ttf$ /index.html'
]),
如果你用的是connect-history-api-fallback on your server (like lite-server,带点的URL默认不重写
connect-history-api-fallback code
if (parsedUrl.pathname.indexOf('.') !== -1) {
logger(
'Not rewriting',
req.method,
req.url,
'because the path includes a dot (.) character.'
);
return next();
}
从 connect-history-api-fallback
版本开始 1.2.0 URLs with dots are allowed and you can solve this problem by using a a rewrite roule
例子
如果您的带点的 URL 是 /api/test/:id
(例如 /api/test/123.34
)并且您的 angular 应用位于 index.html
页面中,您可以添加将规则重写为 connect-history-api-fallback 像这样
rewrites: [
{
from: /^\/api\/test\/[0-9]+\.[0-9]+$/,
to: 'index.html'
}
}
]