亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

深入理解javascript動態插入技術

2019-11-20 21:43:47
字體:
來源:轉載
供稿:網友

最近發現各大類庫都能利用div.innerHTML=HTML片斷來生成節點元素,再把它們插入到目標元素的各個位置上。這東西實際上就是insertAdjacentHTML,但是IE可惡的innerHTML把這優勢變成劣勢。首先innerHTML會把里面的某些位置的空白去掉,見下面運行框的結果:

復制代碼 代碼如下:


<!doctype html>
<html dir="ltr" lang="zh-CN">
    <head>
        <meta charset="utf-8" />
        <title>
            IE的innerHTML By 司徒正美
        </title>
        <script type="text/javascript">
            window.onload = function() {
                var div = document.createElement("div");
                div.innerHTML = "   <td>    <b>司徒</b>正美         </td>        "
                alert("|" + div.innerHTML + "|");
                var c = div.childNodes;
                alert("生成的節點個數  " + c.length);
                for(var i=0,n=c.length;i<n;i++){
                      alert(c[i].nodeType);
                      if(c[i].nodeType === 1){
                          alert(":: "+c[i].childNodes.length);
                      }
                }       
            }
        </script>
    </head>

    <body>
        <p id="p">
        </p>
    </body>

</html>

另一個可惡的地方是,在IE中以下元素的innerHTML是只讀的:col、 colgroup、frameset、html、 head、style、table、tbody、 tfoot、 thead、title 與 tr。為了收拾它們,Ext特意弄了個insertIntoTable。insertIntoTable就是利用DOM的insertBefore與appendChild來添加,情況基本同jQuery。不過jQuery是完全依賴這兩個方法,Ext還使用了insertAdjacentHTML。為了提高效率,所有類庫都不約而同地使用了文檔碎片?;玖鞒潭际峭ㄟ^div.innerHTML提取出節點,然后轉移到文檔碎片上,然后用insertBefore與appendChild插入節點。對于火狐,Ext還使用了createContextualFragment解析文本,直接插入其目標位置上。顯然,Ext的比jQuery是快許多的。不過jQuery的插入的不單是HTML片斷,還有各種節點與jQuery對象。下面重溫一下jQuery的工作流程吧。

復制代碼 代碼如下:

append: function() {
  //傳入arguments對象,true為要對表格進行特殊處理,回調函數
  return this.domManip(arguments, true, function(elem){
    if (this.nodeType == 1)
      this.appendChild( elem );
  });
},
domManip: function( args, table, callback ) {
  if ( this[0] ) {//如果存在元素節點
    var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
    //注意這里是傳入三個參數
    scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
    first = fragment.firstChild;

    if ( first )
      for ( var i = 0, l = this.length; i < l; i++ )
        callback.call( root(this[i], first), this.length > 1 || i > 0 ?
      fragment.cloneNode(true) : fragment );

    if ( scripts )
      jQuery.each( scripts, evalScript );
  }

  return this;

  function root( elem, cur ) {
    return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
      (elem.getElementsByTagName("tbody")[0] ||
      elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
      elem;
  }
}
//elems為arguments對象,context為document對象,fragment為空的文檔碎片
clean: function( elems, context, fragment ) {
  context = context || document;

  // !context.createElement fails in IE with an error but returns typeof 'object'
  if ( typeof context.createElement === "undefined" )
  //確保context為文檔對象
    context = context.ownerDocument || context[0] && context[0].ownerDocument || document;

  // If a single string is passed in and it's a single tag
  // just do a createElement and skip the rest
  //如果文檔對象里面只有一個標簽,如<div>
  //我們大概可能是在外面這樣調用它$(this).append("<div>")
  //這時就直接把它里面的元素名取出來,用document.createElement("div")創建后放進數組返回
  if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
    var match = /^<(/w+)/s*//?>$/.exec(elems[0]);
    if ( match )
      return [ context.createElement( match[1] ) ];
  }
  //利用一個div的innerHTML創建眾節點
  var ret = [], scripts = [], div = context.createElement("div");
  //如果我們是在外面這樣添加$(this).append("<td>表格1</td>","<td>表格1</td>","<td>表格1</td>")
  //jQuery.each按它的第四種支分方式(沒有參數,有length)遍歷aguments對象,callback.call( value, i, value )
  jQuery.each(elems, function(i, elem){//i為索引,elem為arguments對象里的元素
    if ( typeof elem === "number" )
      elem += '';

    if ( !elem )
      return;

    // Convert html string into DOM nodes
    if ( typeof elem === "string" ) {
      // Fix "XHTML"-style tags in all browsers
      elem = elem.replace(/(<(/w+)[^>]*?)//>/g, function(all, front, tag){
        return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
          all :
          front + "></" + tag + ">";
      });

      // Trim whitespace, otherwise indexOf won't work as expected
      var tags = elem.replace(/^/s+/, "").substring(0, 10).toLowerCase();

      var wrap =
        // option or optgroup
        !tags.indexOf("<opt") &&
        [ 1, "<select multiple='multiple'>", "</select>" ] ||

        !tags.indexOf("<leg") &&
        [ 1, "<fieldset>", "</fieldset>" ] ||

        tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
        [ 1, "<table>", "</table>" ] ||

        !tags.indexOf("<tr") &&
        [ 2, "<table><tbody>", "</tbody></table>" ] ||

        // <thead> matched above
      (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
        [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||

        !tags.indexOf("<col") &&
        [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

        // IE can't serialize <link> and <script> tags normally
        !jQuery.support.htmlSerialize &&//用于創建link元素
      [ 1, "div<div>", "</div>" ] ||

        [ 0, "", "" ];

      // Go to html and back, then peel off extra wrappers
      div.innerHTML = wrap[1] + elem + wrap[2];//比如"<table><tbody><tr>" +<td>表格1</td>+"</tr></tbody></table>"

      // Move to the right depth
      while ( wrap[0]-- )
        div = div.lastChild;

      //處理IE自動插入tbody,如我們使用$('<thead></thead>')創建HTML片斷,它應該返回
      //'<thead></thead>',而IE會返回'<thead></thead><tbody></tbody>'
      if ( !jQuery.support.tbody ) {

        // String was a <table>, *may* have spurious <tbody>
        var hasBody = /<tbody/i.test(elem),
        tbody = !tags.indexOf("<table") && !hasBody ?
          div.firstChild && div.firstChild.childNodes :

          // String was a bare <thead> or <tfoot>
        wrap[1] == "<table>" && !hasBody ?
          div.childNodes :
          [];

        for ( var j = tbody.length - 1; j >= 0 ; --j )
        //如果是自動插入的里面肯定沒有內容
          if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
            tbody[ j ].parentNode.removeChild( tbody[ j ] );

      }

      // IE completely kills leading whitespace when innerHTML is used
      if ( !jQuery.support.leadingWhitespace && /^/s/.test( elem ) )
        div.insertBefore( context.createTextNode( elem.match(/^/s*/)[0] ), div.firstChild );
     //把所有節點做成純數組
      elem = jQuery.makeArray( div.childNodes );
    }

    if ( elem.nodeType )
      ret.push( elem );
    else
    //全并兩個數組,merge方法會處理IE下object元素下消失了的param元素
      ret = jQuery.merge( ret, elem );

  });

  if ( fragment ) {
    for ( var i = 0; ret[i]; i++ ) {
      //如果第一層的childNodes就有script元素節點,就用scripts把它們收集起來,供后面用globalEval動態執行
      if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
        scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
      } else {
        //遍歷各層節點,收集script元素節點
        if ( ret[i].nodeType === 1 )
          ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
        fragment.appendChild( ret[i] );
      }
    }

    return scripts;//由于動態插入是傳入三個參數,因此這里就返回了
  }

  return ret;
},

真是復雜的讓人掉眼淚!不過jQuery的實現并不太高明,它把插入的東西統統用clean轉換為節點集合,再把它們放到一個文檔碎片中,然后用appendChild與insertBefore插入它們。在除了火狐外,其他瀏覽器都支持insertAdjactentXXX家族的今日,應該好好利用這些原生API。下面是Ext利用insertAdjactentHTML等方法實現的DomHelper方法,官網給出的數據:

這數據有點老了,而且最新3.03早就解決了在IE table插入內容的詬病(table,tbody,tr等的innerHTML都是只讀,insertAdjactentHTML,pasteHTML等方法都無法修改其內容,要用又慢又標準的DOM方法才行,Ext的早期版本就在這里遭遇滑鐵盧了)??梢钥闯?,結合insertAdjactentHTML與文檔碎片后,IE6插入節點的速度也得到難以置信的提升,直逼火狐?;谒?,Ext開發了四個分支方法insertBefore、insertAfter、insertFirst、append,分別對應jQuery的before、after、prepend與append。不過,jQuery還把這幾個方法巧妙地調換了調用者與傳入參數,衍生出insertBefore、insertAfter、prependTo與appendTo這幾個方法。但不管怎么說,jQuery這樣一刀切的做法實現令人不敢苛同。下面是在火狐中實現insertAdjactentXXX家族的一個版本:

復制代碼 代碼如下:

(function() {
    if ('HTMLElement' in this) {
        if('insertAdjacentHTML' in HTMLElement.prototype) {
            return
        }
    } else {
        return
    }

    function insert(w, n) {
        switch(w.toUpperCase()) {
        case 'BEFOREEND' :
            this.appendChild(n)
            break
        case 'BEFOREBEGIN' :
            this.parentNode.insertBefore(n, this)
            break
        case 'AFTERBEGIN' :
            this.insertBefore(n, this.childNodes[0])
            break
        case 'AFTEREND' :
            this.parentNode.insertBefore(n, this.nextSibling)
            break
        }
    }

    function insertAdjacentText(w, t) {
        insert.call(this, w, document.createTextNode(t || ''))
    }

    function insertAdjacentHTML(w, h) {
        var r = document.createRange()
        r.selectNode(this)
        insert.call(this, w, r.createContextualFragment(h))
    }

    function insertAdjacentElement(w, n) {
        insert.call(this, w, n)
        return n
    }

    HTMLElement.prototype.insertAdjacentText = insertAdjacentText
    HTMLElement.prototype.insertAdjacentHTML = insertAdjacentHTML
    HTMLElement.prototype.insertAdjacentElement = insertAdjacentElement
})()

我們可以利用它設計出更快更合理的動態插入方法。下面是我的一些實現:

復制代碼 代碼如下:

//四個插入方法,對應insertAdjactentHTML的四個插入位置,名字就套用jQuery的
//stuff可以為字符串,各種節點或dom對象(一個類數組對象,便于鏈式操作?。?
//代碼比jQuery的實現簡潔漂亮吧!
    append:function(stuff){
        return  dom.batch(this,function(el){
            dom.insert(el,stuff,"beforeEnd");
        });
    },
    prepend:function(stuff){
        return  dom.batch(this,function(el){
            dom.insert(el,stuff,"afterBegin");
        });
    },
    before:function(stuff){
        return  dom.batch(this,function(el){
            dom.insert(el,stuff,"beforeBegin");
        });
    },
    after:function(stuff){
        return  dom.batch(this,function(el){
            dom.insert(el,stuff,"afterEnd");
        });
    }

它們里面都是調用了兩個靜態方法,batch與insert。由于dom對象是類數組對象,我仿效jQuery那樣為它實現了幾個重要迭代器,forEach、map與filter等。一個dom對象包含復數個DOM元素,我們就可以用forEach遍歷它們,執行其中的回調方法。

復制代碼 代碼如下:

batch:function(els,callback){
    els.forEach(callback);
    return els;//鏈式操作
},

insert方法執行jQuery的domManip方法相應的機能(dojo則為place方法),但insert方法每次處理一個元素節點,不像jQuery那樣處理一組元素節點。群集處理已經由上面batch方法分離出去了。

復制代碼 代碼如下:

insert : function(el,stuff,where){
     //定義兩個全局的東西,提供內部方法調用
     var doc = el.ownerDocument || dom.doc,
     fragment = doc.createDocumentFragment();
     if(stuff.version){//如果是dom對象,則把它里面的元素節點移到文檔碎片中
         stuff.forEach(function(el){
             fragment.appendChild(el);
         })
         stuff = fragment;
     }
     //供火狐與IE部分元素調用
     dom._insertAdjacentElement = function(el,node,where){
         switch (where){
             case 'beforeBegin':
                 el.parentNode.insertBefore(node,el)
                 break;
             case 'afterBegin':
                 el.insertBefore(node,el.firstChild);
                 break;
             case 'beforeEnd':
                 el.appendChild(node);
                 break;
             case 'afterEnd':
                 if (el.nextSibling) el.parentNode.insertBefore(node,el.nextSibling);
                 else el.parentNode.appendChild(node);
                 break;
         }
     };
      //供火狐調用
     dom._insertAdjacentHTML = function(el,htmlStr,where){
         var range = doc.createRange();
         switch (where) {
             case "beforeBegin"://before
                 range.setStartBefore(el);
                 break;
             case "afterBegin"://after
                 range.selectNodeContents(el);
                 range.collapse(true);
                 break;
             case "beforeEnd"://append
                 range.selectNodeContents(el);
                 range.collapse(false);
                 break;
             case "afterEnd"://prepend
                 range.setStartAfter(el);
                 break;
         }
         var parsedHTML = range.createContextualFragment(htmlStr);
         dom._insertAdjacentElement(el,parsedHTML,where);
     };
     //以下元素的innerHTML在IE中是只讀的,調用insertAdjacentElement進行插入就會出錯
     // col, colgroup, frameset, html, head, style, title,table, tbody, tfoot, thead, 與tr;
     dom._insertAdjacentIEFix = function(el,htmlStr,where){
         var parsedHTML = dom.parseHTML(htmlStr,fragment);
         dom._insertAdjacentElement(el,parsedHTML,where)
     };
     //如果是節點則復制一份
     stuff = stuff.nodeType ?  stuff.cloneNode(true) : stuff;
     if (el.insertAdjacentHTML) {//ie,chrome,opera,safari都已實現insertAdjactentXXX家族
         try{//適合用于opera,safari,chrome與IE
             el['insertAdjacent'+ (stuff.nodeType ? 'Element':'HTML')](where,stuff);
         }catch(e){
             //IE的某些元素調用insertAdjacentXXX可能出錯,因此使用此補丁
             dom._insertAdjacentIEFix(el,stuff,where);
         }     
     }else{
         //火狐專用
         dom['_insertAdjacent'+ (stuff.nodeType ? 'Element':'HTML')](el,stuff,where);
     }
 }

insert方法在實現火狐插入操作中,使用了W3C DOM Range對象的一些罕見方法,具體可到火狐官網查看。下面實現把字符串轉換為節點,利用innerHTML這個偉大的方法。Prototype.js稱之為_getContentFromAnonymousElement,但有許多問題,dojo稱之為_toDom,mootools的Element.Properties.html,jQuery的clean。Ext沒有這東西,它只支持傳入HTML片斷的insertAdjacentHTML方法,不支持傳入元素節點的insertAdjacentElement。但有時,我們需要插入文本節點(并不包裹于元素節點之中),這時我們就需要用文檔碎片做容器了,insert方法出場了。

復制代碼 代碼如下:

parseHTML : function(htmlStr, fragment){
    var div = dom.doc.createElement("div"),
    reSingleTag =  /^<(/w+)/s*//?>$/;//匹配單個標簽,如<li>
    htmlStr += '';
    if(reSingleTag.test(htmlStr)){//如果str為單個標簽
        return  [dom.doc.createElement(RegExp.$1)]
    }
    var tagWrap = {
        option: ["select"],
        optgroup: ["select"],
        tbody: ["table"],
        thead: ["table"],
        tfoot: ["table"],
        tr: ["table", "tbody"],
        td: ["table", "tbody", "tr"],
        th: ["table", "thead", "tr"],
        legend: ["fieldset"],
        caption: ["table"],
        colgroup: ["table"],
        col: ["table", "colgroup"],
        li: ["ul"],
        link:["div"]
    };
    for(var param in tagWrap){
        var tw = tagWrap[param];
        switch (param) {
            case "option":tw.pre  = '<select multiple="multiple">'; break;
            case "link": tw.pre  = 'fixbug<div>';  break;
            default : tw.pre  =   "<" + tw.join("><") + ">";
        }
        tw.post = "</" + tw.reverse().join("></") + ">";
    }
    var reMultiTag = /</s*([/w/:]+)/,//匹配一對標簽或多個標簽,如<li></li>,li
    match = htmlStr.match(reMultiTag),
    tag = match ? match[1].toLowerCase() : "";//解析為<li,li
    if(match && tagWrap[tag]){
        var wrap = tagWrap[tag];
        div.innerHTML = wrap.pre + htmlStr + wrap.post;
        n = wrap.length;
        while(--n >= 0)//返回我們已經添加的內容
            div = div.lastChild;
    }else{
        div.innerHTML = htmlStr;
    }
    //處理IE自動插入tbody,如我們使用dom.parseHTML('<thead></thead>')轉換HTML片斷,它應該返回
    //'<thead></thead>',而IE會返回'<thead></thead><tbody></tbody>'
    //亦即,在標準瀏覽器中return div.children.length會返回1,IE會返回2
    if(dom.feature.autoInsertTbody && !!tagWrap[tag]){
        var ownInsert = tagWrap[tag].join('').indexOf("tbody") !== -1,//我們插入的
        tbody = div.getElementsByTagName("tbody"),
        autoInsert = tbody.length > 0;//IE插入的
        if(!ownInsert && autoInsert){
            for(var i=0,n=tbody.length;i<n;i++){
                if(!tbody[i].childNodes.length )//如果是自動插入的里面肯定沒有內容
                    tbody[i].parentNode.removeChild( tbody[i] );
            }
        }
    }
    if (dom.feature.autoRemoveBlank && /^/s/.test(htmlStr) )
        div.insertBefore( dom.doc.createTextNode(htmlStr.match(/^/s*/)[0] ), div.firstChild );
    if (fragment) {
        var firstChild;
        while((firstChild = div.firstChild)){ // 將div上的節點轉移到文檔碎片上!
            fragment.appendChild(firstChild);
        }
        return fragment;
    }
    return div.children;
}

嘛,基本上就是這樣,運行起來比jQuery快許多,代碼實現也算優美,至少沒有像jQuery那樣亂成一團。jQuery還有四個反轉方法。下面是jQuery的實現:

復制代碼 代碼如下:

jQuery.each({
    appendTo: "append",
    prependTo: "prepend",
    insertBefore: "before",
    insertAfter: "after",
    replaceAll: "replaceWith"
}, function(name, original){
    jQuery.fn[ name ] = function( selector ) {//插入物(html,元素節點,jQuery對象)
        var ret = [], insert = jQuery( selector );//將插入轉變為jQuery對象
        for ( var i = 0, l = insert.length; i < l; i++ ) {
            var elems = (i > 0 ? this.clone(true) : this).get();
            jQuery.fn[ original ].apply( jQuery(insert[i]), elems );//調用四個已實現的插入方法
            ret = ret.concat( elems );
        }
        return this.pushStack( ret, name, selector );//由于沒有把鏈式操作的代碼分離出去,需要自行實現
    };
});

我的實現:

復制代碼 代碼如下:

dom.each({
    appendTo: 'append',
    prependTo: 'prepend',
    insertBefore: 'before',
    insertAfter: 'after'
},function(method,name){
    dom.prototype[name] = function(stuff){
        return dom(stuff)[method](this);
    };
});

大致的代碼都給出,大家可以各取所需。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品亚洲综合天堂夜夜| 国产精品久久久久久久电影| 精品久久国产精品| 日韩在线观看网站| 色爱av美腿丝袜综合粉嫩av| 欧美亚洲国产视频小说| 51色欧美片视频在线观看| 91久久国产精品91久久性色| 久久在线观看视频| 国产精品第一区| 精品无人国产偷自产在线| 91成人精品网站| 91国产视频在线| 欧美激情手机在线视频| 精品国产网站地址| 奇米影视亚洲狠狠色| 97成人超碰免| 国产精品日韩专区| 亚洲大胆人体视频| 欧美在线影院在线视频| 亚洲欧美综合区自拍另类| 亚洲欧美自拍一区| 97视频在线观看网址| 欧美一级淫片aaaaaaa视频| 成人性生交大片免费看小说| 精品亚洲一区二区三区四区五区| 亚洲精品资源美女情侣酒店| 国产suv精品一区二区三区88区| 日本韩国在线不卡| 国产精品国产三级国产aⅴ浪潮| 日韩国产在线看| 亚洲精品久久久久久久久久久| 日韩中文字幕在线免费观看| 97在线观看视频| 亚洲a一级视频| 久久久国产一区二区三区| 欧美大秀在线观看| 久久成人av网站| 国产一区二区日韩精品欧美精品| 久久久亚洲欧洲日产国码aⅴ| 日韩久久精品成人| 国产成人一区二区三区| 欧美老女人在线视频| 亚洲色图综合久久| 国产999视频| 91国产精品电影| 国产成人福利夜色影视| 亚洲美女又黄又爽在线观看| 亚洲人成伊人成综合网久久久| 少妇高潮久久77777| 综合国产在线观看| 色综合久久久久久中文网| 欧美激情精品久久久久久| 精品国产成人av| 国产精品男人爽免费视频1| 欧美电影在线观看完整版| 成人免费视频网址| 中文字幕成人精品久久不卡| 日韩视频免费大全中文字幕| 日韩中文视频免费在线观看| 亚洲国产精品va在线看黑人动漫| 亚洲色图欧美制服丝袜另类第一页| 日韩欧美在线视频免费观看| 精品国产一区久久久| 78m国产成人精品视频| 国产婷婷成人久久av免费高清| 亚洲人午夜精品| 国产精品视频yy9099| 久久久视频在线| 国产激情久久久久| 亚洲性生活视频| 日韩中文理论片| 亚洲a∨日韩av高清在线观看| 国产精品视频资源| 国产精品电影观看| 性欧美办公室18xxxxhd| 欧美日韩在线观看视频小说| 亚洲精品成人网| 亚洲美女黄色片| 日韩电影中文字幕在线观看| 亚洲日韩欧美视频| 国产精品视频午夜| 色阁综合伊人av| 国产精品夜色7777狼人| 亚洲国产精品一区二区三区| 日韩第一页在线| 欧美激情国内偷拍| 91av中文字幕| 亚洲国产美女精品久久久久∴| 国产精品久久久久久久久男| 久久av红桃一区二区小说| 亚洲欧美日韩久久久久久| 中文字幕日韩在线观看| 国产香蕉精品视频一区二区三区| 久久免费高清视频| 国产精品美女网站| 欧美性猛交xxxxx免费看| 日韩精品在线观看网站| 国产精品久久久999| 性金发美女69hd大尺寸| 欧美电影免费播放| 久久久久亚洲精品成人网小说| 91精品国产高清久久久久久91| 国产成人精品久久二区二区91| 精品国产拍在线观看| 亚洲国产精品va在线看黑人| 欧美精品免费播放| 亚洲国产精品人人爽夜夜爽| 色吧影院999| 国产精品都在这里| 91色琪琪电影亚洲精品久久| 久久精品99国产精品酒店日本| 日韩在线视频免费观看高清中文| 久久久精品国产一区二区| 亚洲国产欧美精品| 国产一区二区三区久久精品| 欧美一级黑人aaaaaaa做受| 欧美自拍视频在线| 91av福利视频| 伊人激情综合网| 欧美专区在线播放| 日韩综合视频在线观看| 亚洲激情视频网| 91精品中国老女人| 日韩中文字幕在线观看| 亚洲国产精品网站| 亚洲免费影视第一页| 亚洲女人天堂成人av在线| 欧美激情在线观看视频| 一本色道久久88亚洲综合88| 岛国精品视频在线播放| 国产69久久精品成人看| 日本精品视频在线播放| 亚洲日本aⅴ片在线观看香蕉| 国产一区二区三区精品久久久| 中文字幕亚洲国产| 久久久久日韩精品久久久男男| 日本成人在线视频网址| 亚洲国产成人精品久久久国产成人一区| 亚洲精品日韩丝袜精品| 欧美激情性做爰免费视频| 91成人免费观看网站| 久久视频在线免费观看| 国产网站欧美日韩免费精品在线观看| 欧美激情视频三区| 久久网福利资源网站| 狠狠色狠色综合曰曰| 在线观看91久久久久久| 91亚洲精品久久久久久久久久久久| 日韩欧美999| 久久国产精品免费视频| 精品国产自在精品国产浪潮| 欧美激情免费在线| 久久艹在线视频| 一本色道久久综合亚洲精品小说| 中文字幕在线日韩| 亚洲毛片在线免费观看| 日本一区二区在线免费播放| 欧美黄色片在线观看| 欧美成人亚洲成人日韩成人| 26uuu日韩精品一区二区| 精品久久久久久国产| 久久精品国产v日韩v亚洲| 亚洲激情视频在线播放|