Uncaught TypeError: Cannot read property 'attr' of null using popover
Uncaught TypeError: Cannot read property 'attr' of null using popover
我正在使用 onsen-ui 1.3.13,我收到了这个我不明白的错误:
未捕获的类型错误:无法使用 popover @ loader.js:1450
读取 null 的 属性 'attr'
我基本上有 1 个按钮,当我单击它时,会出现 1 个弹出窗口和另外 2 个按钮。按钮 2 对数组进行简单的弹出操作。它有效,但之后立即给我这个错误。
这是我的代码:
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="components/loader.js"></script>
<script src="js/controler.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="js/angular-moment.js"></script>
<script src="js/readable-range.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/sliding_menu.css">
</head>
<body>
<ons-sliding-menu main-page="initial.html" menu-page="menu.html" max-slide-distance="260px" type="overlay" var="menu" side="left" close-on-tap>
</ons-sliding-menu>
<ons-template id="menu.html">
<ons-page modifier="menu-page">
<ons-toolbar modifier="transparent">
<div class="right">
<ons-toolbar-button class="menu-closeMenu" ng-click="menu.closeMenu()">
</ons-icon>Close
</ons-toolbar-button>
</div>
</ons-toolbar>
<ons-list class="menu-list" ng-controller="PopoverController">
<ons-list-item class="menu-item" ng-click="menu.setMainPage('initial.html', {closeMenu: true})">
<ons-icon icon="fa-gbp"></ons-icon>
Initial page
</ons-list-item>
<ons-list-item class="menu-item" ng-click="reset();menu.closeMenu()">
<ons-icon icon="fa-gbp"></ons-icon>
reset
</ons-list-item>
</ons-list>
</ons-page>
</ons-template>
<ons-template id="popover.html">
<ons-popover direction="down" cancelable>
<ons-list>
<ons-list-item modifier="tappable" ng-click="alert(true, 'Sorry not available in this version')">
<ons-icon icon="fa-cloud"></ons-icon>
Save property
</ons-list-item>
<ons-list-item modifier="tappable" ng-click="reset(); destroy($event)" >
<ons-icon icon="fa-home"></ons-icon>
<label>Reset</label>
</ons-list-item>
</ons-list>
</ons-popover>
</ons-template>
</body>
</html>
controler.js:
var app = ons.bootstrap('propertyDeal', ['onsen','angularMoment']);
app.factory('Property', function () {
/**
* Constructor, with class name
*/
function Property(newProperty) {
this.id = newProperty.id;
this.purchasePrice = newProperty.pprice;
this.legaFee = newProperty.legal;
}
return {
createNew: function(newProperty) {
return new Property(newProperty);
}
};
});
app.factory('portfolio', function(Property){
var portfolio = {};
portfolio.list = [];
portfolio.add = function(newProperty){
var prop = Property.createNew(newProperty);
portfolio.list.push(prop);
};
portfolio.remove = function(){
var removed = portfolio.list.pop();
};
return portfolio;
});
app.controller('PopoverController', function($scope, portfolio) {
$scope.popurl = function(url, e) {
$scope.param = url;
ons.createPopover( $scope.param,{parentScope: $scope}).then(function(popover) {
$scope.popover = popover;
$scope.show(e);
});
$scope.show = function(e) {
$scope.popover.show(e);
};
$scope.destroy = function(e) {
$scope.popover.destroy(e);
};
};
$scope.alert = function(material, message) {
ons.notification.alert({
message: message,
modifier: material ? 'material' : undefined
});
};
$scope.reset = function() {
if (portfolio.list.length >= 1){
portfolio.remove();
}
};
});
app.controller('ListCtrl', function(portfolio) {
this.portfolio = portfolio.list;
});
app.controller('PostCtrl', function(portfolio){
this.addProperty = function(newProperty){
if (angular.isDefined(newProperty)) {
newProperty.id = portfolio.list.length;
portfolio.add(newProperty);
}
};
});
initial.html
<ons-navigator>
<ons-page>
<div class="container">
<ons-toolbar>
<div class="left">
<ons-toolbar-button ng-click="menu.toggleMenu()">
<ons-icon icon="ion-navicon" size="28px" fixed-width="false"></ons-icon>
</ons-toolbar-button>
<ons-icon class="icon" icon="ion-android-share"></ons-icon> this is a test
</div>
<div class="right" ng-controller="PopoverController">
<ons-toolbar-button id="android-share" ng-click="popurl('popover_share.html', $event)">
<ons-icon icon="ion-android-share" fixed-width="false"></ons-icon>
</ons-toolbar-button>
<ons-toolbar-button id="android-more" ng-click="popurl('popover.html', $event)">
<ons-icon icon="ion-android-more-vertical" fixed-width="false"></ons-icon>
</ons-toolbar-button>
</div>
</ons-toolbar>
</div>
<div style="text-align: center">
<h2>Page 1</h2>
<ul class="list">
<input type="hidden" ng-model="newProperty.id" placeholder="id">
<li class="list__item">
<span class="currency">£<input type="number" class="text-input text-input--transparent" style="width:100%; margin-top:4px;" ng-model="newProperty.pprice" placeholder="Purchase price" required></span>
</li>
<li class="list__item">
<span class="currency">£<input type="number" class="text-input text-input--transparent" style="width:100%; margin-top:4px;" ng-model="newProperty.legal" placeholder="Legal fees"></span>
</li>
</ul>
</div>
<br />
<div ng-controller="PostCtrl as post">
<button class="button" ng-click="post.addProperty(newProperty);menu.setMainPage('initial2.html')">Next <ons-icon icon="ion-arrow-right-b"></ons-icon></button>
<p>{{newProperty}}</p>
</div>
<div ng-controller="ListCtrl as list">
<p ng-repeat="prop in list.portfolio track by $index">
New Property: {{prop.id}} - {{prop.purchasePrice}}: {{prop.legaFee}} </p>
</div>
</ons-page>
</ons-navigator>
在将 reset() 也添加到滑动菜单后,我还可以说它与滑动菜单一起工作得很好,所以我认为这肯定是弹出窗口的问题,但我不知道是什么。
感谢您的帮助
在该代码中,您一遍又一遍地创建和销毁弹出框。问题不在 reset()
函数中,而是在 destroy()
中。您试图在显示弹出窗口时销毁它,并且存在时间问题。当它已经被摧毁时,它会在内部尝试检查它的位置。即使现在没有消失的动画,因为你只是摧毁它而不是隐藏它。
解决方案是创建一次弹出窗口,然后在需要时显示和隐藏它们。希望对您有所帮助!
更新:
您现在的使用方式实际上存在内存泄漏。每次单击工具栏按钮时都会创建弹出窗口,并在 reset()
函数中将其销毁。问题是,如果您显示弹出窗口,然后在它的外部单击,它将被隐藏而不是被破坏,所以下次您打开弹出窗口时,它会创建另一个弹出窗口。您可以检查您的 DOM 并看到每次都添加了 1 个弹出窗口。
弹出框的正确使用方法是只创建一次,然后在需要时显示和隐藏它。只有当你不再需要它时,你才需要销毁它。有一种方法可以自动完成:
$scope.$on('$destroy', $scope.myPopover.destroy);
当您切换到另一个范围时,这将破坏当前范围中的弹出窗口。
我正在使用 onsen-ui 1.3.13,我收到了这个我不明白的错误: 未捕获的类型错误:无法使用 popover @ loader.js:1450
读取 null 的 属性 'attr'我基本上有 1 个按钮,当我单击它时,会出现 1 个弹出窗口和另外 2 个按钮。按钮 2 对数组进行简单的弹出操作。它有效,但之后立即给我这个错误。
这是我的代码:
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="components/loader.js"></script>
<script src="js/controler.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="js/angular-moment.js"></script>
<script src="js/readable-range.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/sliding_menu.css">
</head>
<body>
<ons-sliding-menu main-page="initial.html" menu-page="menu.html" max-slide-distance="260px" type="overlay" var="menu" side="left" close-on-tap>
</ons-sliding-menu>
<ons-template id="menu.html">
<ons-page modifier="menu-page">
<ons-toolbar modifier="transparent">
<div class="right">
<ons-toolbar-button class="menu-closeMenu" ng-click="menu.closeMenu()">
</ons-icon>Close
</ons-toolbar-button>
</div>
</ons-toolbar>
<ons-list class="menu-list" ng-controller="PopoverController">
<ons-list-item class="menu-item" ng-click="menu.setMainPage('initial.html', {closeMenu: true})">
<ons-icon icon="fa-gbp"></ons-icon>
Initial page
</ons-list-item>
<ons-list-item class="menu-item" ng-click="reset();menu.closeMenu()">
<ons-icon icon="fa-gbp"></ons-icon>
reset
</ons-list-item>
</ons-list>
</ons-page>
</ons-template>
<ons-template id="popover.html">
<ons-popover direction="down" cancelable>
<ons-list>
<ons-list-item modifier="tappable" ng-click="alert(true, 'Sorry not available in this version')">
<ons-icon icon="fa-cloud"></ons-icon>
Save property
</ons-list-item>
<ons-list-item modifier="tappable" ng-click="reset(); destroy($event)" >
<ons-icon icon="fa-home"></ons-icon>
<label>Reset</label>
</ons-list-item>
</ons-list>
</ons-popover>
</ons-template>
</body>
</html>
controler.js:
var app = ons.bootstrap('propertyDeal', ['onsen','angularMoment']);
app.factory('Property', function () {
/**
* Constructor, with class name
*/
function Property(newProperty) {
this.id = newProperty.id;
this.purchasePrice = newProperty.pprice;
this.legaFee = newProperty.legal;
}
return {
createNew: function(newProperty) {
return new Property(newProperty);
}
};
});
app.factory('portfolio', function(Property){
var portfolio = {};
portfolio.list = [];
portfolio.add = function(newProperty){
var prop = Property.createNew(newProperty);
portfolio.list.push(prop);
};
portfolio.remove = function(){
var removed = portfolio.list.pop();
};
return portfolio;
});
app.controller('PopoverController', function($scope, portfolio) {
$scope.popurl = function(url, e) {
$scope.param = url;
ons.createPopover( $scope.param,{parentScope: $scope}).then(function(popover) {
$scope.popover = popover;
$scope.show(e);
});
$scope.show = function(e) {
$scope.popover.show(e);
};
$scope.destroy = function(e) {
$scope.popover.destroy(e);
};
};
$scope.alert = function(material, message) {
ons.notification.alert({
message: message,
modifier: material ? 'material' : undefined
});
};
$scope.reset = function() {
if (portfolio.list.length >= 1){
portfolio.remove();
}
};
});
app.controller('ListCtrl', function(portfolio) {
this.portfolio = portfolio.list;
});
app.controller('PostCtrl', function(portfolio){
this.addProperty = function(newProperty){
if (angular.isDefined(newProperty)) {
newProperty.id = portfolio.list.length;
portfolio.add(newProperty);
}
};
});
initial.html
<ons-navigator>
<ons-page>
<div class="container">
<ons-toolbar>
<div class="left">
<ons-toolbar-button ng-click="menu.toggleMenu()">
<ons-icon icon="ion-navicon" size="28px" fixed-width="false"></ons-icon>
</ons-toolbar-button>
<ons-icon class="icon" icon="ion-android-share"></ons-icon> this is a test
</div>
<div class="right" ng-controller="PopoverController">
<ons-toolbar-button id="android-share" ng-click="popurl('popover_share.html', $event)">
<ons-icon icon="ion-android-share" fixed-width="false"></ons-icon>
</ons-toolbar-button>
<ons-toolbar-button id="android-more" ng-click="popurl('popover.html', $event)">
<ons-icon icon="ion-android-more-vertical" fixed-width="false"></ons-icon>
</ons-toolbar-button>
</div>
</ons-toolbar>
</div>
<div style="text-align: center">
<h2>Page 1</h2>
<ul class="list">
<input type="hidden" ng-model="newProperty.id" placeholder="id">
<li class="list__item">
<span class="currency">£<input type="number" class="text-input text-input--transparent" style="width:100%; margin-top:4px;" ng-model="newProperty.pprice" placeholder="Purchase price" required></span>
</li>
<li class="list__item">
<span class="currency">£<input type="number" class="text-input text-input--transparent" style="width:100%; margin-top:4px;" ng-model="newProperty.legal" placeholder="Legal fees"></span>
</li>
</ul>
</div>
<br />
<div ng-controller="PostCtrl as post">
<button class="button" ng-click="post.addProperty(newProperty);menu.setMainPage('initial2.html')">Next <ons-icon icon="ion-arrow-right-b"></ons-icon></button>
<p>{{newProperty}}</p>
</div>
<div ng-controller="ListCtrl as list">
<p ng-repeat="prop in list.portfolio track by $index">
New Property: {{prop.id}} - {{prop.purchasePrice}}: {{prop.legaFee}} </p>
</div>
</ons-page>
</ons-navigator>
在将 reset() 也添加到滑动菜单后,我还可以说它与滑动菜单一起工作得很好,所以我认为这肯定是弹出窗口的问题,但我不知道是什么。
感谢您的帮助
在该代码中,您一遍又一遍地创建和销毁弹出框。问题不在 reset()
函数中,而是在 destroy()
中。您试图在显示弹出窗口时销毁它,并且存在时间问题。当它已经被摧毁时,它会在内部尝试检查它的位置。即使现在没有消失的动画,因为你只是摧毁它而不是隐藏它。
解决方案是创建一次弹出窗口,然后在需要时显示和隐藏它们。希望对您有所帮助!
更新:
您现在的使用方式实际上存在内存泄漏。每次单击工具栏按钮时都会创建弹出窗口,并在 reset()
函数中将其销毁。问题是,如果您显示弹出窗口,然后在它的外部单击,它将被隐藏而不是被破坏,所以下次您打开弹出窗口时,它会创建另一个弹出窗口。您可以检查您的 DOM 并看到每次都添加了 1 个弹出窗口。
弹出框的正确使用方法是只创建一次,然后在需要时显示和隐藏它。只有当你不再需要它时,你才需要销毁它。有一种方法可以自动完成:
$scope.$on('$destroy', $scope.myPopover.destroy);
当您切换到另一个范围时,这将破坏当前范围中的弹出窗口。