簡體   English   中英

在PhantomJS上ngTransclude失敗

[英]ngTransclude fails on PhantomJS

所以我正在開發一個AngularJS網站,我一直負責讓它對Facebook分享和SEO友好。 我選擇了PhantomJS作為一種可能的解決方案,來評估Javascript並吐出已執行的html代碼,現在只是用信息填充facebook meta標簽。

但是在啟動phantomJS並評估頁面后,我的chrome中出現了這個錯誤:

錯誤:[ngTransclude:orphan]在模板中非法使用ngTransclude指令! 沒有找到需要轉換的父指令。 元素: <ul ng-transclude=""> http://errors.angularjs.org/1.2.22/ngTransclude/orphan?p0=%3Cul%20ng-transclude%3D%22%22%3E

查看代碼之后,我只在網站中使用了一次transclude,這是用於生成我的菜單,其中包含ul和transcluded li項目。

    app.directive('mvMenu', ['$rootScope', '$location', function ($rootScope, $location) {
return {
    restrict: 'E',
    transclude: true,
    controller: function ($scope, $element, $attrs) {
        ...
    },
    template: '<nav id="nav" role="navigation">' +
                '<div class="block">' +
                '<ul ng-transclude>' +
                '</ul>' +
                '</div>' +
                '</nav>'

}
}]);

我的項目也是一個指令,其代碼如下:

app.directive('mvMenuItem', ['$location', function ($location) {
return {
    require: '^mvMenu',
    restrict: 'E',
    scope: {
        text: '@text',
        navLink: '@link',
        icon: '@faicon'
    },
    link: function (scope, element, attr, menuCtrl) {
        ...
    },
    template: '<li ng-class="{\'is-active\': isActive(navLink)}">' +
    '<a ng-click="navAndToggleMenu(navLink)"><span class="fa {{icon}}"></span>{{text | translate}}</a>' +
    '</li><!--'
}
}]);

在任何設備上的任何瀏覽器上使用該站點時,我從未見過此錯誤。 只有在使用phantomJS評估頁面時才會出現。

這是我用來生成html的phantomJS代碼:

var page = require('webpage').create();
var system = require('system');

var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var startTime = new Date().getTime();

page.onResourceReceived = function (response) {
if (requestIds.indexOf(response.id) !== -1) {
    lastReceived = new Date().getTime();
    responseCount++;
    requestIds[requestIds.indexOf(response.id)] = null;
}
};
page.onResourceRequested = function (request) {
if (requestIds.indexOf(request.id) === -1) {
    requestIds.push(request.id);
    requestCount++;
}
};

function checkLoaded() {
return page.evaluate(function () {
    return document.all;
}) != null;
}
// Open the page
page.open(system.args[1], function () { });

var checkComplete = function () {
// We don't allow it to take longer than 5 seconds but
// don't return until all requests are finished
if ((new Date().getTime() - lastReceived > 300 && requestCount ===            
responseCount) || new Date().getTime() - startTime > 10000 || checkLoaded()) {
    clearInterval(checkCompleteInterval);
    var result = page.content;
    //result = result.substring(0, 10000);
    console.log(result);
    //console.log(results);
    phantom.exit();
}
}
// Let us check to see if the page is finished rendering
var checkCompleteInterval = setInterval(checkComplete, 300);

此代碼取自如何使SPA SEO可抓取? ,唯一的區別在於評估方法中的“return document.all”。

提前致謝!

運行PhantomJS腳本后,您獲得的html已經呈現。 當你在已經渲染后在普通瀏覽器中打開它時,讓angular嘗試再次渲染它是沒有意義的。

以下面的標記為例:

<div ng-repeat="stuff in stuffList">{{stuff}}</div>

這例如被渲染到

<div class="ng-repeat" ng-repeat="stuff in stuffList">Stuff1</div>
<div class="ng-repeat" ng-repeat="stuff in stuffList">Stuff2</div>

如果在瀏覽器中打開已渲染的標記會發生什么? 將再次執行ng-repeat ,這將導致以下標記:

<div class="ng-repeat" ng-repeat="stuff in stuffList">Stuff1</div>
<div class="ng-repeat" ng-repeat="stuff in stuffList">Stuff1</div>
<div class="ng-repeat" ng-repeat="stuff in stuffList">Stuff2</div>
<div class="ng-repeat" ng-repeat="stuff in stuffList">Stuff2</div>

那不是你想要的。

您應該在保存標記之前刪除所有頁面腳本。 不再需要JavaScript。

page.evaluate(function(){
    [].forEach.call(document.querySelectorAll("script"), function(s){
        s.parentNode.removeChild(s)
    });
});
fs.write("content.html", page.content);
phantom.exit();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM