網站搜尋

javascript - 如何使用 jQuery find 從完整頁面 HTML 字串中擷取內容


我有一個 TypeScript 方法,旨在從傳入的 Ajax 加載的 HTML 字符串中提取特定的部分視圖元素(如果它是完整視圖的話)。

以下這行回傳長度為 0,即使字串中包含一個具有 class="body-content" 的元素:

$(html).find('.body-content')

功能:

    // Extract a panel from a HTML string
    // Allow for multiple child elements
    private _extractPanel(html: string): JQuery
    {
        var $panel: JQuery;

        // Test for full vs. partial view in html
        if (/<html>/i.test(html))
        {
            // Full view: Match the content selector and extract its children
            $panel = $(html).find('.body-content').first().children();
            // *** THE LINE ABOVE GIVES ZERO MATCHES! ***
        }
        else
        {
            // Partial view: Simply return the entire partial view
            $panel = $(html);
        }
        return $panel;
    }

是因為根元素是一個 HTML 元素,還是我錯過了什麼?$ (html) 返回一個長度為 63 的對象,但 find 沒有返回任何匹配項。

這裡是一個來自除錯器的 html 參數值範例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Index - My ASP.NET Application</title>
        <link href="/Content/bootstrap.css" rel="stylesheet" />
        <link href="/Content/site.css" rel="stylesheet" />
        <script src="/Scripts/modernizr-2.7.2.js"></script>
    </head>

    <body>
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>

                    </button> <a class="navbar-brand" href="/">jQuery Tardis</a>

                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li><a href="/">Home</a>
                        </li>
                        <li><a href="/Home/About">About</a>
                        </li>
                        <li><a href="/Home/Contact">Contact</a>
                        </li>
                    </ul>
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="/Account/Register" id="registerLink">Register</a>
                        </li>
                        <li><a href="/Account/Login" id="loginLink">Log in</a>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="container body-content">
            <div id="testpanel" class="row">
                <div class="AddinListView"> <a href="/">Home</a>

                     <h2>Tardis transition examples</h2>

                    <ul>
                        <li><a href="/Transition/Transition/1?transition=none" target="_self">No transition (hide/show)</a>
                        </li>
                        <li><a href="/Transition/Transition/1?transition=slide" target="_self">Slide out/in</a>
                        </li>
                        <li><a href="/Transition/Transition/1?transition=fade" target="_self">Fade out/in transtions</a>
                        </li>
                    </ul>
                </div>
            </div>
            <hr />
        </div>
        <footer>
            <p>&copy; 2014 - My ASP.NET Application</p>
        </footer>
    </body>

</html>

後續: http://jsfiddle.net/TrueBlueAussie/7AvmW/2/

根據 Jack 的回答,我整理了上面的 JSFiddle 來看看發生了什麼。

結果:

基本上,對於包含無效子元素的字串,例如HTML、HEAD和BODY,jQuery 會將這些元素解包。 我發現的效果當然只是將BODY 的第一層拉平,讓它們回到成為根元素。

解決方案:

最簡單的解決方法是總是用一個虛擬父元素來創建頁面元素以進行搜尋。

例如

$html =$('<div>').html(html);

那麼任何典型的搜尋都會有效:

$html.find('.selector');

答案#1

當你使用 jQuery(html) 時,它會建立一個臨時的 <div>,然後將其 .innerHTML 屬性設置為給定的 HTML 內容。之後,它會迭代 .childNodes 屬性來構建 jQuery 集合。

文件也指出:

在傳入複雜的 HTML 時,某些瀏覽器可能無法生成完全複製所提供 HTML 原始碼的 DOM……在此過程中,某些瀏覽器會過濾掉某些元素,例如 <html>、<title> 或 <head> 元素。因此,插入的元素可能無法代表所傳入的原始字串。

在 Chrome(以及可能其他瀏覽器)中,當整個頁面以這種方式加載時,臨時 <div> 的 .firstChild 屬性是 <body> 的第一個子元素:

var d = document.createElement('div');
d.innerHTML = '<html><body><span>hi</span></body></html>';
console.log(d.firstChild); // <span>hi</span>

解決方案

要可靠地使用 .find(),你可以像這樣將頁面加載到一個臨時元素中:

var $root = $('<div>', {html: html});
var $items = $root.find('.body-content');

如果你事先已經知道頁面的結構,你也可以使用 .filter():

var $items = $(html).filter('.body-content');