Navigationsoptionen für SharePoint

In diesem Artikel werden Navigationsoptionenwebsites mit aktivierter SharePoint-Veröffentlichung in SharePoint beschrieben. Die Auswahl und Konfiguration der Navigation wirkt sich erheblich auf die Leistung und Skalierbarkeit von Websites in SharePoint aus. Die SharePoint-Veröffentlichungswebsitevorlage sollte nur verwendet werden, wenn dies für ein zentrales Portal erforderlich ist, und das Veröffentlichungsfeature sollte nur auf bestimmten Websites und nur bei Bedarf aktiviert werden, da sie sich bei falscher Verwendung auf die Leistung auswirken kann.

Hinweis

Wenn Sie moderne SharePoint-Navigationsoptionen wie Megamenü, kaskadierende Navigation oder Hubnavigation verwenden, gilt dieser Artikel nicht für Ihre Website. Moderne SharePoint-Websitearchitekturen nutzen eine vereinfachte Websitehierarchie und ein Hub-and-Spoke-Modell. Dadurch können viele Szenarien erreicht werden, die KEINE Verwendung des SharePoint-Veröffentlichungsfeatures erfordern.

Übersicht über Navigationsoptionen

Die Konfiguration des Navigationsanbieters kann sich erheblich auf die Leistung für die gesamte Website auswirken. Bei der Auswahl eines Navigationsanbieters und einer Konfiguration, die für die Anforderungen einer SharePoint-Website effektiv skaliert wird, muss sorgfältig überlegt werden. Es gibt zwei sofort einsatzbereite Navigationsanbieter sowie benutzerdefinierte Navigationsimplementierungen.

Die erste Option, Strukturelle Navigation, ist die empfohlene Navigationsoption in SharePoint für klassische SharePoint-Websites, wenn Sie die strukturelle Navigationszwischenspeicherung für Ihre Website aktivieren. Dieser Navigationsanbieter zeigt die Navigationselemente unterhalb der aktuellen Website und optional die aktuelle Website und ihre gleichgeordneten Elemente an. Es bietet zusätzliche Funktionen wie Sicherheitskürzungen und Websitestrukturenumeration. Wenn die Zwischenspeicherung deaktiviert ist, wirkt sich dies negativ auf die Leistung und Skalierbarkeit aus und unterliegt möglicherweise einer Drosselung.

Die zweite Option, Verwaltete Navigation (Metadaten), stellt Navigationselemente mithilfe eines Ausdruckssatzes für verwaltete Metadaten dar. Es wird empfohlen, die Sicherheitskürzung zu deaktivieren, sofern dies nicht erforderlich ist. Die Sicherheitskürzung ist standardmäßig als sichere Einstellung für diesen Navigationsanbieter aktiviert. Viele Websites erfordern jedoch nicht den Aufwand der Sicherheitskürzung, da Navigationselemente häufig für alle Benutzer der Website konsistent sind. Mit der empfohlenen Konfiguration zum Deaktivieren der Sicherheitskürzung erfordert dieser Navigationsanbieter keine Aufzählung der Websitestruktur und ist hochgradig skalierbar mit akzeptablen Leistungseinbußen.

Neben den standardmäßigen Navigationsanbietern haben viele Kunden erfolgreich alternative benutzerdefinierte Navigationsimplementierungen implementiert. Weitere Informationen finden Sie in diesem Artikel unter Search gesteuertes clientseitiges Skripting.

Vor- und Nachteile von SharePoint-Navigationsoptionen

In der folgenden Tabelle sind die Vor- und Nachteile der einzelnen Optionen zusammengefasst.

Strukturelle Navigation Verwaltete Navigation Search-gesteuerte Navigation Benutzerdefinierter Navigationsanbieter
Profis:

Einfach zu warten
Sicherheit gekürzt
Automatische Aktualisierung innerhalb von 24 Stunden, wenn Inhalte geändert werden
Profis:

Einfach zu warten
Profis:

Sicherheit gekürzt
Automatische Updates, wenn Websites hinzugefügt werden
Schnelle Ladezeit und lokal zwischengespeicherte Navigationsstruktur
Profis:

Größere Auswahl an Verfügbaren Optionen
Schnelles Laden bei ordnungsgemäßer Zwischenspeicherung
Viele Optionen funktionieren gut mit reaktionsfähigem Seitendesign
Nachteile:

Wirkt sich auf die Leistung aus, wenn die Zwischenspeicherung deaktiviert ist
Drosselung unterliegen
Nachteile:

Nicht automatisch aktualisiert, um die Websitestruktur widerzuspiegeln
Wirkt sich auf die Leistung aus, wenn die Sicherheitskürzung aktiviert ist oder die Navigationsstruktur komplex ist.
Nachteile:

Keine Möglichkeit, Websites einfach zu bestellen
Erfordert die Anpassung der seite master (technische Kenntnisse erforderlich)
Nachteile:

Benutzerdefinierte Entwicklung ist erforderlich
Externe Datenquelle/gespeicherter Cache ist erforderlich, z. B. Azure

Die am besten geeignete Option für Ihre Website hängt von Ihren Standortanforderungen und Von Ihren technischen Fähigkeiten ab. Wenn Sie einen einfach zu konfigurierenden Navigationsanbieter benötigen, der automatisch aktualisiert wird, wenn Inhalte geändert werden, ist die strukturelle Navigation mit aktivierter Zwischenspeicherung eine gute Option.

Hinweis

Die Anwendung des gleichen Prinzips wie moderne SharePoint-Websites, indem die allgemeine Websitestruktur auf eine flachere, nicht hierarchische Struktur vereinfacht wird, verbessert die Leistung und vereinfacht den Wechsel zu modernen SharePoint-Websites. Dies bedeutet, dass anstelle einer einzelnen Websitesammlung mit Hunderten von Websites (Unterwebs) ein besserer Ansatz darin besteht, viele Websitesammlungen mit sehr wenigen Unterwebsites (Unterwebs) zu haben.

Analysieren der Navigationsleistung in SharePoint

Das Tool Seitendiagnose für SharePoint ist eine Browsererweiterung für Microsoft Edge- und Chrome-Browser, die sowohl moderne SharePoint-Portal- als auch klassische Veröffentlichungswebsiteseiten analysiert. Dieses Tool funktioniert nur für SharePoint und kann nicht auf einer SharePoint-Systemseite verwendet werden.

Das Tool generiert einen Bericht für jede analysierte Seite, der zeigt, wie sich die Seite mit einem vordefinierten Satz von Regeln abschneidet, und zeigt detaillierte Informationen an, wenn die Ergebnisse für einen Test außerhalb des Basiswerts liegen. SharePoint-Administratoren und Designer können das Tool verwenden, um Leistungsprobleme zu beheben, um sicherzustellen, dass neue Seiten vor der Veröffentlichung optimiert werden.

SPRequestDuration ist insbesondere die Zeit, die SharePoint benötigt, um die Seite zu verarbeiten. Eine hohe Navigation (z. B. das Einschließen von Seiten in die Navigation), komplexe Websitehierarchien und andere Konfigurations- und Topologieoptionen können erheblich zu längeren Daueren beitragen.

Verwenden der strukturellen Navigation in SharePoint

Dies ist die standardmäßig verwendete Standardnavigation und die einfachste Lösung. Es ist keine Anpassung erforderlich, und ein nichttechnischer Benutzer kann auch problemlos Elemente hinzufügen, Elemente ausblenden und die Navigation über die Einstellungsseite verwalten. Es wird empfohlen, die Zwischenspeicherung zu aktivieren, da andernfalls ein teurer Leistungskonflikt besteht.

Implementieren der strukturellen Navigationszwischenspeicherung

Unter Websiteeinstellungen>Aussehen und Verhalten>Navigation können Sie überprüfen, ob die strukturelle Navigation entweder für die globale Navigation oder für die aktuelle Navigation ausgewählt ist. Die Auswahl von Seiten anzeigen hat negative Auswirkungen auf die Leistung.

Strukturelle Navigation mit ausgewählter Option

Die Zwischenspeicherung kann auf Websitesammlungsebene und auf Websiteebene aktiviert oder deaktiviert werden und ist standardmäßig für beide aktiviert. Aktivieren Sie zum Aktivieren auf Websitesammlungsebene unter Websiteeinstellungen>Websitesammlungsverwaltung>Websitesammlungsnavigation das Kontrollkästchen Zwischenspeichern aktivieren.

Aktivieren Sie die Zwischenspeicherung auf Websitesammlungsebene.

Aktivieren Sie zum Aktivieren auf Websiteebene unter Websiteeinstellungen>navigation das Kontrollkästchen Zwischenspeichern aktivieren.

Aktivieren Sie die Zwischenspeicherung auf Websiteebene.

Verwenden von verwalteter Navigation und Metadaten in SharePoint

Die verwaltete Navigation ist eine weitere sofort einsatzbereite Option, mit der Sie die meisten Funktionen wie die strukturelle Navigation neu erstellen können. Verwaltete Metadaten können so konfiguriert werden, dass die Sicherheitskürzung aktiviert oder deaktiviert ist. Bei der Konfiguration mit deaktivierter Sicherheitskürzung ist die verwaltete Navigation relativ effizient, da alle Navigationslinks mit einer konstanten Anzahl von Serveraufrufen geladen werden. Die Aktivierung von Sicherheitskürzungen negiert jedoch einige der Leistungsvorteile der verwalteten Navigation.

Wenn Sie die Sicherheitskürzung aktivieren müssen, empfehlen wir Folgendes:

  • Aktualisieren aller benutzerfreundlichen URL-Links auf einfache Links
  • Hinzufügen erforderlicher Sicherheitskürzungsknoten als benutzerfreundliche URLs
  • Beschränken Sie die Anzahl der Navigationselemente auf maximal 100 und nicht mehr als drei Ebenen tief.

Viele Websites erfordern keine Sicherheitskürzung, da die Navigationsstruktur häufig für alle Benutzer der Website konsistent ist. Wenn die Sicherheitskürzung deaktiviert ist und der Navigation ein Link hinzugefügt wird, auf den nicht alle Benutzer Zugriff haben, wird der Link weiterhin angezeigt, führt aber zu einer Meldung verweigerter Zugriff. Es besteht kein Risiko eines versehentlichen Zugriffs auf den Inhalt.

Implementieren der verwalteten Navigation und der Ergebnisse

Es gibt mehrere Artikel auf Microsoft Learn zu den Details der verwalteten Navigation. Weitere Informationen finden Sie beispielsweise unter Übersicht über die verwaltete Navigation in SharePoint Server.

Um die verwaltete Navigation zu implementieren, richten Sie Begriffe mit URLs ein, die der Navigationsstruktur der Website entsprechen. Die verwaltete Navigation kann sogar manuell zusammengestellt werden, um die strukturelle Navigation in vielen Fällen zu ersetzen. Zum Beispiel:

SharePoint-Websitestruktur.)

Verwenden Search clientseitiger Skripterstellung

Eine gängige Klasse benutzerdefinierter Navigationsimplementierungen umfasst vom Client gerenderte Entwurfsmuster, die einen lokalen Cache von Navigationsknoten speichern.

Diese Navigationsanbieter haben einige wichtige Vorteile:

  • Sie funktionieren in der Regel gut mit reaktionsfähigen Seitendesigns.
  • Sie sind extrem skalierbar und leistungsfähig, da sie ohne Ressourcenkosten gerendert werden können (und nach einem Timeout im Hintergrund aktualisiert werden können).
  • Diese Navigationsanbieter können Navigationsdaten mithilfe verschiedener Strategien abrufen, die von einfachen statischen Konfigurationen bis hin zu verschiedenen dynamischen Datenanbietern reichen.

Ein Beispiel für einen Datenanbieter ist die Verwendung einer Search-gesteuerten Navigation, die Flexibilität für das Aufzählen von Navigationsknoten und die effiziente Verarbeitung von Sicherheitskürzungen ermöglicht.

Es gibt weitere beliebte Optionen zum Erstellen von benutzerdefinierten Navigationsanbietern. Weitere Anleitungen zum Erstellen eines benutzerdefinierten Navigationsanbieters finden Sie unter Navigationslösungen für SharePoint-Portale .

Mithilfe der Suche können Sie die im Hintergrund erstellten Indizes mit fortlaufender Durchforstung nutzen. Die Suchergebnisse werden aus dem Suchindex abgerufen, und die Ergebnisse sind sicherheitsbeschnitten. Dies ist in der Regel schneller als sofort einsatzbereite Navigationsanbieter, wenn Sicherheitskürzungen erforderlich sind. Die Verwendung der Suche für die strukturelle Navigation, insbesondere bei einer komplexen Websitestruktur, beschleunigt die Ladezeit der Seite erheblich. Der Standard Vorteil gegenüber der verwalteten Navigation besteht darin, dass Sie von der Sicherheitskürzung profitieren.

Dieser Ansatz umfasst das Erstellen einer benutzerdefinierten master-Seite und das Ersetzen des vordefinierten Navigationscodes durch benutzerdefinierten HTML-Code. Gehen Sie wie im folgenden Beispiel beschrieben vor, um den Navigationscode in der Datei seattle.htmlzu ersetzen. In diesem Beispiel öffnen Sie die seattle.html Datei und ersetzen das gesamte Element id="DeltaTopNavigation" durch benutzerdefinierten HTML-Code.

Beispiel: Ersetzen des vordefinierten Navigationscodes auf einer master Seite

  1. Navigieren Sie zur Seite Websiteeinstellungen.
  2. Öffnen Sie den master Seitenkatalog, indem Sie auf Gestaltungsvorlagen klicken.
  3. Von hier aus können Sie durch die Bibliothek navigieren und die Datei seattle.masterherunterladen.
  4. Bearbeiten Sie den Code mithilfe eines Text-Editors, und löschen Sie den Codeblock im folgenden Screenshot.
    Löschen Sie den angezeigten Codeblock.
  5. Entfernen Sie den Code zwischen den <SharePoint:AjaxDelta id="DeltaTopNavigation"> Tags und , <\SharePoint:AjaxDelta> und ersetzen Sie ihn durch den folgenden Codeausschnitt:
<div id="loading">
  <!--Replace with path to loading image.-->
  <div style="background-image: url(''); height: 22px; width: 22px; ">
  </div>
</div>
<!-- Main Content-->
<div id="navContainer" style="display:none">
    <div data-bind="foreach: hierarchy" class="noindex ms-core-listMenu-horizontalBox">
        <a class="dynamic menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode" data-bind="attr: { href: item.Url, title: item.Title }">
            <span class="menu-item-text" data-bind="text: item.Title">
            </span>
        </a>
        <ul id="menu" data-bind="foreach: $data.children" style="padding-left:20px">
            <li class="static dynamic-children level1">
                <a class="static dynamic-children menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode" data-bind="attr: { href: item.Url, title: item.Title }">

                 <!-- ko if: children.length > 0-->
                    <span aria-haspopup="true" class="additional-background ms-navedit-flyoutArrow dynamic-children">
                        <span class="menu-item-text" data-bind="text: item.Title">
                        </span>
                    </span>
                <!-- /ko -->
                <!-- ko if: children.length == 0-->
                    <span aria-haspopup="true" class="ms-navedit-flyoutArrow dynamic-children">
                        <span class="menu-item-text" data-bind="text: item.Title">
                        </span>
                    </span>
                <!-- /ko -->
                </a>

                <!-- ko if: children.length > 0-->
                <ul id="menu"  data-bind="foreach: children;" class="dynamic  level2" >
                    <li class="dynamic level2">
                        <a class="dynamic menu-item ms-core-listMenu-item ms-displayInline  ms-navedit-linkNode" data-bind="attr: { href: item.Url, title: item.Title }">

          <!-- ko if: children.length > 0-->
          <span aria-haspopup="true" class="additional-background ms-navedit-flyoutArrow dynamic-children">
           <span class="menu-item-text" data-bind="text: item.Title">
           </span>
          </span>
           <!-- /ko -->
          <!-- ko if: children.length == 0-->
          <span aria-haspopup="true" class="ms-navedit-flyoutArrow dynamic-children">
           <span class="menu-item-text" data-bind="text: item.Title">
           </span>
          </span>
          <!-- /ko -->
                        </a>
          <!-- ko if: children.length > 0-->
         <ul id="menu" data-bind="foreach: children;" class="dynamic level3" >
          <li class="dynamic level3">
           <a class="dynamic menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode" data-bind="attr: { href: item.Url, title: item.Title }">
            <span class="menu-item-text" data-bind="text: item.Title">
            </span>
           </a>
          </li>
         </ul>
           <!-- /ko -->
                    </li>
                </ul>
                <!-- /ko -->
            </li>
        </ul>
    </div>
</div>

6. Ersetzen Sie die URL im Tag zum Laden des Imageankers am Anfang durch einen Link zu einem Ladebild in Ihrer Websitesammlung. Nachdem Sie die Änderungen vorgenommen haben, benennen Sie die Datei um, und laden Sie sie dann in den master Seitenkatalog hoch. Dadurch wird eine neue generiert. master Datei.
7. Dieser HTML-Code ist das grundlegende Markup, das von den Suchergebnissen aufgefüllt wird, die von JavaScript-Code zurückgegeben werden. Sie müssen den Code bearbeiten, um den Wert für var root = "websitesammlungs-URL" zu ändern, wie im folgenden Codeausschnitt veranschaulicht:
var root = "https://spperformance.sharepoint.com/sites/NavigationBySearch";

8. Die Ergebnisse werden dem Self.nodes-Array zugewiesen, und eine Hierarchie wird aus den Objekten mithilfe von linq.js Zuweisen der Ausgabe zu einem Array self.hierarchy erstellt. Dieses Array ist das Objekt, das an den HTML-Code gebunden ist. Dies erfolgt in der toggleView()-Funktion, indem das Selbstobjekt an die ko.applyBinding()-Funktion übergeben wird.
Dies bewirkt dann, dass das Hierarchiearray an den folgenden HTML-Code gebunden wird:
<div data-bind="foreach: hierarchy" class="noindex ms-core-listMenu-horizontalBox">

Die Ereignishandler für mouseenter und mouseexit werden der Navigation auf oberster Ebene hinzugefügt, um die Dropdownmenüs der Unterwebsite zu verarbeiten, die in der addEventsToElements() Funktion ausgeführt werden.

In unserem komplexen Navigationsbeispiel zeigt ein neuer Seitenladevorgang ohne lokales Zwischenspeichern an, dass die auf dem Server aufgewendete Zeit aus der strukturellen Benchmarknavigation reduziert wurde, um ein ähnliches Ergebnis wie der verwaltete Navigationsansatz zu erhalten.

Informationen zur JavaScript-Datei...

Hinweis

Wenn Sie benutzerdefiniertes JavaScript verwenden, stellen Sie sicher, dass das öffentliche CDN aktiviert ist und sich die Datei an einem CDN-Speicherort befindet.

Die gesamte JavaScript-Datei sieht wie folgt aus:

//Models and Namespaces
var SPOCustom = SPOCustom || {};
SPOCustom.Models = SPOCustom.Models || {}
SPOCustom.Models.NavigationNode = function () {

    this.Url = ko.observable("");
    this.Title = ko.observable("");
    this.Parent = ko.observable("");

};

var root = "https://spperformance.sharepoint.com/sites/NavigationBySearch";
var baseUrl = root + "/_api/search/query?querytext=";
var query = baseUrl + "'contentClass=\"STS_Web\"+path:" + root + "'&trimduplicates=false&rowlimit=300";

var baseRequest = {
    url: "",
    type: ""
};


//Parses a local object from JSON search result.
function getNavigationFromDto(dto) {
    var item = new SPOCustom.Models.NavigationNode();
    if (dto != undefined) {

        var webTemplate = getSearchResultsValue(dto.Cells.results, 'WebTemplate');

        if (webTemplate != "APP") {
            item.Title(getSearchResultsValue(dto.Cells.results, 'Title')); //Key = Title
            item.Url(getSearchResultsValue(dto.Cells.results, 'Path')); //Key = Path
            item.Parent(getSearchResultsValue(dto.Cells.results, 'ParentLink')); //Key = ParentLink
        }

    }
    return item;
}

function getSearchResultsValue(results, key) {

    for (i = 0; i < results.length; i++) {
        if (results[i].Key == key) {
            return results[i].Value;
        }
    }
    return null;
}

//Parse a local object from the serialized cache.
function getNavigationFromCache(dto) {
    var item = new SPOCustom.Models.NavigationNode();

    if (dto != undefined) {

        item.Title(dto.Title);
        item.Url(dto.Url);
        item.Parent(dto.Parent);
    }

    return item;
}

/* create a new OData request for JSON response */
function getRequest(endpoint) {
    var request = baseRequest;
    request.type = "GET";
    request.url = endpoint;
    request.headers = { ACCEPT: "application/json;odata=verbose" };
    return request;
};

/* Navigation Module*/
function NavigationViewModel() {
    "use strict";
    var self = this;
    self.nodes = ko.observableArray([]);
    self.hierarchy = ko.observableArray([]);;
    self.loadNavigatioNodes = function () {
        //Check local storage for cached navigation datasource.
        var fromStorage = localStorage["nodesCache"];
        if (false) {
            var cachedNodes = JSON.parse(localStorage["nodesCache"]);

            if (cachedNodes && timeStamp) {
                //Check for cache expiration. Currently set to 3 hrs.
                var now = new Date();
                var diff = now.getTime() - timeStamp;
                if (Math.round(diff / (1000 * 60 * 60)) < 3) {

                    //return from cache.
                    var cacheResults = [];
                    $.each(cachedNodes, function (i, item) {
                        var nodeitem = getNavigationFromCache(item, true);
                        cacheResults.push(nodeitem);
                    });

                    self.buildHierarchy(cacheResults);
                    self.toggleView();
                    addEventsToElements();
                    return;
                }
            }
        }
        //No cache hit, REST call required.
        self.queryRemoteInterface();
    };

    //Executes a REST call and builds the navigation hierarchy.
    self.queryRemoteInterface = function () {
        var oDataRequest = getRequest(query);
        $.ajax(oDataRequest).done(function (data) {
            var results = [];
            $.each(data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results, function (i, item) {

                if (i == 0) {
                    //Add root element.
                    var rootItem = new SPOCustom.Models.NavigationNode();
                    rootItem.Title("Root");
                    rootItem.Url(root);
                    rootItem.Parent(null);
                    results.push(rootItem);
                }
                var navItem = getNavigationFromDto(item);
                results.push(navItem);
            });
            //Add to local cache
            localStorage["nodesCache"] = ko.toJSON(results);

            localStorage["nodesCachedAt"] = new Date().getTime();
            self.nodes(results);
            if (self.nodes().length > 0) {
                var unsortedArray = self.nodes();
                var sortedArray = unsortedArray.sort(self.sortObjectsInArray);

                self.buildHierarchy(sortedArray);
                self.toggleView();
                addEventsToElements();
            }
        }).fail(function () {
            //Handle error here!!
            $("#loading").hide();
            $("#error").show();
        });
    };
    self.toggleView = function () {
        var navContainer = document.getElementById("navContainer");
        ko.applyBindings(self, navContainer);
        $("#loading").hide();
        $("#navContainer").show();

    };
    //Uses linq.js to build the navigation tree.
    self.buildHierarchy = function (enumerable) {
        self.hierarchy(Enumerable.From(enumerable).ByHierarchy(function (d) {
            return d.Parent() == null;
        }, function (parent, child) {
            if (parent.Url() == null || child.Parent() == null)
                return false;
            return parent.Url().toUpperCase() == child.Parent().toUpperCase();
        }).ToArray());

        self.sortChildren(self.hierarchy()[0]);
    };


    self.sortChildren = function (parent) {

        // sjip processing if no children
        if (!parent || !parent.children || parent.children.length === 0) {
            return;
        }

        parent.children = parent.children.sort(self.sortObjectsInArray2);

        for (var i = 0; i < parent.children.length; i++) {
            var elem = parent.children[i];

            if (elem.children && elem.children.length > 0) {
                self.sortChildren(elem);
            }
        }
    };

    // ByHierarchy method breaks the sorting in chrome and firefox
    // we need to resort  as ascending
    self.sortObjectsInArray2 = function (a, b) {
        if (a.item.Title() > b.item.Title())
            return 1;
        if (a.item.Title() < b.item.Title())
            return -1;
        return 0;
    };


    self.sortObjectsInArray = function (a, b) {
        if (a.Title() > b.Title())
            return -1;
        if (a.Title() < b.Title())
            return 1;
        return 0;
    }
}

//Loads the navigation on load and binds the event handlers for mouse interaction.
function InitCustomNav() {
    var viewModel = new NavigationViewModel();
    viewModel.loadNavigatioNodes();
}

function addEventsToElements() {
    //events.
      $("li.level1").mouseover(function () {
          var position = $(this).position();
          $(this).find("ul.level2").css({ width: 100, left: position.left + 10, top: 50 });
      })
   .mouseout(function () {
     $(this).find("ul.level2").css({  left: -99999, top: 0 });
   
    });
   
     $("li.level2").mouseover(function () {
          var position = $(this).position();
          console.log(JSON.stringify(position));
          $(this).find("ul.level3").css({ width: 100, left: position.left + 95, top:  position.top});
      })
   .mouseout(function () {
     $(this).find("ul.level3").css({  left: -99999, top: 0 });
    });
} _spBodyOnLoadFunctionNames.push("InitCustomNav");

Um den oben in der jQuery $(document).ready Funktion gezeigten Code zusammenzufassen, wird eine viewModel object erstellt, und dann wird die loadNavigationNodes() Funktion für dieses Objekt aufgerufen. Diese Funktion lädt entweder die zuvor erstellte Navigationshierarchie, die im lokalen HTML5-Speicher des Clientbrowsers gespeichert ist, oder sie ruft die Funktion queryRemoteInterface()auf.

QueryRemoteInterface() erstellt eine Anforderung mithilfe der getRequest() -Funktion mit dem zuvor im Skript definierten Abfrageparameter und gibt dann Daten vom Server zurück. Diese Daten sind im Wesentlichen ein Array aller Standorte in der Websitesammlung, die als Datenübertragungsobjekte mit verschiedenen Eigenschaften dargestellt werden.

Diese Daten werden dann in die zuvor definierten SPO.Models.NavigationNode Objekte analysiert, die verwenden Knockout.js , um beobachtbare Eigenschaften für die Verwendung durch Datenbindung der Werte in den zuvor definierten HTML-Code zu erstellen.

Die Objekte werden dann in ein Ergebnisarray eingefügt. Dieses Array wird mithilfe von Knockout in JSON analysiert und im lokalen Browserspeicher gespeichert, um die Leistung bei zukünftigen Seitenladevorgängen zu verbessern.

Vorteile dieses Ansatzes

Ein hauptvorteil dieses Ansatzes besteht darin, dass die Navigation mithilfe des lokalen HTML5-Speichers beim nächsten Laden der Seite für den Benutzer lokal gespeichert wird. Durch die Verwendung der Such-API für die strukturelle Navigation erhalten wir wesentliche Leistungsverbesserungen. Es sind jedoch einige technische Funktionen zum Ausführen und Anpassen dieser Funktionalität benötigt.

In der Beispielimplementierung werden die Websites auf die gleiche Weise sortiert wie die standardmäßige strukturelle Navigation; alphabetische Reihenfolge. Wenn Sie von dieser Reihenfolge abweichen möchten, wäre es komplizierter zu entwickeln und zu warten. Außerdem müssen Sie bei diesem Ansatz von den unterstützten master Seiten abweichen. Wenn die benutzerdefinierte master Seite nicht verwaltet wird, verpassen Ihre Website Updates und Verbesserungen, die Microsoft an den master Seiten vornimmt.

Der obige Code weist die folgenden Abhängigkeiten auf:

Die aktuelle Version von LinqJS enthält nicht die byHierarchy-Methode, die im obigen Code verwendet wird, und der Navigationscode wird unterbrochen. Um dies zu beheben, fügen Sie der Linq.js-Datei vor der Zeile Flatten: function ()die folgende Methode hinzu.

ByHierarchy: function(firstLevel, connectBy, orderBy, ascending, parent) {
     ascending = ascending == undefined ? true : ascending;
     var orderMethod = ascending == true ? 'OrderBy' : 'OrderByDescending';
     var source = this;
     firstLevel = Utils.CreateLambda(firstLevel);
     connectBy = Utils.CreateLambda(connectBy);
     orderBy = Utils.CreateLambda(orderBy);

     //Initiate or increase level
     var level = parent === undefined ? 1 : parent.level + 1;

    return new Enumerable(function() {
         var enumerator;
         var index = 0;

        var createLevel = function() {
                 var obj = {
                     item: enumerator.Current(),
                     level : level
                 };
                 obj.children = Enumerable.From(source).ByHierarchy(firstLevel, connectBy, orderBy, ascending, obj);
                 if (orderBy !== undefined) {
                     obj.children = obj.children[orderMethod](function(d) {
                         return orderBy(d.item); //unwrap the actual item for sort to work
                     });
                 }
                 obj.children = obj.children.ToArray();
                 Enumerable.From(obj.children).ForEach(function(child) {
                     child.getParent = function() {
                         return obj;
                     };
                 });
                 return obj;
             };

        return new IEnumerator(

        function() {
             enumerator = source.GetEnumerator();
         }, function() {
             while (enumerator.MoveNext()) {
                 var returnArr;
                 if (!parent) {
                     if (firstLevel(enumerator.Current(), index++)) {
                         return this.Yield(createLevel());
                     }

                } else {
                     if (connectBy(parent.item, enumerator.Current(), index++)) {
                         return this.Yield(createLevel());
                     }
                 }
             }
             return false;
         }, function() {
             Utils.Dispose(enumerator);
         })
     });
 },

Übersicht über die verwaltete Navigation in SharePoint Server

Zwischenspeicherung und Leistung der strukturellen Navigation