Navigatieopties voor SharePoint

In dit artikel worden navigatieopties voor sites beschreven waarvoor SharePoint-publicatie is ingeschakeld in SharePoint. De keuze en configuratie van navigatie heeft een aanzienlijke invloed op de prestaties en schaalbaarheid van sites in SharePoint. De sharePoint-publicatiesitesjabloon mag alleen worden gebruikt als dat nodig is voor een gecentraliseerde portal en de publicatiefunctie mag alleen worden ingeschakeld op specifieke sites en alleen wanneer dit nodig is, omdat deze de prestaties kan beïnvloeden wanneer deze onjuist wordt gebruikt.

Opmerking

Als u moderne SharePoint-navigatieopties gebruikt, zoals megamenu, trapsgewijze navigatie of hubnavigatie, is dit artikel niet van toepassing op uw site. Moderne SharePoint-sitearchitecturen maken gebruik van een meer afgevlakte sitehiërarchie en een hub-and-spoke-model. Hierdoor kunnen veel scenario's worden bereikt waarvoor de publicatiefunctie van SharePoint NIET is vereist.

Overzicht van navigatieopties

De configuratie van de navigatieprovider kan de prestaties van de hele site aanzienlijk beïnvloeden. Er moet zorgvuldig worden nagedacht over het kiezen van een navigatieprovider en configuratie die effectief kan worden geschaald voor de vereisten van een SharePoint-site. Er zijn twee standaardnavigatieproviders en aangepaste navigatie-implementaties.

De eerste optie, Structurele navigatie, is de aanbevolen navigatieoptie in SharePoint voor klassieke SharePoint-sites , als u structurele navigatiecache voor uw site inschakelt. Deze navigatieprovider geeft de navigatie-items onder de huidige site weer, en optioneel de huidige site en de bijbehorende broers en zusters. Het biedt aanvullende mogelijkheden, zoals beveiliging bijsnijden en inventarisatie van sitestructuur. Als caching is uitgeschakeld, heeft dit een negatieve invloed op de prestaties en schaalbaarheid en kan dit worden beperkt.

De tweede optie, Beheerde navigatie (metagegevens), vertegenwoordigt navigatie-items met behulp van een termenset beheerde metagegevens. We raden u aan om beveiligingsbeperkingen uit te schakelen, tenzij dit vereist is. Beveiliging bijsnijden is ingeschakeld als een veilige standaardinstelling voor deze navigatieprovider; Veel sites vereisen echter niet de overhead van beveiligingsbeperkingen, omdat navigatie-elementen vaak consistent zijn voor alle gebruikers van de site. Met de aanbevolen configuratie voor het uitschakelen van beveiliging hoeft deze navigatieprovider de sitestructuur niet op te sommen en is het zeer schaalbaar met acceptabele gevolgen voor de prestaties.

Naast de standaardnavigatieproviders hebben veel klanten alternatieve aangepaste navigatie-implementaties geïmplementeerd. Zie Search-driven client-side scripting in dit artikel.

Voor- en nadelen van SharePoint-navigatieopties

De volgende tabel bevat een overzicht van de voor- en nadelen van elke optie.

Structurele navigatie Beheerde navigatie Search gestuurde navigatie Aangepaste navigatieprovider
Pros:

Eenvoudig te onderhouden
Beveiliging is bijgesneden
Automatisch bijgewerkt binnen 24 uur wanneer inhoud wordt gewijzigd
Pros:

Eenvoudig te onderhouden
Pros:

Beveiliging is bijgesneden
Automatisch bijwerken wanneer sites worden toegevoegd
Snelle laadtijd en lokaal opgeslagen navigatiestructuur
Pros:

Ruimere keuze aan beschikbare opties
Snel laden wanneer cache correct wordt gebruikt
Veel opties werken goed met responsief paginaontwerp
Tegens:

Heeft invloed op de prestaties als caching is uitgeschakeld
Onderhevig aan beperking
Tegens:

Niet automatisch bijgewerkt om de sitestructuur weer te geven
Heeft invloed op de prestaties als beveiligingsinkorten is ingeschakeld of wanneer de navigatiestructuur complex is
Tegens:

Geen mogelijkheid om eenvoudig sites te bestellen
Aanpassing van de basispagina vereist (technische vaardigheden vereist)
Tegens:

Aangepaste ontwikkeling is vereist
Externe gegevensbron/cache die is opgeslagen, is nodig, bijvoorbeeld Azure

De meest geschikte optie voor uw site is afhankelijk van uw sitevereisten en van uw technische mogelijkheden. Als u een eenvoudig te configureren navigatieprovider wilt die automatisch wordt bijgewerkt wanneer inhoud wordt gewijzigd, is structurele navigatie met caching ingeschakeld een goede optie.

Opmerking

Het toepassen van hetzelfde principe als moderne SharePoint-sites door de algehele sitestructuur te vereenvoudigen tot een platte, niet-hiërarchische structuur verbetert de prestaties en vereenvoudigt het verplaatsen naar moderne SharePoint-sites. Wat dit betekent is dat in plaats van één siteverzameling met honderden sites (subwebs), een betere benadering is om veel siteverzamelingen met zeer weinig subsites (subwebs) te hebben.

Navigatieprestaties analyseren in SharePoint

Het hulpprogramma Paginadiagnose voor SharePoint is een browserextensie voor Microsoft Edge- en Chrome-browsers waarmee zowel de moderne SharePoint-portal als de klassieke publicatiesitepagina's worden geanalyseerd. Dit hulpprogramma werkt alleen voor SharePoint en kan niet worden gebruikt op een SharePoint-systeempagina.

Het hulpprogramma genereert een rapport voor elke geanalyseerde pagina waarin wordt aangegeven hoe de pagina presteert op basis van een vooraf gedefinieerde set regels en gedetailleerde informatie wordt weergegeven wanneer de resultaten voor een test buiten de basislijnwaarde vallen. SharePoint-beheerders en -ontwerpers kunnen het hulpprogramma gebruiken om prestatieproblemen op te lossen om ervoor te zorgen dat nieuwe pagina's worden geoptimaliseerd voordat ze worden gepubliceerd.

SPRequestDuration is met name de tijd die sharepoint nodig heeft om de pagina te verwerken. Zware navigatie (zoals het opnemen van pagina's in navigatie), complexe sitehiërarchieën en andere configuratie- en topologieopties kunnen allemaal aanzienlijk bijdragen aan langere duur.

Structurele navigatie gebruiken in SharePoint

Dit is destandaardnavigatie die standaard wordt gebruikt en is de meest eenvoudige oplossing. Er is geen aanpassing vereist en een niet-technische gebruiker kan ook eenvoudig items toevoegen, items verbergen en de navigatie beheren vanaf de instellingenpagina. We raden u aan om caching in te schakelen, anders is er een dure prestatie-afweging.

Structurele navigatiecaching implementeren

Onder Site-instellingen>Uiterlijknavigatie> kunt u controleren of structurele navigatie is geselecteerd voor globale navigatie of huidige navigatie. Als u Pagina's weergeven selecteert, heeft dit een negatieve invloed op de prestaties.

Structurele navigatie met Subsites weergeven geselecteerd.

Caching kan worden ingeschakeld of uitgeschakeld op het niveau van de siteverzameling en op siteniveau, en is standaard ingeschakeld voor beide. Als u wilt inschakelen op het niveau van de siteverzameling, schakelt u onder Site-instellingen>Siteverzamelingsbeheer>navigatie het selectievakje In cache inschakelen in.

Caching op siteverzamelingsniveau inschakelen.

Als u wilt inschakelen op siteniveau, schakelt u onderNavigatievan site-instellingen> het selectievakje In cache inschakelen in.

Caching op siteniveau inschakelen.

Beheerde navigatie en metagegevens gebruiken in SharePoint

Beheerde navigatie is een andere out-of-the-box-optie die u kunt gebruiken om de meeste van dezelfde functionaliteit als structurele navigatie opnieuw te maken. Beheerde metagegevens kunnen worden geconfigureerd om beveiliging in- of uit te schakelen. Wanneer de beveiliging is uitgeschakeld, is beheerde navigatie vrij efficiënt omdat alle navigatiekoppelingen worden geladen met een constant aantal server-aanroepen. Als u beveiligingsbeperkingen inschakelt, worden echter enkele prestatievoordelen van beheerde navigatie teniet gedaan.

Als u beveiligingsbeperkingen wilt inschakelen, raden we u aan het volgende te doen:

  • Alle beschrijvende URL-koppelingen bijwerken naar eenvoudige koppelingen
  • Vereiste beveiligingsknooppunten toevoegen als beschrijvende URL's
  • Beperk het aantal navigatie-items tot niet meer dan 100 en niet meer dan drie niveaus diep

Veel sites vereisen geen beveiligingsbeperkingen, omdat de navigatiestructuur vaak consistent is voor alle gebruikers van de site. Als het inkorten van beveiliging is uitgeschakeld en er een koppeling wordt toegevoegd aan de navigatie waartoe niet alle gebruikers toegang hebben, wordt de koppeling nog steeds weergegeven, maar wordt de toegang geweigerd. Er is geen risico op onbedoelde toegang tot de inhoud.

Beheerde navigatie en de resultaten implementeren

Er zijn verschillende artikelen op Microsoft Learn over de details van beheerde navigatie. Zie bijvoorbeeld Overzicht van beheerde navigatie in SharePoint Server.

Als u beheerde navigatie wilt implementeren, stelt u voorwaarden in met URL's die overeenkomen met de navigatiestructuur van de site. Beheerde navigatie kan in veel gevallen zelfs handmatig worden samengesteld om structurele navigatie te vervangen. Bijvoorbeeld:

SharePoint-sitestructuur.)

Scripting aan Search aan de clientzijde gebruiken

Een algemene klasse aangepaste navigatie-implementaties omvat door de client gegenereerde ontwerppatronen die een lokale cache van navigatieknooppunten opslaan.

Deze navigatieproviders hebben een aantal belangrijke voordelen:

  • Ze werken over het algemeen goed met responsieve paginaontwerpen.
  • Ze zijn uiterst schaalbaar en presterend omdat ze zonder resourcekosten kunnen worden weergegeven (en op de achtergrond kunnen worden vernieuwd na een time-out).
  • Deze navigatieproviders kunnen navigatiegegevens ophalen met behulp van verschillende strategieën, variërend van eenvoudige statische configuraties tot verschillende dynamische gegevensproviders.

Een voorbeeld van een gegevensprovider is het gebruik van een Search gestuurde navigatie, die flexibiliteit biedt voor het inventariseren van navigatieknooppunten en het efficiënt afhandelen van beveiligingsbeperkingen.

Er zijn andere populaire opties om aangepaste navigatieproviders te bouwen. Raadpleeg Navigatieoplossingen voor SharePoint-portals voor meer informatie over het bouwen van een aangepaste navigatieprovider.

Met behulp van zoeken kunt u gebruikmaken van de indexen die op de achtergrond zijn opgebouwd met behulp van continue verkenning. De zoekresultaten worden opgehaald uit de zoekindex en de resultaten zijn beveiligingsupdates. Dit is over het algemeen sneller dan standaardnavigatieproviders wanneer beveiliging is vereist. Het gebruik van zoeken voor structurele navigatie, met name als u een complexe sitestructuur hebt, zal de laadtijd van pagina's aanzienlijk versnellen. Het belangrijkste voordeel hiervan ten opzichte van beheerde navigatie is dat u profiteert van beveiligingsbeperkingen.

Deze benadering omvat het maken van een aangepaste basispagina en het vervangen van de standaardnavigatiecode door aangepaste HTML. Volg deze procedure die in het volgende voorbeeld wordt beschreven om de navigatiecode in het bestand seattle.htmlte vervangen. In dit voorbeeld opent u het seattle.html bestand en vervangt u het hele element id="DeltaTopNavigation" door aangepaste HTML-code.

Voorbeeld: de standaardnavigatiecode op een basispagina vervangen

  1. Ga naar de pagina Site-instellingen.
  2. Open de galerie met basispagina's door op Basispagina's te klikken.
  3. Hier kunt u door de bibliotheek navigeren en het bestand seattle.masterdownloaden.
  4. Bewerk de code met een teksteditor en verwijder het codeblok in de volgende schermopname.
    Verwijder het weergegeven codeblok.
  5. Verwijder de code tussen de <SharePoint:AjaxDelta id="DeltaTopNavigation"> tags en <\SharePoint:AjaxDelta> en vervang deze door het volgende codefragment:
<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. Vervang de URL in de ankertag voor het laden van afbeeldingen aan het begin door een koppeling naar een afbeelding die in uw siteverzameling wordt geladen. Nadat u de wijzigingen hebt aangebracht, wijzigt u de naam van het bestand en uploadt u het naar de galerie met basispagina's. Hiermee wordt een nieuw .master-bestand gegenereerd.
7. Deze HTML is de basismarkering die wordt ingevuld door de zoekresultaten die worden geretourneerd uit JavaScript-code. U moet de code bewerken om de waarde voor var root = 'URL van siteverzameling' te wijzigen, zoals wordt weergegeven in het volgende codefragment:
var root = "https://spperformance.sharepoint.com/sites/NavigationBySearch";

8. De resultaten worden toegewezen aan de self.nodes-matrix en er wordt een hiërarchie uit de objecten gebouwd met behulp van linq.js het toewijzen van de uitvoer aan een matrix self.hierarchy. Deze matrix is het object dat is gebonden aan de HTML. Dit wordt gedaan in de functie toggleView() door het object zelf door te geven aan de functie ko.applyBinding().
Hierdoor wordt de hiërarchiematrix vervolgens gebonden aan de volgende HTML:
<div data-bind="foreach: hierarchy" class="noindex ms-core-listMenu-horizontalBox">

De gebeurtenis-handlers voor mouseenter en mouseexit worden toegevoegd aan de navigatie op het hoogste niveau om de vervolgkeuzemenu's van de subsite te verwerken die in de addEventsToElements() functie worden uitgevoerd.

In ons complexe navigatievoorbeeld toont een nieuwe paginalading zonder de lokale caching dat de tijd die op de server is besteed, is beperkt van de structurele benchmarknavigatie om een vergelijkbaar resultaat te krijgen als de beheerde navigatiebenadering.

Over het JavaScript-bestand...

Opmerking

Als u aangepast JavaScript gebruikt, moet u ervoor zorgen dat het openbare CDN is ingeschakeld en dat het bestand zich op een CDN-locatie bevindt.

Het volledige JavaScript-bestand ziet er als volgt uit:

//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");

Als u de code wilt samenvatten die hierboven in de jQuery $(document).ready functie wordt weergegeven, wordt er een viewModel object gemaakt en wordt vervolgens de loadNavigationNodes() functie op dat object aangeroepen. Met deze functie wordt de eerder gebouwde navigatiehiërarchie geladen die is opgeslagen in de lokale HTML5-opslag van de clientbrowser of wordt de functie queryRemoteInterface()aangeroepen.

QueryRemoteInterface() bouwt een aanvraag met behulp van de getRequest() functie met de queryparameter die eerder in het script is gedefinieerd en retourneert vervolgens gegevens van de server. Deze gegevens zijn in feite een matrix van alle sites in de siteverzameling die wordt weergegeven als gegevensoverdrachtsobjecten met verschillende eigenschappen.

Deze gegevens worden vervolgens geparseerd in de eerder gedefinieerde SPO.Models.NavigationNode objecten die worden gebruikt Knockout.js om waarneembare eigenschappen te maken voor gebruik door gegevens die de waarden binden in de HTML die we eerder hebben gedefinieerd.

De objecten worden vervolgens in een resultatenmatrix geplaatst. Deze matrix wordt geparseerd in JSON met behulp van knock-out en opgeslagen in de lokale browseropslag voor betere prestaties bij het laden van pagina's in de toekomst.

Voordelen van deze aanpak

Een belangrijk voordeel van deze aanpak is dat door lokale HTML5-opslag te gebruiken, de navigatie lokaal wordt opgeslagen voor de gebruiker wanneer deze de pagina de volgende keer laadt. We krijgen belangrijke prestatieverbeteringen door het gebruik van de zoek-API voor structurele navigatie; Het kost echter enige technische mogelijkheden om deze functionaliteit uit te voeren en aan te passen.

In de voorbeelduitvoering zijn de sites op dezelfde manier geordend als de kant-en-klare structurele navigatie; alfabetische volgorde. Als u van deze volgorde wilt afwijken, zou het ingewikkelder zijn om te ontwikkelen en te onderhouden. Voor deze aanpak moet u ook afwijken van de ondersteunde basispagina's. Als de aangepaste basispagina niet wordt onderhouden, mist uw site updates en verbeteringen die Microsoft aanbrengt in de basispagina's.

De bovenstaande code heeft de volgende afhankelijkheden:

De huidige versie van LinqJS bevat niet de ByHierarchy-methode die in de bovenstaande code wordt gebruikt en breekt de navigatiecode. U kunt dit oplossen door de volgende methode toe te voegen aan het Linq.js-bestand vóór de regel Flatten: function ().

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);
         })
     });
 },

Overzicht van beheerde navigatie in SharePoint Server

Structurele navigatiecache en prestaties