我有以下字符串:
"/root/get";
现在我在上面的字符串中生成一个带有1个范围变量的查询字符串,但问题是当该变量的值发生变化时,新的值没有自动更新到我的URL中。
您可以在下面的演示中看到我有2个按钮更新和检查。在更新中我生成查询字符串,并在检查按钮上我更新范围变量的值,但这没有反映在我的URL中。
我不明白为什么会这样。
单击check按钮而不调用generateQueryParameters方法时的预期输出:
/root/get?no=2
var app = angular.module("myApp", []);
app.controller("myController", function ($scope) {
$scope.no = 1;
$scope.str = "/root/get";
$scope.update = function (data) {
$scope.str=generateQueryParameters($scope.str,
"no",$scope.no);
console.log($scope.str);
};
$scope.check = function () {
$scope.no=2;
console.log($scope.str);
};
function generateQueryParameters(url,name,value)
{
var re = new RegExp("([?&]" + name + "=)[^&]+", "");
function add(sep) {
url += sep + name + "=" + encodeURIComponent(value);
}
function change() {
url = url.replace(re, "$1" + encodeURIComponent(value));
}
if (url.indexOf("?") === -1) {
add("?");
} else {
if (re.test(url)) {
change();
} else {
add("&");
}
}
return url;
}
});

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<input type="button" value="Update" ng-click="update()">
<input type="button" value="Check" ng-click="check()">
</div>
&#13;
更新:我知道$ scope.no的价值何时会发生变化,所以我不认为我需要观察员而且我不想拨打generateParameters
再次。为什么angular不会像Angular绑定那样自动更新str
中的值?
答案 0 :(得分:3)
让我们从您的代码中的问题开始。您通过函数生成请求字符串,该函数实际上仅在update
函数
$scope.update = function(data) {
$scope.str = generateQueryParameters($scope.str,
"no", $scope.no);
console.log($scope.str);
};
$scope.check = function() {
$scope.no = 2;
console.log($scope.str);
};
您更改check
功能中的版本号,但不再调用该功能以更改$scope.str
,因此$scope.str
的值仍然相同。
您可以在代码段中执行以下步骤轻松测试:
点击更新(v0)
点击检查(v0)
但是再次点击更新,您会看到它现在已更新(v2)
因此,在第2步中您实际更改了版本,您只是不再生成要使用的str
。
为您的代码轻松修复只是为了在每次更改版本时调用分配新str
的函数来安排代码:
$scope.update = function(data) {
$scope.no = 1;
$scope.str = generateQueryParameters($scope.str,
"no", $scope.no);
console.log($scope.str);
};
$scope.check = function() {
$scope.no = 2;
// here you need to call again your function for composing your URL and changing the value of str
$scope.str = generateQueryParameters($scope.str,
"no", $scope.no);
console.log($scope.str);
};
function generateStringRequest() {
}
否则,您需要查看no
版本参数,并在每次版本更改时自动刷新str
值。但是这个解决方案意味着你将在每个调用API的控制器中都有一个观察器,并且所有参数总是在控制器内硬编码:
$scope.$watch('no', function() {
$scope.str = generateQueryParameters($scope.str, 'no', $scope.no);
});
即使这个解决方案有效,实际上也很糟糕。 管理呼叫的逻辑是在控制器内部,这是一种非常糟糕的做法(您应该考虑使用集中式服务)。
更好的是,在AngularJS中,您可以使用自定义拦截器并管理有关HTTP请求的所有操作。 因此,您可以指定HTTP请求的参数,即要使用的API的版本。
这将使您的代码保持清洁。此外,如果您希望将来更改某些请求,您只需更改该请求参数即可。
如果您想更改所有请求,可以在拦截器内设置version 1
的所有请求都将替换为version 2
。
这里有一个关于如何定义拦截器的示例代码:
angular.module('myApp').factory('MyHTTPFactory', MyHTTPFactory)
.config(function($httpProvider) {
// register the new interceptor in AngularJS
$httpProvider.interceptors.push('MyHTTPFactory');
});
MyHTTPFactory.$inject = [];
function MyHTTPFactory() {
// this is the base URL of your rest requests, so this interceptor will be applied only to the requests directed to your service
const MY_REST_URL = 'blablabla';
// methods exposed by the service
let factory = {
request: request,
requestError: requestError,
response: response,
responseError: responseError
};
return factory;
// ============================================================
function request(config) {
if (config.url.includes(MY_REST_URL)) {
let versionToUse = config.version;
// here use a function for elaborating your query string, directly in the interecptor code
config.url = elaborateQueryString();
}
return config;
}
function requestError(config) {
return config;
}
function response(res) {
return res;
}
function responseError(res) {
return res;
}
// function for getting the query string you want to
function elaborateQueryString() {
// elaborate your requests
}
}
然后只需通过$http
执行HTTP请求,将请求中使用的版本作为参数添加:
// perform your request as usual simply specifying the new version parameter
let request = {
url: `myserviceurl`,
version: '2' // or whatever you qNR
};
$http(request);
所以拦截器将会#34;嗅探&#34;在您执行之前的所有请求中,它将根据您的需要正确组合版本和查询字符串,并且您的所有操作都在其中进行管理并集中。
正如最后一个提示,在定义版本号等常量时,其余服务的端点,无论如何,使用AngularJS constant
并将它们注入需要使用它们的位置。硬编码字符串不是一个好习惯。
答案 1 :(得分:1)
您可以使用新的控制器作为语法(允许您直接绑定到控制器属性和方法)轻松定义属性 str
,如下所示:< / p>
Object.defineProperty(vm,
"str", {
get: function() {
return vm.generateQueryParameters("/root/get","no", vm.no);
},
set: function(newValue) {
// setter function
},
enumerable: true,
configurable: true
});
这意味着每次您访问str
的值,它会重新评估url字符串。这使您的代码独立 $scope
和$watch
,并且更加具有前瞻性。
var app = angular.module("myApp", []);
app.controller("myController", function() {
var vm = this;
vm.no = 1;
Object.defineProperty(vm,
"str", {
get: function() {
return vm.generateQueryParameters("/root/get","no", vm.no);
},
set: function(newValue) {
// setter function
},
enumerable: true,
configurable: true
});
vm.update = function(data) {
console.log(vm.str);
};
vm.check = function() {
vm.no = 2;
console.log(vm.str);
};
vm.generateQueryParameters = function(url, name, value) {
var re = new RegExp("([?&]" + name + "=)[^&]+", "");
function add(sep) {
url += sep + name + "=" + encodeURIComponent(value);
}
function change() {
url = url.replace(re, "$1" + encodeURIComponent(value));
}
if (url.indexOf("?") === -1) {
add("?");
} else {
if (re.test(url)) {
change();
} else {
add("&");
}
}
return url;
}
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController as ctrl">
<input type="button" value="Update" ng-click="ctrl.update()">
<input type="button" value="Check" ng-click="ctrl.check()">
</div>
&#13;
对于以下对象(来自讨论):
[
{
"name": "Node-1",
"isParent": true,
"text" : [
{
"str" : "/root/get",
},
{
"str" : "/root/get",
}],
"nodes": [
{
"name": "Node-1-1",
"isParent": false,
"text" : [
{
"str" : "/root/get",
},
{
"str" : "/root/get",
}],
"nodes": [
{
"name": "Node-1-1-1",
"isParent": false,
"text" : [
{
"str" : "/root/get",
},
{
"str" : "/root/get",
}],
"nodes": []
}
]
}
]
}
]
我们可以扩展这种方法 - 见下面的演示:
var app = angular.module("myApp", []);
app.controller("myController", function() {
var vm = this;
vm.no = 1;
vm._records=[{"name":"Node-1","isParent":true,"text":[{"str":"/root/get",},{"str":"/root/get",}],"nodes":[{"name":"Node-1-1","isParent":false,"text":[{"str":"/root/get",},{"str":"/root/get",}],"nodes":[{"name":"Node-1-1-1","isParent":false,"text":[{"str":"/root/get",},{"str":"/root/get",}],"nodes":[]}]}]}];
vm.setRecords = function(node, url) {
node.text && node.text.forEach(function(e){
e.str = url;
});
// recursively set url
node.nodes && node.nodes.forEach(function(e){
vm.setRecords(e, url);
});
}
Object.defineProperty(vm,
"records", {
get: function() {
let url = vm.generateQueryParameters("/root/get", "no", vm.no);
vm._records.forEach(function(e){
vm.setRecords(e, url);
});
return vm._records;
},
set: function(newValue) {
// setter function
},
enumerable: true,
configurable: true
});
vm.update = function(data) {
console.log(vm.records);
};
vm.check = function() {
vm.no = 2;
console.log(vm.records);
};
vm.generateQueryParameters = function(url, name, value) {
var re = new RegExp("([?&]" + name + "=)[^&]+", "");
function add(sep) {
url += sep + name + "=" + encodeURIComponent(value);
}
function change() {
url = url.replace(re, "$1" + encodeURIComponent(value));
}
if (url.indexOf("?") === -1) {
add("?");
} else {
if (re.test(url)) {
change();
} else {
add("&");
}
}
return url;
}
});
&#13;
.as-console-wrapper{top:25px;max-height:calc(100% - 25px)!important;}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController as ctrl">
<input type="button" value="Update" ng-click="ctrl.update()">
<input type="button" value="Check" ng-click="ctrl.check()">
</div>
&#13;
答案 2 :(得分:0)
您需要为no
添加一个称为generateQueryParameters
的方法的观察者,并更改$scope.str
的值
var app = angular.module("myApp", []);
app.controller("myController", function ($scope) {
$scope.no = 1;
$scope.str = "/root/get";
$scope.check = function () {
console.log($scope.str);
};
$scope.$watch('no', function() {
$scope.str = generateQueryParameters($scope.str,
"no",$scope.no);
});
$scope.update = function (data) {
$scope.no=2;
};
function generateQueryParameters(url,name,value)
{
var re = new RegExp("([?&]" + name + "=)[^&]+", "");
function add(sep) {
url += sep + name + "=" + encodeURIComponent(value);
}
function change() {
url = url.replace(re, "$1" + encodeURIComponent(value));
}
if (url.indexOf("?") === -1) {
add("?");
} else {
if (re.test(url)) {
change();
} else {
add("&");
}
}
return url;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<input type="button" value="Update" ng-click="update()">
<input type="button" value="Check" ng-click="check()">
</div>
首先更新,然后检查
答案 3 :(得分:0)
你需要在check方法中再次调用generateQueryParameters方法。
$scope.check = function () {
$scope.no=2;
$scope.str=generateQueryParameters($scope.str,
"no",$scope.no);
console.log($scope.str);
};
答案 4 :(得分:0)
您可以使用
"UPDATE obj, orb SET obj.id = orb.id WHERE obj.desig = orb.desig AND
obj.id != orb.id;"
在函数中对范围应用更改。它实质上有助于强制您的双向数据绑定启动并捕获范围中的新更改。如果你正确地实现数据绑定,你不必使用这个命令,但它确实可以作为一个脏的快速黑客。
答案 5 :(得分:0)
尝试这个,问题是javascript原始值是作为值而不是引用传递的。
var app = angular.module("myApp", []);
app.controller("myController", function ($scope) {
$scope.testObject = {
no: 1,
str: "/root/get"
};
$scope.update = function (data) {
$scope.str=generateQueryParameters($scope.testObject,
"no");
console.log($scope.testObject);
};
$scope.check = function () {
$scope.testObject.no=2;
console.log($scope.testObject.str);
};
function generateQueryParameters(urlAndValue, name)
{
var re = new RegExp("([?&]" + name + "=)[^&]+", "");
function add(sep) {
urlAndValue.str += sep + name + "=" + encodeURIComponent(urlAndValue.no);
}
function change() {
urlAndValue.str = urlAndValue.str.replace(re, "$1" + encodeURIComponent(urlAndValue.no));
}
if (urlAndValue.str.indexOf("?") === -1) {
add("?");
} else {
if (re.test(urlAndValue.str)) {
change();
} else {
add("&");
}
}
return urlAndValue.str;
}
});
答案 6 :(得分:0)
试试这个:
$scope.str = "/root/get";
$scope.$apply();