我试图在Visual Studio 2015中学习如何在Cordova应用程序中使用WinJS。我目前正在努力获得Try WinJS website所述的基本列表视图。该应用程序在我的Android手机上成功启动,但是在我的Windows 8.1 PC上应用程序拒绝启动超过启动画面,给我错误0x800a138f - JavaScript runtime error: Unable to get property 'firstElementChild' of undefined or null reference
我当前的index.html如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WinJSTest</title>
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<meta name="msapplication-tap-highlight" content="no" />
<!-- WinJS references -->
<link href="css/ui-dark.css" rel="stylesheet" />
<script src="js/winstore-jscompat.js" ></script>
<!-- WinJSTest CSS references -->
<link href="css/index.css" rel="stylesheet" />
</head>
<body>
<!-- Simple template for the ListView instantiation -->
<div class="smallListIconTextTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
<div class="smallListIconTextItem">
<div class="smallListIconTextItem-Detail">
<h4 data-win-bind="textContent: title"></h4>
<h6 data-win-bind="textContent: text"></h6>
</div>
</div>
</div>
<!-- The declarative markup necesary for ListView instantiation -->
<!-- Call WinJS.UI.processAll() in your initialization code -->
<div id="listView"
class="win-selectionstylefilled"
data-win-control="WinJS.UI.ListView"
data-win-options="{
itemDataSource: Sample.ListView.data.dataSource,
itemTemplate: select('.smallListIconTextTemplate'),
selectionMode: 'single',
tapBehavior: 'none',
swipeBehavior: 'none',
layout: { type: WinJS.UI.ListLayout }
}">
</div>
<script src="js/WinJS.js"></script>
<!-- Cordova reference, this is added to your app when it's built. -->
<script src="cordova.js"></script>
<script src="scripts/platformOverrides.js"></script>
<script src="scripts/index.js"></script>
</body>
</html>
index.js也可以在下面找到:
// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkID=397704
// To debug code on page load in Ripple or on Android devices/emulators: launch your app, set breakpoints,
// and then run "window.location.reload()" in the JavaScript Console.
(function () {
"use strict";
document.addEventListener( 'deviceready', onDeviceReady.bind( this ), false );
function onDeviceReady() {
// Handle the Cordova pause and resume events
document.addEventListener( 'pause', onPause.bind( this ), false );
document.addEventListener( 'resume', onResume.bind( this ), false );
// TODO: Cordova has been loaded. Perform any initialization that requires Cordova here.
var items = [];
// Generate 2000 items
for (var i = 0; i < 2000; i++) {
items.push({ title: "Lorem Ipsum " + i, text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s " });
}
var itemList = new WinJS.Binding.List(items);
WinJS.Namespace.define("Sample.ListView", {
data: itemList
});
WinJS.UI.processAll();
};
function onPause() {
// TODO: This application has been suspended. Save application state here.
};
function onResume() {
// TODO: This application has been reactivated. Restore application state here.
};
} )();
希望有经验的人可以弄清楚我做错了什么:D
答案 0 :(得分:1)
我会检查FirElement是什么,以及它是否为空。
从那里,你可以尝试找出第一个孩子是什么。我开始时就像一个疯狂的人一样使用console.log。
所以在这种情况下,我用以下内容启动应用程序:
<强>的console.log(对象)强>
然后
<强>的console.log(object.firstElementChild)强>
这个帖子也更详细地解释了它:Unable to get property 'options' of undefined or null reference
答案 1 :(得分:1)
将它放在你的启动代码中。有点时髦,但有效...
这只应用于Windows应用商店。
(function () {
var winjs_drop_head_body = function (elem) {
if (!elem.winControl)
return;
//var before = elem.innerHTML;
var head = elem.firstElementChild;
if (head.localName == 'head') {
var body = head.nextElementSibling;
while (body.firstElementChild) {
elem.insertBefore(body.firstElementChild, head);
}
$(head).remove();
$(body).remove();
}
//var after = elem.innerHTML;
};
var winjs_drop_head_body_all = function () {
var heads = document.querySelectorAll('head');
for (var h = 0; h < heads.length; h++) {
var head = heads[h];
if (head.parentNode.localName != 'html') {
winjs_drop_head_body(<any>head.parentNode);
}
}
};
// drop the head after setting innerHTML
WinJS.Utilities.ready(() => {
var property = "innerHTML";
var propertyDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, property);
var getter = propertyDescriptor.get;
var setter = propertyDescriptor.set;
Object.defineProperty(HTMLElement.prototype, property, {
get: getter,
set: function (value) {
var that = this;
setter.call(that,value);
winjs_drop_head_body(that);
},
enumerable: propertyDescriptor.enumerable,
configurable: propertyDescriptor.configurable,
});
});
var oldApplyAll = WinJS.UI.processAll;
WinJS.UI.processAll = function (rootElement?, skipRoot?) {
var oldVal = oldApplyAll(rootElement, skipRoot);
oldVal.done(() => {
winjs_drop_head_body_all();
});
return oldVal;
}
})();
答案 2 :(得分:0)
我遇到了同样的问题。我发现设置innerHTML没有按预期工作。内容始终设置为
<head></head><body>CONTENTS</body>
如果内容包含标记。
即使您在调试器中的QuickWatch中手动设置它。
我认为这与商店应用中的安全限制有关。
我写了一个删除头部和身体元素的函数:
export function winjs_drop_head_body_all() {
var heads = document.querySelectorAll('head');
for (var h = 0; h < heads.length; h++) {
var head = heads[h];
if (head.parentNode.localName != 'html') {
HMSMapUtil.winjs_drop_head_body(head.parentNode);
}
}
}
export function winjs_drop_head_body(elem) {
var head = elem.firstElementChild
if (head.localName == 'head') {
var body = head.nextElementSibling;
while (body.firstElementChild) {
elem.insertBefore(body.firstElementChild, head);
}
}
}
我在winjs.js中winjs_drop_head_body_all()
的每一行之后WinJS.UI.processAll().done(...)
和winjs_drop_head_body(elem)
结束时调用.innerHTML =
。
这是一个修补程序,而不是一个真正的解决方案,但我还没有找到其他办法。
希望有人能找到更好的解决方案。