SharePoint Online 的導覽選項

重要:  本文係由機器翻譯而成,請參閱免責聲明。本文的英文版本請見這裡,以供參考。

本文將說明如何使用結構式導覽和搜尋導向導覽,SharePoint Online 的改善頁面載入時間。

全域導覽建置結構式導覽所需的查詢可以讓您載入更多速度緩慢並且在 SharePoint Online 的頁面。這是因為每個這些查詢傳送到 SQL server 的另一個要求。每個網站,您的子網站的更多要求到 SQL server。此問題也會影響的主版頁面。這表示全域導覽也會受到影響。

部分 SharePoint 網站需要大型及複雜的結構。使用的方塊出結構式導覽,查詢所使用的內容,可能會變得很慢頁面載入時間,因為多重網站層級。每個層級的子網站也會建立另一個查詢。

有兩個主要的方塊出導覽選項,在 SharePoint 中,以及第三個,自訂的搜尋導向的方法。每個選項都有優缺點下表所述。

結構化的功能

受管理的導覽

搜尋導向導覽

專業人員:

  • 容易設定

  • 安全性調整

  • 新增網站時,自動更新

專業人員:

  • 若要維持簡單

專業人員:

  • 安全性調整

  • 新增網站時,自動更新

  • 快速的載入時間和本機快取導覽結構

缺點:

  • 可以不佳執行複雜的網站結構

缺點:

  • 不會自動更新,以反映網站結構

缺點:

  • 沒有輕鬆順序網站的能力

  • 需要自訂主版頁面 (技術必要)

如果您有許多子網站的網站,您使用結構式導覽,可能會拖慢頁面載入往下大幅。在您網站的需求,然後在您的技術功能取決於您的網站最適當的選項。如果您習慣使用自訂的主版頁面,若要維持的 SharePoint online 中預設主版頁面可能會發生變更組織中有一些功能,搜尋導向] 選項會產生最佳的使用者體驗。如果您想要的方塊出結構式導覽和搜尋之間的簡單折衷,受管理的導覽就會是很好的選項。受管理的導覽選項可以透過維護設定,不包含的程式碼自訂檔案,和其會更快比的方塊出結構式導覽。

另一種是重建現有的網站,並減少的導覽項目和所需的子網站。這是因為結構式導覽會執行,以及,只要網站結構和導覽並不太複雜。

本文將比較範例網站集合中的各種方法。範例網站集合有 11 的子網站,而且每一個子網站有至少四個額外的子網站。

螢幕擷取畫面顯示網站與子網站

在 SharePoint Online 中使用結構式導覽

這是預設使用的方塊出導覽,最乾淨的簡單且適當的解決方案在大多數情況下。除非有多個子網站或子網站的階層數的複雜結構,以及執行結構式導覽。這種方法的優點是,為安全性修剪,加入新的網站時,自動更新並不需要任何自訂主版頁面。非技術使用者可以輕鬆新增項目、 隱藏的項目,並從 [設定] 頁面中管理導覽。

開啟 SharePoint Online 中的結構式導覽

若要說明如何在標準的 SharePoint Online 方案,使用結構式導覽] 和 [顯示效能子選項開啟。以下是螢幕擷取畫面設定可在 [網站設定] 頁面上找到 >功能

螢幕擷取畫面顯示子網站

在 SharePoint Online 中的分析結構式導覽效能

若要分析 SharePoint 頁面的效能,請在 Internet Explorer 中使用 F12 開發工具 [網路] 索引標籤。

螢幕擷取畫面顯示 F12 開發工具 [網路] 索引標籤

[網路] 索引標籤上按一下正在載入.aspx 頁面上,然後按一下 [詳細資料] 索引標籤上。

螢幕擷取畫面顯示 [詳細資料] 索引標籤

按一下 [回應標頭]。

[詳細資料] 索引標籤的螢幕擷取畫面

SharePoint 會傳回其回應標頭中的一些實用的診斷資訊。最適合其中一項是SPRequestDuration   的值,以毫秒為單位的時間長度要求原本在伺服器上的程序。

以下螢幕擷取畫面顯示子網站中未核取的結構式導覽。這表示在全域導覽中是只有網站集合連結:

螢幕擷取畫面顯示載入時間為要求期間

SPRequestDuration   索引鍵的 245 毫秒的值。這代表傳回要求所花的時間。由於網站上有一個導覽項目,這是很好的 SharePoint Online 執行方式不經常導覽基準。下一步的螢幕擷取畫面顯示如何新增子網站中會影響此按鍵。

螢幕擷取畫面顯示要求期間 2502 毫秒

新增子網站有大幅會增加,以傳回頁面要求的時間。

使用一般的結構化的功能的優點是,您可以輕鬆地組織順序隱藏網站、 新增頁面、 結果安全性修剪,而您不偏離使用 SharePoint Online 中支援的主版頁面。如果您謹慎結構您的網站,您的網站集合最小化的子網站數量然後結構式導覽執行也。

在 SharePoint Online 中使用受管理的導覽和受管理的中繼資料

受管理的導覽是功能的另一個--現成的選項,您可以使用重新建立相同的排序與結構式導覽。

使用受管理的中繼資料的優點是快速擷取資料和查詢中使用的內容,來建立網站功能。雖然速度有任何安全性調整結果,因此如果使用者沒有存取特定的網站,請連結仍會顯示,但會導致錯誤訊息。

如何實作受管理的導覽和結果   

有幾篇文章 TechNet 上的 [受管理的導覽,詳細資訊,例如,請參閱SharePoint Server 2013 中受管理的導覽概觀

才能實作受管理的導覽,您需要有儲存管理員權限的字詞。設定以符合結構的網站集合的 Url,受管理的導覽,可以用來取代結構式導覽中。例如:

子網站1 範例的螢幕擷取畫面

下列範例會顯示使用受管理的導覽複雜導覽的效能。

SPRequestDuration 範例的螢幕擷取畫面

一致的方式使用受管理的導覽,皆可改善效能的查詢結構式導覽方法比較的內容。

使用搜尋導向用戶端指令碼

您可以使用搜尋運用背景使用連續編目 」 會建立索引。這表示沒有經常內容查詢。搜尋結果會提取從搜尋索引,結果安全性調整。這是較快,使用一般內容的查詢。使用搜尋結構式導覽,尤其是如果您有複雜的網站的結構,會加速大幅載入時間的頁面。這對受管理的導覽的主要優點是,您可以從安全性調整。

此方法需要建立的自訂主版頁面,並使用自訂的 HTML 取代的方塊出導覽程式碼。請遵循此程序來取代檔案 seattle.html 中的功能。

在此範例中,您將會開啟 seattle.html 檔案,並取代整個項目id = 」 之 DeltaTopNavigation 」與自訂的 HTML 程式碼。

範例: 若要取代的方塊出導覽中的程式碼的主版頁面

  1. 瀏覽至 [網站設定] 頁面。

  2. 按一下 [主版頁面,以開啟主版頁面圖庫。

  3. 從這裡開始,您可以瀏覽文件庫,並下載檔案seattle.master

  4. 編輯使用文字編輯器的程式碼,然後刪除以下的螢幕擷取畫面中的程式碼區塊。

    要刪除之 DeltaTopNavigation 程式碼的螢幕擷取畫面
  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">
                    <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 }">
                        <span aria-haspopup="true" class="additional-background ms-navedit-flyoutArrow dynamic-children">
                            <span class="menu-item-text" data-bind="text: item.Title">
                            </span>
                        </span>
                    </a>
                    <ul id="menu" data-bind="foreach: children; visible: children.length>0" class="dynamic" >
                        <li class="dynamic">
                            <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>
                </li>
            </ul>
        </div>
    </div>
  6. 取代中載入的 URL 圖像錨點標記開頭與網站集合中的載入圖像的連結。您所做變更之後,重新命名檔案,然後再上傳至主版頁面圖庫。這會產生新.master] 檔案。

  7. 此 HTML 是從 JavaScript 程式碼,傳回搜尋結果將填入基本標記。您將需要編輯下列程式碼,變更var root = “site collection URL的值,如下列程式碼片段所示:

    var root = “https://spperformance.sharepoint.com/sites/NavigationBySearch”;

    整個 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 firefix 
        // 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.dynamic-children").mouseover(function () {
            var position = $(this).position();
            $(this).find("ul").css({ width: 125, left: position.left + 10, top: 50 });
    
        })
            .mouseout(function () {
                $(this).find("ul").css({ width: 0, left: -99999, top: 0 });
            });
    }
    
    _spBodyOnLoadFunctionNames.push("InitCustomNav");
    

    摘要總結viewModel物件,建立,而且loadNavigationNodes()然後函數在該物件,顯示上方 jQuery $(document).ready函數中的程式碼稱為。此函數 [載入 HTML5 本機儲存空間的用戶端瀏覽器中儲存先前建立的導覽階層或呼叫函數queryRemoteInterface()。

    QueryRemoteInterface()建置getRequest()函數使用較舊版本中的指令碼定義的查詢參數的要求,然後從伺服器傳回的資料。此資料是基本上陣列的各種內容的資料傳輸物件以表示的網站集合中的所有網站。此資料然後剖析到用它來建立顯著屬性以用於 Knockout.js 先前已定義之的SPO.Models.NavigationNode物件的資料繫結值,我們先前定義的 html。結果陣列被然後放置的物件。此陣列將使用油墨廓清 JSON 剖析,而儲存於本機瀏覽器儲存空間,以在未來的頁面載入改善效能。

  8. 接下來,結果會指派給self.nodes陣列,而不使用 linq.js 將輸出指派給陣列self.heirarchy物件內建階層。此陣列是繫結到 HTML 的物件。這是toggleView()函數中自我的物件傳遞給ko.applyBinding()函數。然後,這會使繫結至下列 HTML 階層陣列:

    <div data-bind=”foreach: hierarchy” class=”noindex ms-core-listMenu-horizontalBox”>

    最後, mouseenter和mouseexit的事件處理常式會新增至完成addEventsToElements()函數中的最上層功能來處理子網站下拉式功能表。

    螢幕擷取畫面下方顯示的導覽結果:

    導覽結果的螢幕擷取畫面

    在我們的複雜的導覽範例全新頁面載入不本機快取會顯示在伺服器花費的時間已經剪下向下事先結構式導覽,以取得受管理的導覽的方法類似的結果。

    SPRequestDuration 301 的螢幕擷取畫面

    這種方法的其中一個的主要優點是,藉由使用 HTML5 本機的儲存空間,導覽儲存本機使用者的下次他們載入頁面。

從搜尋 API 使用結構式導覽; 取得主要的效能提升不過,花一些技術的功能,可執行及自訂這項功能。在範例實作網站會排序的方塊出結構式導覽; 為相同的方式依字母順序。如果您想要與此順序不符合時,就會更複雜開發及維護作業。此外,此方法需要您支援的主版頁面與不符合。如果並未維持自訂主版頁面時,您的網站會錯過更新及改善 Microsoft 所產生的主版頁面。

上述的程式碼具有下列的相依性:

LinqJS 目前版本不包含上述的程式碼中使用的 ByHierarchy 方法,而且會中斷導覽程式碼。若要修正此問題,檔案中加入下列方法 Linq.js 行之前 「 Flatten: 函數 () 」。

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

附註: 機器翻譯免責聲明︰本文係以電腦系統翻譯而成,未經人為介入。Microsoft 提供此等機器翻譯旨在協助非英語系使用者輕鬆閱讀 Microsoft 產品、服務及技術相關內容。基於本文乃由機器翻譯而成,因此文中可能出現詞辭、語法、文法上之錯誤。

擴展您的技能
探索訓練
優先取得新功能
加入 Office 測試人員

這項資訊有幫助嗎?

感謝您的意見反應!

感謝您的意見反應! 我們將協助您與其中一位 Office 支援專員連絡以深入了解您的意見。

×