观察程序在数据加载需要一段时间时"休眠"



我已经编写了一个指令,它自动扩展返回键上的文本区域。然而,当我预先填充文本区域时,我希望它能增长到内容的大小。

当数据加载需要一点时间时,我的观察者有点睡着了。我必须点击文本区域才能与它进行交互,以便它最初自动展开。

理想情况下,我希望在初始自动扩展完成后停止观察程序,但不停止输入侦听器。

这是我的代码

angular.module('app',[])
.controller('mainCtrl', function($timeout) {
var vm = this;
vm.tab = 1;

//fake async call
$timeout(function() {
vm.text = 'fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r ';
}, 1500);
})
.directive('autoResize', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function autoResizeLink(scope, element, attrs, ngModel) {
scope.$watch(function() {
console.log('listen');
if((ngModel.$viewValue || ngModel.$modelValue) && element[0].scrollHeight > 0) {
console.log('view value appeared', ngModel.$viewValue);
console.log('element[0].scrollHeight',element[0].scrollHeight);
element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
element.css('height', element[0].scrollHeight + 'px');
console.log('stop listening here');
}
});
element.on('input', function () {
element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
element.css('height', element[0].scrollHeight + 'px');
});
}
}
});
a {
text-decoration: underline;
color: blue;
cursor: pointer;
}
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
</head>

<body>
<div ng-controller="mainCtrl as vm">

<a ng-click="vm.tab = 1">Tab 1</a>
<a ng-click="vm.tab = 2">Tab 2</a>

<div ng-show="vm.tab === 2">
<textarea auto-resize ng-model="vm.text"></textarea>
</div>
</div>
</body>
</html>

只有当存在用户事件或框架事件(例如来自服务器的数据(时,观察者才会评估其观察表达式。你称之为";"睡着了";是AngularJS框架的正常行为。

不要使用观察程序,而是使用$formatters和$viewChangeListeners管道:

app.directive('autoResize', function($timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function autoResizeLink(scope, element, attrs, ngModel) {
ngModel.$formatters.push(function(data) {
$timeout(resize);
return data;
});
ngModel.$viewChangeListeners.push(function() {
$timeout(resize);
});
function resize() {
console.log("resize");
element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
element.css('height', element[0].scrollHeight + 'px');
}
}
}
});

当ngModelController从框架中获取新的模型值时,它会调用$formatters函数。当它从用户那里获得新值时,它会调用$viewChangeListeners。

演示

angular.module('app',[])
.controller('mainCtrl', function($timeout) {
var vm = this;
vm.tab = 1;

//fake async call
$timeout(function() {
console.log("data");
vm.text = 'fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r fsafsafsafasfsa r ';
}, 1500);
})
.directive('autoResize', function($timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function autoResizeLink(scope, element, attrs, ngModel) {
ngModel.$formatters.push(function(data) {
$timeout(resize);
return data;
});
ngModel.$viewChangeListeners.push(function() {
$timeout(resize);
});
function resize() {
console.log("resize");
element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
element.css('height', element[0].scrollHeight + 'px');
}
}
}
});
a {
text-decoration: underline;
color: blue;
cursor: pointer;
}
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
</head>

<body>
<div ng-controller="mainCtrl as vm">

<a ng-click="vm.tab = 1">Tab 1</a>
<a ng-click="vm.tab = 2">Tab 2</a>

<div ng-if="vm.tab === 2">
<textarea auto-resize ng-model="vm.text"></textarea>
</div>
</div>
</body>
</html>

最新更新