快速入門:將搜尋新增到應用程式 (HTML)

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

大部分使用者都依賴搜尋來找尋他們所要的物件。例如,假設您的應用程式會播放媒體檔案,那麼使用者會希望能夠搜尋特定歌曲或影片;如果您的應用程式是烹飪應用程式,則使用者會希望能夠搜尋特定食譜或食材。

只需稍微規劃,為您的應用程式新增搜尋並不難。以下是您所需的內容:

  • 要搜尋的資料來源。您需要使用者想要搜尋的某種目錄或項目的詳細目錄。您對這份詳細目錄描述得越詳盡,搜尋結果就越精確。
  • 用於輸入搜尋查詢的控制項。Windows 提供的 SearchBox 控制項可讓您的應用程式使用。SearchBox 提供用來輸入查詢的輸入區域、用來執行搜尋的搜尋按鈕,以及用來處理搜尋查詢的事件。它甚至能夠自動提供一些搜尋建議。
  • 用來顯示搜尋結果的頁面。Microsoft Visual Studio 提供 [搜尋結果頁] 範本,可建立您在處理搜尋查詢和顯示結果時所需的大量程式碼。

這個快速入門說明如何使用這些項目為您的應用程式新增搜尋功能。

如需了解此功能的運作情形,請參閱應用程式功能,從開始到完成系列: Windows 市集應用程式 UI,從開始到完成

先決條件

設定資料

使用者輸入搜尋查詢時,您的應用程式就會搜尋使用者想要尋找的項目。您應用程式搜尋的資料可能有數種形式:XML 檔案、JavaScript 物件標記法 (JSON) 資料、資料庫、Web 服務,或檔案系統中的檔案。

這個快速入門中的範例會使用您在 Visual Studio 建立新專案時,Microsoft Visual Studio 產生的範例資料。

當您使用 Visual Studio 建立新的 [格線應用程式]、[中樞應用程式]**** 或 [分割應用程式] 時,會在您的應用程式 js 資料夾中建立名為 data.js 的檔案。這個檔案包含可取代成您自己資料的靜態資料。例如,如果您的應用程式發出取得 RSS 或 JSON 資料的 xhr 要求,您可能需要將自己的程式碼新增到 data.js。在該處包含程式碼可讓您易於使用自己的資料,而不用變更 [搜尋結果頁] 所用的資料模型。

以下的範例是範例資料看起來的樣子:

function generateSampleData() {
    // . . .
    var sampleGroups = [
        { key: "group1", title: "Group Title: 1", // . . .
        // . . .
    ];

    var sampleItems = [
        { group: sampleGroups[0], title: "Item Title: 1", // . . .
        // . . .
    ];

    return sampleItems;
}

如果要讓檔案存取此資料,data.js 檔案會定義公開這些成員的 Data 命名空間:

  • items:包含資料項目的 WinJS.Binding.List。這是一個 List 群組。
  • groups:包含資料項目所屬群組的 WinJS.Binding.List(您也可以透過呼叫 items.groups 取得群組)。
  • getItemReference:抓取包含群組索引鍵和指定項目標題的物件。
  • getItemsFromGroup:抓取 FilteredListProjection,其中包含屬於群組的項目以及指定索引鍵。
  • resolveGroupReference:抓取代表含指定索引鍵之群組的物件。
  • resolveItemReference:這個方法會使用包含兩個字串、一個群組索引鍵和標題的陣列。這個方法會抓取含有指定群組索引鍵和標題的項目。

您不需要使用此命名空間或這些成員來包含您的資料,但這樣做可以讓使用 [搜尋結果頁] 範本更加簡單

(如需使用範本產生之資料的詳細資訊,請參閱如何自訂 Visual Studio 範本資料)。

新增搜尋結果頁

[搜尋結果頁]**** 會處理搜尋查詢並顯示結果。現在為您的專案新增一個搜尋結果頁。(這些指示假設您從中樞、格線或分割範本建立專案)

Hh465238.wedge(zh-tw,WIN.10).gif新增搜尋結果頁項目

  1. 在 [方案總管] 的 [頁面]**** 專案資料夾中,新增名為搜尋的新資料夾。

  2. 開啟 [搜尋] 資料夾的捷徑功能表,然後選擇 [加入]**** > [新增項目]。

  3. 在 [加入新項目]**** 對話方塊的中央窗格,選擇 [搜尋結果頁]。針對這個範例,保留 [名稱]**** 方塊中顯示的預設名稱 searchResults.html。

  4. 選擇 [加入]。

    Visual Studio 會將 searchResults.html、searchResults.css 以及 searchResults.js 新增到新 [搜尋]**** 資料夾中的專案。

我們還要對搜尋結果頁進行一些處理,但現在先將 SearchBox 新增到我們的應用程式。 使用 SearchBox 比較容易在實作搜尋結果頁時予以測試。

SearchBox 可讓使用輸入查詢。它也可以顯示建議。只需將這個標記新增到 HTML 頁面,即可將 SearchBox 新增至您的應用程式:

<div class="searchBox"
    data-win-control="WinJS.UI.SearchBox"
    data-win-options="{placeholderText: 'Search'}">
</div>

(您還需要登錄 onquerysubmitted 事件;我們將在之後的步驟中說明)。

您應該將搜尋方塊放置在哪裡?建議您在應用程式的每個頁面放置搜尋方塊,讓使用者能夠隨時輕鬆搜尋。如果空間有限,您可以將搜尋方塊放在頂端應用程式列。

Hh465238.wedge(zh-tw,WIN.10).gif將 SearchBox 新增至頁面

  1. 我們將 SearchBox 新增到您的其中一個應用程式頁面。這些指示適用於以 Page 控制項為基礎的任何頁面。

    SearchBox 的最佳擺放位置通常是頁面右上角。從 Visual Studio 範本建立的大多數頁面 (例如 [頁面控制項] 範本) 都有一個包含頁面標題和返回按鈕的 header 元素:

            <header aria-label="Header content" role="banner">
                <button data-win-control="WinJS.UI.BackButton"></button>
                <h1 class="titlearea win-type-ellipsis">
                    <span class="pagetitle"></span>
                </h1>
            </header>
    

    只要將您的 SearchBox 加在 h1 元素的後面:

            <header aria-label="Header content" role="banner">
                <button data-win-control="WinJS.UI.BackButton"></button>
                <h1 class="titlearea win-type-ellipsis">
                    <span class="pagetitle">Welcome to basicPage</span>
                </h1>
                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search'}">
                </div>
            </header>
    
  2. (建議選項) 您應該讓您的使用者只要開始使用鍵盤輸入,就能夠搜尋應用程式中的內容。

    許多人都將使用鍵盤與 Windows 8 互動。讓使用者透過輸入進行搜尋可以有效使用鍵盤互動,並讓您的應用程式搜尋經驗與 [開始] 畫面一致。

    SearchBox 控制項的 focusOnKeyboardInput 屬性設定為 true,讓搜尋方塊在使用者輸入項目時收到輸入。

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true }">
                </div>
    
  3. Visual Studio 為您建立的 default.css 樣式表提供標頭元素一個 -ms-grid 配置。若要將 SearchBox 放在頁面的右上角,只要將這個樣式新增到您頁面的階層式樣式表 (CSS) 檔案:

    .searchBox {
        -ms-grid-column: 4;
        margin-top: 57px;
        margin-right: 29px;
    }
    

Hh465238.wedge(zh-tw,WIN.10).gif處理 onquerysubmitted 事件

  1. 您的應用程式很可能會有多個 SearchBox 控制項。我們來定義這些控制項都能使用的單一 onquerysubmitted 事件處理常式。

    開啟您應用程式的 default.js 檔案。

  2. 建立名為 "querySubmittedHandler" 的 onquerysubmitted 事件處理常式,它使用一個名為 "args" 的引數(您可以將這個方法定義放在包裝現有 default.js 程式碼之匿名函式的任何位置)。

        function querySubmittedHandler(args) {
    
        }
    
  3. 呼叫 WinJS.Navigation.navigate 使用事件處理常式瀏覽至新的搜尋結果頁。args.details 屬性包含的物件可提供搜尋結果頁所需之事件的相關資訊,因此當您呼叫 WinJS.Navigation.navigate 時會傳送這個物件。

        function querySubmittedHandler(args) {
            WinJS.Navigation.navigate('/pages/search/searchResults.html', args.detail);
        }
    

    警告  如果使用 [空白應用程式] 範本建立應用程式,則需要在應用程式新增瀏覽支援,才能讓搜尋正常運作。 您可以在應用程式新增名為 PageControlNavigator 的自訂控制項,以便使用與格線、分割及瀏覽應用程式範本相同的方式支援瀏覽。您可以在快速入門:使用單頁瀏覽中,了解這個自訂控制項支援瀏覽的方式。如果您不要使用自訂控制項支援瀏覽,則需要撰寫自己的程式碼,以接聽和回應瀏覽事件,例如 WinJS.Navigation.navigated。您可以在瀏覽和瀏覽歷程記錄範例查看範例,以了解如何不使用自訂控制項 (例如 PageControlNavigator) 來支援瀏覽。

     

  4. 我們現在需要定義命名空間並將處理常式設為成員,以公開發佈這個事件處理常式。我們將這個命名空間稱為 "SearchUtils"。我們還需要使用 WinJS.UI.eventHandler 方法,以宣告的方式設定事件處理常式 (如需此操作如何運作的詳細資訊,請參閱如何以宣告方式設定事件處理常式)。

        WinJS.Namespace.define("SearchUtils",
        {
            querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler)
        }
        );
    
  5. 開啟包含您 SearchBox 的 HTML 頁面。使用 data-win-options 屬性將 onquerysubmitted 事件設成 SampleUtils.querySubmittedHandler

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true,
                     onquerysubmitted: SearchUtils.querySubmittedHandler}">
                </div>
    

讓我們來試試看。執行應用程式,並在 SearchBox 中輸入測試查詢,然後按 Enter 鍵。如果您使用的是 Visual Studio 提供的範例資料,試著使用 "1" 作為您的測試查詢。

測試查詢

您編寫的 onquerysubmitted 事件處理常式會瀏覽至搜尋結果頁,並傳遞您輸入的查詢。

測試查詢的結果

如果您使用範例資料,應該會看到符合測試查詢的項目。如果使用自己的資料,您可能還不能取得任何結果,我們需要先更新搜尋結果頁。我們將在之後的步驟加以說明。

搜尋您的資料

現在請回到搜尋結果頁。 當您的應用程式瀏覽到搜尋結果頁時,第一個會呼叫的方法是 _handleQuery 方法。 _handleQuery 會呼叫多個我們需要修改的方法:

  1. _generateFilters

    產生篩選清單,使用者按一下即可篩選結果。

  2. _searchData

    搜尋您的資料是否有相符的項目,並將它們儲存在名為 originalResultsList

  3. _populateFilterBar

    在我們的篩選清單顯示篩選。

我們來更新這些方法,針對您的資料加以自訂。

更新篩選

_generateFilters 方法會產生篩選清單,使用者按一下即可篩選結果。範本產生的方法會建立三個篩選:"All" 篩選可顯示所有結果、顯示群組 1 項目的篩選,以及顯示其他項目的篩選。我們將範例產生的程式碼取代為可動態產生篩選清單的程式碼。如此一來,如果您變更範例資料,您的新篩選就會顯示在頁面上。我們將會更新 _generateFilters 程式碼,並建立兩個 Helper 方法。但首先,我們需要更新 data.js 檔案以存取群組清單;我們要使用這些群組定義篩選。

Hh465238.wedge(zh-tw,WIN.10).gif更新 _generateFilters 方法

  1. 在 searchResults.js 中,找尋 _generateFilters 方法並刪除其中所含的程式碼。

  2. 初始化 _filters 陣列 (_filters 陣列是搜尋結果頁定義的成員變數)。

    
            _generateFilters: function () {
                this._filters = [];
    
  3. 現在來建立篩選。篩選是含有三個屬性的物件:

    • results:要顯示的項目 List。我們目前將它設定為 null
    • text:篩選的顯示文字。
    • predicate:使用項目的函式。如果項目符合篩選條件 (選取此篩選後應該顯示的項目),此函式會傳回 true;否則,傳回 false

    首先,我們來建立 "All" 篩選。全部篩選一定會顯示項目,因此它的 predicate 一定會傳回 true

    
                this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });
    
  4. 現在,我們為資料中的每個群組建立篩選。我們的群組會儲存成名為 Data.groupsList。使用 forEach 方法逐一處理 List 中的每個群組。forEach 方法使用函式作為參數;這個函式會針對清單中的每個項目進行呼叫。我們將名為 _createFiltersForGroups 的成員函式傳送給它;我們將在下個步驟建立函式。

                if (window.Data) {
                    Data.groups.forEach(this._createFiltersForGroups.bind(this));
                }
            },
    
  5. 現在,讓我們來建立 _createFiltersForGroups 函式。

    1. 建立一個名為 _createFiltersForGroups 的成員函式,這個函式可接受三個參數:elementindexarray

              _createFiltersForGroups: function (element, index, array){
      
      
    2. element 參數包含我們的群組物件。 建立一個新篩選物件並使用 push 方法將它新增到 _filters 陣列。將篩選的 results 屬性設定為 null、將它的 text 屬性設定為 element.title,並將它的 predicate 屬性設定為名為 _filterPredicate 的函式。您將在下個步驟中定義 _filterPredicate 方法。

                  this._filters.push(
                      { results: null, text: element.title, predicate: this._filterPredicate.bind(element)}
                      );
              },
      
    3. 建立一個名為 _filterPredicate 的成員函式,這個函式可接受一個名為 item 的參數。如果 item 參數的 group 屬性等於目前的群組物件,便傳回 true

              _filterPredicate: function (item) {
      
                  return item.group === this;          
              },
      

下列為我們剛建立之三個方法的完整程式碼:

        _generateFilters: function () {
            this._filters = [];
            this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });

            if (window.Data) {
                Data.groups.forEach(this._createFiltersForGroups.bind(this));
            }
        },

        _createFiltersForGroups: function (element, index, array){
            
            this._filters.push(
                { results: null, text: element.title, predicate: this._filterPredicate.bind(element)}
                );
        },

        _filterPredicate: function (item) {

            return item.group === this;          
        },

執行應用程式並進行搜尋,您應該會在篩選列中看到您的新篩選。

更新的篩選清單

如果您使用的是範本產生的範例資料,您可能會發現有些群組遭到裁剪。您可以在搜尋結果頁的 CSS 檔案中進行一些調整來修正這個問題。

Hh465238.wedge(zh-tw,WIN.10).gif更新搜尋結果頁的 CSS

  1. 開啟 searchResults.css。

  2. 尋找 .searchResults section[role=main] 樣式並將 -ms-grid-rows 屬性的值變更成 "auto 1fr"。

    .searchResults section[role=main] {
        /* Define a grid with rows for the filters and results */
        -ms-grid-columns: 1fr;
        -ms-grid-rows: auto 1fr;
        -ms-grid-row: 1;
        -ms-grid-row-span: 2;
        display: -ms-grid;
    }
    
  3. 尋找 .searchResults section[role=main] .filterbar 樣式,並將 word-wrap 屬性的值變更成 "normal",然後將 margin-bottom 設為 "20px"。

        .searchResults section[role=main] .filterbar {
            -ms-font-feature-settings: "case" 1;
            -ms-grid-row: 1;
            list-style-type: none;
            margin-left: 60px;
            margin-right: 60px;
            margin-top: 133px;
            max-width: calc(100% - 120px);
            position: relative;
            white-space: normal;
            z-index: 1; 
            margin-bottom: 20px; 
        }
    
  4. 尋找 .searchResults section[role=main] .filterbar li 樣式並將 display 屬性的值變更成 "inline-block"。

            .searchResults section[role=main] .filterbar li {
                display: inline-block; 
                margin-left: 20px;
                margin-right: 20px;
                margin-top: 5px;
                opacity: 0.6;
            }
    
  5. 尋找 .searchResults section[role=main] .resultslist 樣式,並將 -ms-grid-row 屬性的值變更成 "2",然後將 -ms-grid-row-span 設為 "1"。

        .searchResults section[role=main] .resultslist {
            -ms-grid-row: 2;
            -ms-grid-row-span: 1;
            height: 100%;
            position: relative;
            width: 100%;
            z-index: 0;
        }
    

執行應用程式並進行另一個搜尋。您現在應該會看到所有篩選。

更新的篩選清單

更新搜尋演算法

_searchData 方法會搜尋符合搜尋查詢的項目資料。範本產生的程式碼會搜尋每個項目的標題、副標題及描述。我們來撰寫自己的搜尋程式碼,依相關性排序結果。

Hh465238.wedge(zh-tw,WIN.10).gif更新 _searchData 方法

  1. 開啟 searchResults.js,尋找 _searchData 方法,並刪除其中所含的程式碼。

  2. 建立名為 originalResults 的變數;這會是我們的傳回值。

            // This function populates a WinJS.Binding.List with search results for the
            // provided query.
            _searchData: function (queryText) {
    
                // Create a variable for the results list.
                var originalResults;
    
  3. 將查詢文字和我們看到的文字轉換成小寫,讓我們的搜尋變成區分大小寫。我們先將查詢轉換成小寫,並將它儲存成名為 lowercaseQueryText 的變數。

                // Convert the query to lowercase. 
                var lowercaseQueryText = queryText.toLocaleLowerCase();
    
  4. 嘗試存取資料前,先確定資料已經存在。

                if (window.Data)
                {
    
  5. 如果您使用 data.js 提供的範例資料,則我們的項目會儲存在 Data.items,這是 WinJS.Binding.List 物件。使用 createFiltered 方法篩選出不符合搜尋查詢的項目。

    createFiltered 方法使用篩選函式作為參數。這個篩選函式使用一個參數 itemList 會在清單中的每個項目呼叫此函式,以判斷它是否應該在篩選後的清單中。 如果應該包含項目,函式就會傳回 true,如果應該略過項目,則會傳回 false

                    originalResults = Data.items.createFiltered(
    
                        function (item) {
    
  6. 在 JavaScript 中,您可以在現有物件附加新的屬性。將 ranking 屬性新增到 item,並將它的值設為 "-1"。

                            // A ranking < 0 means that a match wasn't found. 
                            item.ranking = -1;
    
  7. 首先,我們來看看項目標題是否包含查詢文字。如果有,給項目 10 點。

                            if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
    
                                item.ranking += 10;
                            }
    
  8. 接著,在副標題欄位檢查相符的項目。如果找到相符的項目,給項目 5 點。

                            if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                                item.ranking += 5;
                            }
    
  9. 最後,檢查描述欄位。如果找到相符的項目,給項目 1 點。

                            if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                                item.ranking += 1;
                            }
    
  10. 如果項目的點數為 -1,表示不符合我們的搜尋查詢。針對傳回值,如果項目的點數等級大於或等於 0,則傳回 true

                            return (item.ranking >= 0);
                        }
                     );
    
  11. 目前為止,我們已將清單縮小為只符合搜尋查詢的項目,並新增了點數等級資訊。現在,我們使用 createSorted 方法排序結果清單,將最多點數的項目排在第一個。

                    // Sort the results by the ranking info we added. 
                    originalResults = originalResults.createSorted(function (firstItem, secondItem){
                            if (firstItem.ranking == secondItem.ranking) {
                                return 0;
                            }
                            else if (firstItem.ranking < secondItem.ranking)
                                return 1;
                            else
                                return -1;
                        });
    
                }
    
  12. 如果我們的資料遺失,請建立一個空的清單。

                else {
    
                    // For some reason, the Data namespace is null, so we 
                    // create an empty list to return. 
                    originalResults = new WinJS.Binding.List();
    
                }
    
  13. 最後,傳回結果。

                return originalResults;
            }
    

下列為更新的 _searchData 方法的完整程式碼。

        _searchData: function (queryText) {

            // Create a variable for the results list.
            var originalResults;

            // Convert the query to lowercase. 
            var lowercaseQueryText = queryText.toLocaleLowerCase();

            if (window.Data)
            {
                originalResults = Data.items.createFiltered(

                    function (item) {

                        // A ranking < 0 means that a match wasn't found. 
                        item.ranking = -1;

                        if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {

                            item.ranking += 10;
                        }
                        if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                            item.ranking += 5;
                        }
                        if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                            item.ranking += 1;
                        }

                        return (item.ranking >= 0);
                    }
                 );

                // Sort the results by the ranking info we added. 
                originalResults = originalResults.createSorted(function (firstItem, secondItem){
                        if (firstItem.ranking == secondItem.ranking) {
                            return 0;
                        }
                        else if (firstItem.ranking < secondItem.ranking)
                            return 1;
                        else
                            return -1;
                    });

            }
            else {

                // For some reason, the Data namespace is null, so we 
                // create an empty list to return. 
                originalResults = new WinJS.Binding.List();

            }

            return originalResults;
        }

提供瀏覽到搜尋傳回的項目

當您執行應用程式並進行搜尋時,搜尋結果頁會將結果顯示在 ListView 控制項中。 現在,按一下其中一個搜尋結果項目並不會有任何反應。我們新增一些程式碼,在使用者按一下時顯示項目。

當使用者按一下 ListView 中的項目時,ListView 會觸發 oniteminvoked 事件。搜尋結果頁的範例產生程式碼會定義名為 _itemInvokedoniteminvoked 事件處理常式。更新程式碼以瀏覽到叫用的項目。

Hh465238.wedge(zh-tw,WIN.10).gif新增項目瀏覽

  • 開啟 searchResults.js,然後將程式碼新增至 _itemInvoked 函式以瀏覽到正確頁面。注意  這裡顯示的 URI 是針對「中樞」範本。對於「格線」範本,URI 必須是:/pages/itemDetail/itemDetail.html。對於「分割」範本,URL 必須是:/pages/items/items.html。

     

            _itemInvoked: function (args) {
                args.detail.itemPromise.done(function itemInvoked(item) {
                    // TODO: Navigate to the item that was invoked.
                    var itemData = [item.groupKey, item.data.title];
                    WinJS.Navigation.navigate("/pages/item/item.html", { item: itemData });
                });
            },
    

(選用) 更新 ListView 控制項的 itemTemplate

範本產生的搜尋結果頁會定義 itemTemplate,這是設計與 Visual Studio 為您建立的範例資料來源搭配使用;它會預期每個資料項目都有下列欄位:"影像"、"標題"、"副標題"及"描述"。

如果資料項目具備不同欄位,您就必須修改 itemTemplate。如需相關指示,請參閱快速入門:新增 ListView

(選用) 新增搜尋建議

搜尋建議會顯示在搜尋窗格的搜尋方塊下方。建議非常重要,因為這樣可以節省使用者的時間,並為使用者提供搜尋您應用程式內容時的重要提示。

您可以從數個來源得到建議:

  • 您可以自行定義建議。例如,您可以建立汽車製造商清單。
  • 如果您的應用程式搜尋本機檔案,則可以從 Windows 得到建議。
  • 您可以從 Web 服務或伺服器得到建議。

如需有關顯示建議的使用者經驗指導方針,請參閱搜尋的指導方針和檢查清單

如果使用 LocalContentSuggestionSettings,只要透過幾行程式碼,就可以根據 Windows 的本機檔案新增建議。此外,您也可以登錄搜尋方塊控制項的 onsuggestionsrequested 事件並建立自己的建議清單,其中包括您從其他來源 (例如本機定義的清單或 Web 服務) 所擷取的建議。這個快速入門說明如何處理 onsuggestionsrequested 事件。

如需示範如何新增搜尋建議的其他程式碼範例,請下載 SearchBox 控制項範例。範例會示範如何使用這三種可能來源新增搜尋建議,以及如何使用輸入法 (IME) 產生的查詢文字替代形式來新增東亞語言的建議 (如果應用程式將由日文或中文使用者使用,建議您使用替代查詢文字)。

Hh465238.wedge(zh-tw,WIN.10).gif處理 SuggestionsRequested 事件

  1. 您的應用程式可能會有多個 SearchBox 控制項;讓我們在您的 default.js 檔案中定義單一事件處理常式,讓這些控制項都能使用。在您之前步驟中建立的 querySubmittedHandler 方法後面新增此程式碼。

        function suggestionsRequestedHandler(args) {
    
  2. SearchBox 查詢文字轉換為小寫。

            var query = args.detail.queryText.toLocaleLowerCase();
    
  3. 系統會自動提供一些搜尋建議,例如使用者執行過的搜尋。讓我們將搜尋建議新增至系統提供的搜尋建議中。

            // Retrieve the system-supplied suggestions.
            var suggestionCollection = args.detail.searchSuggestionCollection;
    
  4. 確定查詢至少包含一個字元,且我們可以存取自己的資料。

            if (query.length > 0 && window.Data) {
    
  5. 逐一查看資料中的每個項目,並檢查是否有相符項目。尋找相符項目時,可將相符項目的標題附加至搜尋建議集合。

                Data.items.forEach(
                    function (element, index, array) {
                        if (element.title.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element.title);
                        }
    
                    });
    
  6. args.detail.linguisticDetails.queryTextAlternatives 屬性會針對以 IME 輸入文字的使用者提供其他建議。使用這些建議可改善東亞語言使用者的搜尋經驗。讓我們檢查替代查詢文字是否有字串包含原始查詢,並將其新增至我們的搜尋建議清單。

                args.detail.linguisticDetails.queryTextAlternatives.forEach(
                    function (element, index, array) {
                        if (element.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element);
                        }
    
                    });
            }
        }
    

    這就是我們的搜尋建議事件處理常式所需的程式碼。下列是完整的 suggestionsRequestedHandler 方法:

        function suggestionsRequestedHandler(args) {
    
            var query = args.detail.queryText.toLocaleLowerCase();
    
            // Retrieve the system-supplied suggestions.
            var suggestionCollection = args.detail.searchSuggestionCollection;
    
            if (query.length > 0 && window.Data) {
    
                Data.items.forEach(
                    function (element, index, array) {
                        if (element.title.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element.title);
                        }
    
                    });
    
                args.detail.linguisticDetails.queryTextAlternatives.forEach(
                    function (element, index, array) {
                        if (element.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element);
                        }
    
                    });
    
            }
        }
    

    注意  如果您的資料來源非同步,必須將更新包裝在 Promise 中的搜尋建議集合。範例程式碼使用 List,這是同步的資料來源,如果 List 是非同步資料來源,方法看起來會像這樣。

     

        function suggestionsRequestedHandler(args) {
    
            var query = args.detail.queryText.toLocaleLowerCase();
    
            // Retrieve the system-supplied suggestions.
            var suggestionCollection = args.detail.searchSuggestionCollection;
    
            if (query.length > 0 && window.Data) {
    
                args.detail.setPromise(WinJS.Promise.then(null, 
                    function () {
                        Data.items.forEach(
                            function (element, index, array) {
                                if (element.title.substr(0, query.length).toLocaleLowerCase() === query) {
                                    suggestionCollection.appendQuerySuggestion(element.title);
                                }
    
                            });
    
                        args.detail.linguisticDetails.queryTextAlternatives.forEach(
                            function (element, index, array) {
                                if (element.substr(0, query.length).toLocaleLowerCase() === query) {
                                    suggestionCollection.appendQuerySuggestion(element);
                                }
    
                            });
    
                    })
                 );
            }
        }
    
  7. 這就是我們的搜尋建議事件處理常式所需的程式碼。透過在之前步驟定義的 SearchUtils 命名空間公開這些程式碼,讓這些程式碼可供公開存取。

        WinJS.Namespace.define("SearchUtils",
        {
            querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler),
            suggestionsRequestedHandler: WinJS.UI.eventHandler(suggestionsRequestedHandler)
        }
        );
    
  8. 現在向我們的 SearchBox 登錄事件。開啟包含您 SearchBox 的 HTML 頁面,將 onsuggestionsrequested 事件設為 SearchUtils.suggestionsRequestedHandler

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true,
                     onquerysubmitted: SearchUtils.querySubmittedHandler,
                     onsuggestionsrequested: SearchUtils.suggestionsRequestedHandler}">
                </div>
    

實作搜尋協定 (針對舊版 Windows)

在 Windows 8.1 之前,應用程式使用搜尋常用鍵提供應用程式內搜尋。開發人員實作搜尋協定和使用 SearchPane API 來處理查詢以及取得建議和結果。

雖然我們繼續完全支援 Windows 8 搜尋協定與 SearchPane API,但是從 Windows 8.1 開始,我們建議使用 SearchBox 控制項而非 SearchPane。 使用 SearchBox 的應用程式不需要實作搜尋協定。

應用程式到底該不該使用 SearchPane 與搜尋協定?如果您認為使用者不會經常搜尋您的應用程式,則可使用 SearchPane 與搜尋協定。建議您在應用程式中使用含有搜尋字符 (Segoe UI Symbol 0xE0094,15pt) 的按鈕時,讓使用者按一下就能啟用搜尋窗格。若要查看用來實作 SearchPane 與搜尋協定的程式碼,請參閱搜尋協定範例

摘要與後續步驟

您使用了 SearchBox 控制項與 [搜尋結果頁],將搜尋新增到應用程式。

如需可協助您為使用者設計和建立出色搜尋體驗的指導方針,請參閱搜尋的指導方針和檢查清單

相關主題

SearchBox 控制項範例

搜尋的指導方針和檢查清單