Navigasjonsalternativer for SharePoint

Denne artikkelen beskriver navigasjonsalternativer med SharePoint-publisering aktivert i SharePoint. Valget og konfigurasjonen av navigasjonen påvirker ytelsen og skalerbarheten til nettsteder i SharePoint betydelig. Malen for SharePoint-publiseringsnettsted bør bare brukes hvis det er nødvendig for en sentralisert portal, og publiseringsfunksjonen bør bare aktiveres på bestemte nettsteder, og bare når det er nødvendig, da den kan påvirke ytelsen når den brukes feil.

Obs!

Hvis du bruker moderne navigasjonsalternativer for SharePoint, for eksempel megameny, gjennomgripende navigasjon eller hubnavigasjon, gjelder ikke denne artikkelen for området. Moderne SharePoint-områdearkitekturer drar nytte av et mer flatt områdehierarki og en hub-og-eik-modell. Dette gjør at mange scenarioer kan oppnås som IKKE krever bruk av SharePoint-publiseringsfunksjonen.

Oversikt over navigasjonsalternativer

Konfigurasjon av navigasjonsleverandør kan ha betydelig innvirkning på ytelsen for hele nettstedet, og det må tas nøye hensyn til å velge en navigasjonsleverandør og konfigurasjon som skaleres effektivt for kravene til et SharePoint-nettsted. Det finnes to forhåndsdefinerte navigasjonsleverandører, i tillegg til egendefinerte navigasjonsimplementeringer.

Det første alternativet, strukturell navigasjon, er det anbefalte navigasjonsalternativet i SharePoint for klassiske SharePoint-områder , hvis du aktiverer strukturell navigasjonsbufring for området. Denne navigasjonsleverandøren viser navigasjonselementene under gjeldende område, og eventuelt gjeldende område og tilhørende sideordnede. Den gir flere funksjoner som sikkerhetstrimming og opplisting av områdestruktur. Hvis hurtigbufring er deaktivert, vil dette påvirke ytelsen og skalerbarheten negativt, og kan være underlagt begrensning.

Det andre alternativet, administrert (metadata)-navigasjon, representerer navigasjonselementer ved hjelp av et termsett for forvaltede metadata. Vi anbefaler at sikkerhetstrimming deaktiveres med mindre det er nødvendig. Sikkerhetstrimming er aktivert som en sikker standardinnstilling for denne navigasjonsleverandøren. Mange nettsteder krever imidlertid ikke sikkerhetstrimming fordi navigasjonselementer ofte er konsekvente for alle brukere av nettstedet. Med den anbefalte konfigurasjonen for å deaktivere sikkerhetstrimming krever ikke denne navigasjonsleverandøren opplisting av områdestrukturen og er svært skalerbar med akseptabel ytelsesinnvirkning.

I tillegg til de forhåndsdefinerte navigasjonsleverandørene har mange kunder implementert alternative egendefinerte navigasjonsimplementeringer. Se Søk-drevet skripting på klientsiden i denne artikkelen.

Fordeler og ulemper med navigasjonsalternativer i SharePoint

Tabellen nedenfor oppsummerer fordelene og ulempene ved hvert alternativ.

Strukturell navigasjon Administrert navigasjon Søk-drevet navigasjon Leverandør av egendefinert navigering
Proffene:

Enkelt å vedlikeholde
Sikkerhet trimmet
Oppdateres automatisk innen 24 timer når innholdet endres
Proffene:

Enkelt å vedlikeholde
Proffene:

Sikkerhet trimmet
Oppdateres automatisk etter hvert som områder legges til
Hurtiglastingstid og lokalt bufret navigasjonsstruktur
Proffene:

Bredere utvalg av tilgjengelige alternativer
Rask innlasting når hurtigbufring brukes på riktig måte
Mange alternativer fungerer bra med responsiv sideutforming
Ulemper:

Påvirker ytelsen hvis hurtigbufring er deaktivert
Underlagt begrensning
Ulemper:

Oppdateres ikke automatisk for å gjenspeile områdestrukturen
Påvirker ytelsen hvis sikkerhetstrimming er aktivert eller når navigasjonsstrukturen er kompleks
Ulemper:

Ingen mulighet til enkelt å bestille nettsteder
Krever tilpassing av hoveddokumentet (tekniske ferdigheter kreves)
Ulemper:

Egendefinert utvikling er nødvendig
Ekstern datakilde / lagret hurtigbuffer er nødvendig, for eksempel Azure

Det mest passende alternativet for nettstedet avhenger av kravene til nettstedet og den tekniske funksjonaliteten. Hvis du vil ha en brukervennlig navigasjonsleverandør som oppdateres automatisk når innholdet endres, er strukturell navigasjon med hurtigbufring aktivert et godt alternativ.

Obs!

Bruk av det samme prinsippet som moderne SharePoint-nettsteder ved å forenkle den generelle nettstedsstrukturen til en flatere, ikke-hierarkisk struktur forbedrer ytelsen og forenkler flytting til moderne SharePoint-nettsteder. Dette betyr at i stedet for å ha én enkelt nettstedssamling med hundrevis av nettsteder (sekundære webområder), er en bedre fremgangsmåte å ha mange nettstedssamlinger med svært få sekundære nettsteder (sekundære webområder).

Analysere navigasjonsytelsen i SharePoint

Verktøyet Sidediagnose for SharePoint er en nettleserutvidelse for Microsoft Edge- og Chrome-nettlesere som analyserer både den moderne SharePoint-portalen og klassiske publiseringsnettstedssider. Dette verktøyet fungerer bare for SharePoint, og kan ikke brukes på en SharePoint-systemside.

Verktøyet genererer en rapport for hver analyserte side som viser hvordan siden yter mot et forhåndsdefinert sett med regler, og viser detaljert informasjon når resultatene for en test faller utenfor grunnlinjeverdien. SharePoint-administratorer og -utformere kan bruke verktøyet til å feilsøke ytelsesproblemer for å sikre at nye sider er optimalisert før publisering.

SpRequestDuration er spesielt tiden det tar for SharePoint å behandle siden. Tung navigasjon (for eksempel inkludert sider i navigasjon), komplekse områdehierarkier og andre alternativer for konfigurasjon og topologi kan alle bidra dramatisk til lengre varighet.

Bruke strukturell navigasjon i SharePoint

Dette er den forhåndsdefinerte navigasjonen som brukes som standard, og er den enkleste løsningen. Det krever ingen tilpassing, og en ikke-teknisk bruker kan også enkelt legge til elementer, skjule elementer og administrere navigasjonen fra innstillingssiden. Vi anbefaler at du aktiverer hurtigbufring, ellers er det en dyr ytelsesavveining.

Slik implementerer du strukturell navigasjonshurtigbufring

Du kan validere om strukturell navigasjon er valgt for enten global navigasjon eller gjeldendenavigasjon, underUtseende og> funksjonalitet for områdeinnstillinger>. Hvis du velger Vis sider , påvirkes ytelsen negativt.

Strukturell navigasjon med Vis sekundære områder valgt.

Hurtigbufring kan aktiveres eller deaktiveres på områdesamlingsnivå og på områdenivå, og er aktivert for begge som standard. Hvis du vil aktivere på områdesamlingsnivå, merker du av for Aktiver hurtigbufring under Områdesamling>> for administrasjon avområdesamling for områdesamling.

Aktiver hurtigbufring på områdesamlingsnivå.

Hvis du vil aktivere på områdenivå, merker du av for Aktiver hurtigbufring underNavigasjon for områdeinnstillinger>.

Aktiver hurtigbufring på områdenivå.

Bruke administrert navigasjon og metadata i SharePoint

Administrert navigasjon er et annet forhåndsdefinert alternativ som du kan bruke til å gjenopprette mesteparten av samme funksjonalitet som strukturell navigasjon. Forvaltede metadata kan konfigureres slik at sikkerhetstrimming er aktivert eller deaktivert. Når konfigurert med sikkerhetstrimming deaktivert, er administrert navigasjon ganske effektivt ettersom den laster inn alle navigasjonskoblingene med et konstant antall serverkall. Aktivering av sikkerhetstrimming opphever imidlertid noen av ytelsesfordelene ved administrert navigasjon.

Hvis du må aktivere sikkerhetstrimming, anbefaler vi at du:

  • Oppdater alle egendefinerte URL-koblinger til enkle koblinger
  • Legg til nødvendige sikkerhetstrimmingsnoder som egendefinerte URL-adresser
  • Begrens antallet navigasjonselementer til ikke mer enn 100 og ikke mer enn tre nivåer dypt

Mange nettsteder krever ikke sikkerhetstrimming, siden navigasjonsstrukturen ofte er konsekvent for alle brukere av nettstedet. Hvis sikkerhetstrimming er deaktivert og en kobling legges til i navigasjonen som ikke alle brukere har tilgang til, vil koblingen fortsatt vises, men vil føre til en melding om at tilgang nektes. Det er ingen risiko for utilsiktet tilgang til innholdet.

Slik implementerer du administrert navigasjon og resultatene

Det finnes flere artikler i Microsoft Learn om detaljene for administrert navigasjon. Se for eksempel oversikt over administrert navigasjon i SharePoint Server.

Hvis du vil implementere administrert navigasjon, konfigurerer du termer med nettadresser som tilsvarer navigasjonsstrukturen på området. Administrert navigasjon kan også manuelt kurateres for å erstatte strukturell navigasjon i mange tilfeller. Eksempel:

Områdestruktur for SharePoint.)

Bruke Søk-drevet skripting på klientsiden

Én vanlig klasse med egendefinerte navigasjonsimplementeringer omfatter klientgjengivede utformingsmønstre som lagrer en lokal buffer med navigasjonsnoder.

Disse navigasjonsleverandørene har et par viktige fordeler:

  • De fungerer vanligvis bra med responsive sideutforminger.
  • De er svært skalerbare og ytefulle fordi de kan gjengis uten ressurskostnader (og oppdatere i bakgrunnen etter et tidsavbrudd).
  • Disse navigasjonsleverandørene kan hente navigasjonsdata ved hjelp av ulike strategier, alt fra enkle statiske konfigurasjoner til ulike dynamiske dataleverandører.

Et eksempel på en dataleverandør er å bruke en Søk-drevet navigasjon, som gir fleksibilitet til å nummerere navigasjonsnoder og håndtere sikkerhetstrimming effektivt.

Det finnes andre populære alternativer for å bygge egendefinerte navigasjonsleverandører. Se gjennom navigasjonsløsninger for SharePoint-portaler for ytterligere veiledning om hvordan du bygger en egendefinert navigasjonsleverandør.

Ved hjelp av søk kan du dra nytte av indeksene som er innebygd i bakgrunnen ved hjelp av kontinuerlig kravlesøk. Søkeresultatene hentes fra søkeindeksen, og resultatene er sikkerhetstrimmet. Dette er vanligvis raskere enn forhåndsdefinerte navigasjonsleverandører når sikkerhetstrimming er nødvendig. Hvis du bruker søk etter strukturell navigasjon, spesielt hvis du har en kompleks områdestruktur, vil det øke hastigheten på sidelastingstiden betraktelig. Den største fordelen med dette over administrert navigasjon er at du drar nytte av sikkerhetstrimming.

Denne fremgangsmåten innebærer å opprette et egendefinert hoveddokument og erstatte den forhåndsdefinerte navigasjonskoden med egendefinert HTML. Følg denne fremgangsmåten som er beskrevet i eksemplet nedenfor for å erstatte navigasjonskoden i filen seattle.html. I dette eksemplet åpner seattle.html du filen og erstatter hele elementet id="DeltaTopNavigation" med egendefinert HTML-kode.

Eksempel: Erstatte den forhåndsdefinerte navigasjonskoden i et hoveddokument

  1. Gå til siden Innstillinger for område.
  2. Åpne galleriet for hoveddokumenter ved å klikke Hoveddokumenter.
  3. Herfra kan du navigere gjennom biblioteket og laste ned filen seattle.master.
  4. Rediger koden ved hjelp av et tekstredigeringsprogram, og slett kodeblokken i følgende skjermbilde.
    Slett kodeblokken som vises.
  5. Fjern koden mellom <SharePoint:AjaxDelta id="DeltaTopNavigation"> kodene og <\SharePoint:AjaxDelta> og erstatt den med følgende kodesnutt:
<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. Erstatt nettadressen i den innlastende bildeankerkoden i begynnelsen, med en kobling til et innlastende bilde i nettstedssamlingen. Når du har gjort endringene, kan du gi filen et nytt navn og deretter laste den opp til galleriet for hoveddokumenter. Dette genererer en ny MASTER-fil.
7. Denne HTML-koden er den grunnleggende koden som fylles ut av søkeresultatene som returneres fra JavaScript-kode. Du må redigere koden for å endre verdien for var root = "URL-adresse for områdesamling" som vist i følgende kodesnutt:
var root = "https://spperformance.sharepoint.com/sites/NavigationBySearch";

8. Resultatene tilordnes self.nodes-matrisen, og et hierarki er bygget ut av objektene ved hjelp av linq.js tilordning av utdataene til en matrise self.hierarchy. Denne matrisen er objektet som er bundet til HTML-koden. Dette gjøres i toggleView()-funksjonen ved å sende selvobjektet til ko.applyBinding()-funksjonen.
Dette fører deretter til at hierarkimatrisen blir bundet til følgende HTML:
<div data-bind="foreach: hierarchy" class="noindex ms-core-listMenu-horizontalBox">

Hendelsesbehandlingene for og mouseexit legges til i navigasjonen på øverste nivå for mouseenter å håndtere rullegardinmenyene for sekundære områder som gjøres i addEventsToElements() funksjonen.

I vårt komplekse navigeringseksempel viser en ny sidelasting uten lokal hurtigbufring tiden som brukes på serveren, blitt kuttet ned fra den strukturelle referansenavigasjonen for å få et lignende resultat som den administrerte navigasjonstilnærmingen.

Om JavaScript-filen ...

Obs!

Hvis du bruker egendefinert JavaScript, må du kontrollere at offentlig CDN er aktivert og at filen er på en CDN-plassering.

Hele JavaScript-filen er som følger:

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

Hvis du vil oppsummere koden som vises ovenfor i jQuery $(document).ready funksjonen, er det opprettet og viewModel object deretter loadNavigationNodes() kalles funksjonen på objektet. Denne funksjonen laster enten inn det tidligere bygde navigasjonshierarkiet som er lagret i den lokale HTML5-lagringsplassen i klientleseren, eller kaller funksjonen queryRemoteInterface().

QueryRemoteInterface() bygger en forespørsel ved hjelp av getRequest() funksjonen med spørringsparameteren som er definert tidligere i skriptet, og returnerer deretter data fra serveren. Disse dataene er i hovedsak en matrise av alle områdene i områdesamlingen representert som dataoverføringsobjekter med ulike egenskaper.

Disse dataene analyseres deretter i de tidligere definerte SPO.Models.NavigationNode objektene som brukes Knockout.js til å opprette observerbare egenskaper for bruk av data som binder verdiene inn i HTML-koden som vi definerte tidligere.

Objektene plasseres deretter i en resultatmatrise. Denne matrisen analyseres i JSON ved hjelp av Knockout og lagres i den lokale nettleserlagringen for bedre ytelse ved fremtidige sideinnlastinger.

Fordeler med denne tilnærmingen

Én av de viktigste fordelene med denne fremgangsmåten er at navigasjonen lagres lokalt for brukeren neste gang de laster inn siden ved hjelp av HTML5 lokal lagring. Vi får store ytelsesforbedringer ved bruk av søke-API-en for strukturell navigasjon. Det kreves imidlertid noen tekniske funksjoner for å utføre og tilpasse denne funksjonaliteten.

I eksempelimplementeringen er områdene ordnet på samme måte som den innebygde strukturelle navigasjonen. alfabetisk rekkefølge. Hvis du ønsker å avvike fra denne ordren, ville det være mer komplisert å utvikle og vedlikeholde. Denne fremgangsmåten krever også at du avviker fra hoveddokumentene som støttes. Hvis det egendefinerte hoveddokumentet ikke opprettholdes, går nettstedet glipp av oppdateringer og forbedringer som Microsoft gjør i hoveddokumentene.

Koden ovenfor har følgende avhengigheter:

Gjeldende versjon av LinqJS inneholder ikke ByHierarchy-metoden som brukes i koden ovenfor, og vil bryte navigasjonskoden. Du kan løse dette ved å legge til følgende metode i den Linq.js filen før linjen 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);
         })
     });
 },

Oversikt over administrert navigasjon i SharePoint Server

Strukturell hurtigbufring og ytelse for navigasjon