אפשרויות ניווט עבור SharePoint

מאמר זה מתאר אתרי אפשרויות ניווט שבהם פרסום SharePoint זמין ב- SharePoint. הבחירה והתצורה של הניווט משפיעות באופן משמעותי על הביצועים והדרגתיות של אתרים ב- SharePoint. יש להשתמש בתבנית אתר הפרסום של SharePoint רק במידת הצורך עבור פורטל מרכזי, ותכונת הפרסום צריכה להיות זמינה רק באתרים ספציפיים ורק כאשר הדבר נדרש מכיוון שהיא יכולה להשפיע על הביצועים כאשר נעשה בה שימוש שגוי.

הערה

אם אתה משתמש באפשרויות ניווט מודרניות של SharePoint, כגון תפריט מגה, ניווט בהתאם להירארכיית הקשרים או ניווט ברכזת, מאמר זה אינו חל על האתר שלך. ארכיטקטורות אתר מודרניות של SharePoint משתמשות בהירארכיית אתרים שטוחה יותר ובמודל רכזת-חישור. הדבר מאפשר להשיג תרחישים רבים שאינם דורשים שימוש בתכונת הפרסום של SharePoint.

מבט כולל על אפשרויות ניווט

תצורת ספק הניווט יכולה להשפיע באופן משמעותי על הביצועים עבור האתר כולו, ויש לקחת בחשבון כדי לבחור ספק ניווט ותצורה שקנה מידה יעיל עבור הדרישות של אתר SharePoint. קיימים שני ספקי ניווט מורגלים והטמעות ניווט מותאמות אישית.

האפשרות הראשונה, ניווט מבני, היא אפשרות הניווט המומלצת ב- SharePoint עבור אתרי SharePoint קלאסיים, אם תפעיל אחסון במטמון של ניווט מבני עבור האתר שלך. ספק ניווט זה מציג את פריטי הניווט מתחת לאתר הנוכחי, ובאופציונליות את האתר הנוכחי ואת האחים שלו. הוא מספק יכולות נוספות כגון חיתוך אבטחה וספירה של מבנה האתר. אם אחסון במטמון אינו זמין, הדבר ישפיע באופן שלילי על הביצועים ועל המדרגיות, וייתכן שהוא יהיה כפוף לוויסות.

האפשרות השניה, ניווט מנוהל (מטה-נתונים), מייצגת פריטי ניווט באמצעות ערכת מונחים של מטה-נתונים מנוהלים. מומלץ לבטל את חיתוך האבטחה, אלא אם נדרש. הגברת אבטחה זמינה כהגדרה מאובטחת כברירת מחדל עבור ספק ניווט זה; עם זאת, אתרים רבים אינם דורשים את התוקף של הגברת האבטחה מאחר שרכיבים בניווט לעתים קרובות עקביים עבור כל המשתמשים באתר. עם התצורה המומלצת כדי להפוך חיתוך אבטחה ללא זמין, ספק ניווט זה אינו דורש ספירת מבנה אתר והוא מדרגי ביותר עם השפעת ביצועים מקובלת.

בנוסף לספקי הניווט המוכללים, לקוחות רבים יישמו בהצלחה יישומי ניווט מותאמים אישית חלופיים. ראה חיפוש מבוסס-לקוח מבוסס-לקוח במאמר זה.

אפשרויות ניווט של יתרונות וחסרונות של SharePoint

הטבלה הבאה מסכמת את היתרונות והחסרונות של כל אפשרות.

ניווט מבני ניווט מנוהל חיפוש מונחה-מקשים ספק ניווט מותאם אישית
מקצוענים:

קל לתחזוקה
אבטחה חתכו
עדכונים אוטומטיים תוך 24 שעות בעת שינוי התוכן
מקצוענים:

קל לתחזוקה
מקצוענים:

אבטחה חתכו
עדכונים אוטומטיים בעת הוספת אתרים
זמן טעינה מהיר ומבנה ניווט המאוחסן במטמון מקומי
מקצוענים:

מגוון רחב יותר של אפשרויות זמינות
טעינה מהירה בעת שימוש נכון באחסון במטמון
אפשרויות רבות פועלות היטב עם עיצוב דף מגיב
האסירים:

משפיע על הביצועים אם אחסון במטמון אינו זמין
כפוף לוויסות
האסירים:

לא עודכן באופן אוטומטי כדי לשקף את מבנה האתר
משפיע על הביצועים אם חיתוך אבטחה זמין או כאשר מבנה הניווט מורכב
האסירים:

אין יכולת להזמין אתרים בקלות
נדרשת התאמה אישית של הדף הראשי (נדרשים כישורים טכניים)
האסירים:

יש צורך בפיתוח מותאם אישית
נדרש מקור נתונים חיצוני / מטמון מאוחסן, לדוגמה, Azure

האפשרות המתאימה ביותר עבור האתר שלך תלויה בדרישות האתר שלך וביכולות הטכניות שלך. אם אתה מעוניין לספק ניווט קל לקבוע את תצורתו אשר מתעדכן באופן אוטומטי בעת שינוי תוכן, ניווט מבני כאשר אחסון במטמון זמין הוא אפשרות טובה.

הערה

החלת אותו עיקרון כמו אתרי SharePoint מודרניים על-ידי פישוט מבנה האתר הכולל על מבנה חנופה ולא הירארכי משפרת את הביצועים ומפשטת את המעבר לאתרי SharePoint מודרניים. משמעות הדבר היא כי במקום אוסף אתרים יחיד עם מאות אתרים (אתרי משנה), גישה טובה יותר היא להוסיף אוספי אתרים רבים עם אתרי משנה מעטים מאוד (אתרי משנה).

ניתוח ביצועי ניווט ב- SharePoint

הכלי 'אבחון דפים' עבור SharePoint הוא הרחבת דפדפן עבור דפדפני Microsoft Edge ו- Chrome המנתחים הן את דפי אתר הפרסום המודרניים של SharePoint והן את דפי אתר הפרסום הקלאסיים. כלי זה פועל רק עבור SharePoint, ולא ניתן להשתמש בו בדף מערכת של SharePoint.

הכלי יוצר דוח עבור כל דף שנותחו המציג את הביצועים של הדף מול ערכה מוגדרת מראש של כללים ומציג מידע מפורט כאשר התוצאות עבור בדיקה חורגות מערך הבסיס. מנהלי מערכת ומעצבים של SharePoint יכולים להשתמש בכלי כדי לפתור בעיות ביצועים כדי להבטיח שדפים חדשים ממוטבים לפני הפרסום.

SPRequestDuration בפרט הוא הזמן שנדרש ל- SharePoint לעבד את הדף. ניווט כבד (כגון דפים בניווט), הירארכיות אתר מורכבות ואפשרויות תצורה וטופולוגיה אחרות יכולות לתרום באופן דרמטי לכל משך זמן ארוך יותר.

שימוש בניווט מבני ב- SharePoint

זהו הניווט ההוער לשימוש כברירת מחדל, והוא הפתרון ההושר ביותר. הוא אינו דורש התאמה אישית ומשתמש לא טכני יכול גם להוסיף בקלות פריטים, להסתיר פריטים ולנהל את הניווט בדף ההגדרות. אנו ממליצים להפעיל אחסון במטמון, אחרת קיים תיקון ביצועים יקר.

כיצד ליישם אחסון במטמון של ניווט מבני

תחת ניווט מראה>ותחושה של> הגדרותאתר, באפשרותך לאמת אם ניווט מבני נבחר עבור ניווט כללי או ניווט נוכחי. בחירה באפשרות הצג דפים תהיה השפעה שלילית על הביצועים.

ניווט מבני כאשר האפשרות 'הצג אתרי משנה' נבחרה.

ניתן להפוך אחסון במטמון לזמין או ללא זמין ברמת אוסף האתרים וברמת האתר, והוא זמין עבור שניהם כברירת מחדל. כדי להפוך לזמין ברמת אוסף האתרים, תחת ניווט>> באוסף אתרים של ניהול אוסף אתרים של הגדרותאתר, סמן את התיבה הפוך אחסון במטמון לזמין.

הפוך אחסון במטמון לזמין ברמת אוסף האתרים.

כדי להפוך לזמין ברמת האתר, תחת ניווט בהגדרות>האתר, סמן את התיבה עבור הפוך אחסון במטמון לזמין.

הפוך אחסון במטמון לזמין ברמת האתר.

שימוש בניווט מנוהל ומטה-נתונים ב- SharePoint

ניווט מנוהל הוא אפשרות נוספת מוכן לשימוש שניתן להשתמש בה כדי ליצור מחדש את רוב הפונקציונליות של ניווט מבני. ניתן להגדיר מטה-נתונים מנוהלים כך שחיתוך אבטחה יהיה זמין או לא זמין. כאשר נקבעה תצורה עם חיתוך אבטחה לא זמין, הניווט המנוהל יעיל למדי מאחר שהוא טוען את כל קישורי הניווט עם מספר קבוע של קריאות שרת. עם זאת, הפיכת הגברת אבטחה לזמינה תנצל חלק מיתרונות הביצועים של ניווט מנוהל.

אם עליך להפוך את הגברת האבטחה לזמינה, אנו ממליצים לך:

  • עדכן את כל קישורי כתובת ה- URL הידידותית לקישורים פשוטים
  • הוסף צמתי חיתוך אבטחה נדרשים ככתובות URL ידידותיות
  • הגבלת מספר פריטי הניווט לעומק של לא יותר מ- 100 ולא יותר משלוש רמות

אתרים רבים אינם דורשים הגברת אבטחה, מפני שמבנה הניווט עקבי לעתים קרובות עבור כל המשתמשים באתר. אם חיתוך אבטחה אינו זמין ונוסף קישור לניווט שלא לכל המשתמשים יש גישה אליו, הקישור עדיין יוצג, אך יוביל להודעה שהגישה נדחתה. אין סיכון לגישה בלתי מגגת לתוכן.

כיצד ליישם ניווט מנוהל והתוצאות

קיימים כמה מאמרים בנושא Microsoft Learn אודות פרטי הניווט המנוהל. לדוגמה, ראה מבט כולל על ניווט מנוהל ב- SharePoint Server.

כדי ליישם ניווט מנוהל, עליך להגדיר מונחים עם כתובות URL התואמות למבנה הניווט של האתר. הניווט המנוהל יכול אף להיות מובנה באופן ידני כדי להחליף ניווט מבני במקרים רבים. לדוגמה:

מבנה אתר SharePoint.)

שימוש חיפוש מבוסס-לקוח מבוסס-לקוח

מחלקה נפוצה אחת של יישומי ניווט מותאמים אישית מאמצת דפוסי עיצוב המעובדים על-ידי לקוח, המאחסנים מטמון מקומי של צמתי ניווט.

לספקי ניווט אלה יש כמה יתרונות עיקריים:

  • בדרך כלל הם פועלים היטב עם עיצובי עמודים מגיבים.
  • הן מדרגיות וביצועיות במיוחד מכיוון שהן יכולות לעבד ללא עלות משאב (וריענון ברקע לאחר פרק זמן קצוב).
  • ספקי ניווט אלה יכולים לאחזר נתוני ניווט באמצעות אסטרטגיות שונות, החל בתצורות סטטיות פשוטות וספקי נתונים דינאמיים שונים.

דוגמה לספק נתונים היא להשתמש בניווט מונחה-חיפוש, המאפשר גמישות בספירה של צמתי ניווט וטיפול בחיתוך אבטחה ביעילות.

קיימות אפשרויות פופולריות אחרות לבניית ספקי ניווט מותאמים אישית. סקור פתרונות ניווט עבור פורטלי SharePoint לקבלת הדרכה נוספת לגבי בניית ספק ניווט מותאם אישית.

באמצעות חיפוש באפשרותך למנף את האינדקסים המוכללים ברקע באמצעות סריקה רציפה. תוצאות החיפוש יתבצעו מאינדקס החיפוש והתוצאות ייחתכו באבטחה. בדרך כלל, מהירות זו מהירה יותר מספקי ניווט מוערם כאשר נדרשת הגברת אבטחה. שימוש בחיפוש אחר ניווט מבני, במיוחד אם יש לך מבנה אתר מורכב, יזרז את טעינת הדפים במידה ניכרת. היתרון העיקרי של אפשרות זו בניווט מנוהל הוא יתרונות של חיתוך אבטחה.

גישה זו כרוכה ביצירת דף בסיס מותאם אישית והחלפה של קוד הניווט המוטבע ב- HTML מותאם אישית. בצע הליך זה המתואר בדוגמה הבאה כדי להחליף את קוד הניווט בקובץ seattle.html. בדוגמה זו, תפתח את הקובץ ותחליף seattle.html את הרכיב כולו בקוד id="DeltaTopNavigation" HTML מותאם אישית.

לדוגמה: החלפת קוד הניווט 'מחוץ לתיבה' בדף ראשי

  1. נווט לדף הגדרות האתר.
  2. פתח את גלריית הדפים הראשיים על-ידי לחיצה על דפים ראשיים.
  3. מכאן תוכל לנווט בספריה ולהוריד את הקובץ seattle.master.
  4. ערוך את הקוד באמצעות עורך טקסט ומחק את בלוק הקוד בצילום המסך הבא.
    מחק את בלוק הקוד המוצג.
  5. הסר את הקוד בין התגיות <SharePoint:AjaxDelta id="DeltaTopNavigation"><\SharePoint:AjaxDelta> לבין והחלף אותו בסעיף הבא:
<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. החלף את כתובת ה- URL של תג עוגן התמונה הטעינה בהתחלה, בקישור לתמונת טעינה באוסף האתרים שלך. לאחר ביצוע השינויים, שנה את שם הקובץ ולאחר מכן העלה אותו בגלריית הדפים הראשיים. פעולה זו יוצרת קובץ .master חדש.
7. HTML זה הוא הסימון הבסיסי המאוכלס בתוצאות החיפוש המוחזרים מקוד JavaScript. יהיה עליך לערוך את הקוד כדי לשנות את הערך עבור בסיס var = "כתובת URL של אוסף אתרים" כפי שצוין במקטע הבא:
var root = "https://spperformance.sharepoint.com/sites/NavigationBySearch";

8. התוצאות מוקצות למערך self.nodes והירארכיה בנויה מתוך האובייקטים באמצעות linq.js הקצאת הפלט ל- self.hierarchy של מערך. מערך זה הוא האובייקט המאוגד ל- HTML. פעולה זו מתבצעת בפונקציה toggleView() על-ידי העברת האובייקט העצמי לפונקציה ko.applyBinding().
לאחר מכן, פעולה זו גורמת לאגד את מערך ההירארכיה ל- HTML הבא:
<div data-bind="foreach: hierarchy" class="noindex ms-core-listMenu-horizontalBox">

המטפלים באירועים עבור mouseenter ונוספים mouseexit לניווט ברמה העליונה כדי לטפל בתפריטים הנפתחים של אתר המשנה הזמינים בפונקציה addEventsToElements() .

בדוגמה המורכבת שלנו לניווט, עומס דף חדש ללא האחסון במטמון המקומי מציג את הזמן שהושקע בשרת נחתך מהניווט המבני של בחינת ביצועים כדי לקבל תוצאה דומה כגישה של הניווט המנוהל.

אודות קובץ JavaScript...

הערה

אם אתה משתמש ב- JavaScript מותאם אישית, ודא ש- CDN ציבורי זמין והקובץ נמצא במיקום CDN.

קובץ ה- JavaScript כולו הוא כדלקמן:

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

כדי לסכם את הקוד המוצג לעיל בפונקציה jQuery $(document).ready , viewModel object נוצר ולאחר מכן loadNavigationNodes() מתבצעת קריאה לפונקציה באובייקט זה. פונקציה זו טוען את הירארכיית הניווט שנבנתה בעבר המאוחסנת באחסון המקומי של HTML5 של דפדפן הלקוח או שהיא קוראת לפונקציה queryRemoteInterface().

QueryRemoteInterface() בונה בקשה באמצעות הפונקציה עם getRequest() פרמטר השאילתה שהוגדר קודם לכן בקובץ ה- Script ולאחר מכן מחזיר נתונים מהשרת. נתונים אלה הם למעשה מערך של כל האתרים באוסף האתרים המיוצגים אובייקטים של העברת נתונים עם מאפיינים שונים.

לאחר מכן, נתונים SPO.Models.NavigationNodeKnockout.js אלה ינותחו לאובייקטים שהוגדרו קודם לכן, אשר משתמשים בהם כדי ליצור מאפיינים ניתנים להצגה לשימוש על-ידי איגוד הנתונים של הערכים ב- HTML שהגדרנו קודם לכן.

לאחר מכן האובייקטים מציבים במערך תוצאות. מערך זה לנתח את מבנה הטקסט ב- JSON באמצעות Knockout ולאחסן אותו באחסון בדפדפן המקומי כדי לשפר את הביצועים בטעינת עמודים עתידית.

היתרונות של גישה זו

אחד היתרונות העיקריים של גישה זו הוא ששימוש באחסון מקומי של HTML5, הניווט מאוחסן באופן מקומי עבור המשתמש בפעם הבאה שהוא טוען את הדף. אנו מקבלים שיפורי ביצועים משמעותיים מהשימוש ב- API של החיפוש עבור ניווט מבני; עם זאת, נדרשת יכולת טכנית מסוימת כדי לבצע ולהתאים אישית פונקציונליות זו.

בהטמעה לדוגמה, האתרים מסודרים באותו אופן כמו הניווט המבני המוכלל; סדר אלפביתי. אם אתה רוצה לסטות מההוראה, זה יהיה מסובך יותר לפתח ולתחזק. כמו כן, גישה זו דורשת ממך לסטות מעמודי הבסיס הנתמכים. אם הדף הראשי המותאם אישית אינו נשמר, האתר שלך יחמיץ עדכונים ושיפורים ש- Microsoft מבצעת בדפים הראשיים.

הקוד לעיל כולל את יחסי התלות הבאים:

הגירסה הנוכחית של LinqJS אינה מכילה את פעולת השירות ByHierarchy המשמשת בקוד לעיל והיא ת לנתק את קוד הניווט. כדי לתקן זאת, הוסף את השיטה הבאה Linq.js הקובץ לפני השורה 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);
         })
     });
 },

מבט כולל על ניווט מנוהל ב- SharePoint Server

אחסון במטמון וביצועים בניווט מבני