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

首頁 > 編程 > JavaScript > 正文

AngularJS創建自定義指令的方法詳解

2019-11-20 08:36:11
字體:
來源:轉載
供稿:網友

本文實例講述了AngularJS創建自定義指令的方法。分享給大家供大家參考,具體如下:

這是一篇譯文,來自angular開發者說明的指令。主要面向已經熟悉angular開發基礎的開發者。這篇文檔解釋了什么情況下需要創建自己的指令,和如何去創建指令。

什么是指令

從一個高的層面來講,指令是angular $compile服務的說明,當特定的標簽(屬性,元素名,或者注釋) 出現在DOM中的時候,它讓編譯器附加指定的行為到DOM上。

這個過程是很簡單的。angular內部有很用這樣自帶的指令,比如說ngBind, ngView,就像你創建控制器和服務一樣,你也可以創建自己的指令。當angular啟動的時候,Angular的編譯器分析html去匹配指令,這允許指令注冊行為或者改變DOM。

匹配指令

在寫指令之前,我們首先需要知道的是angular是如何匹配到一個指令的,在以下的例子我們說input元素匹配到ngModel指令.

<input ng-model="foo">

下面這種方法同樣也會匹配到ngModel:

<input data-ng:model="foo">

Angular會規范化一個元素的標簽名和屬性名,以便確定哪一個元素匹配到哪一個指令。我們在js中是通過使用規范化后的駝峰式的名字來引用指令(比如ngModel)。在HTML中常常使用'-'劃定的屬性名字來調用指令(比如說ng-model).

規范化的處理過程:

-去掉元素或屬性上面的x-和data-的前綴
-轉化':','-'和‘_-'形式的命名為駝峰式拼寫

以下例子展示了用不同的方式匹配到ngBind指令

<span ng-bind="name"></span> <br/><span ng:bind="name"></span> <br/><span ng_bind="name"></span> <br/><span data-ng-bind="name"></span> <br/><span x-ng-bind="name"></span> <br/>

Best Practice: 優先使用'-'格式的命名(比如說ng-bind匹配ngBind)。如果你想在HTML驗證工具中通過,你可以用'data-'前綴的方式(比如data-ng-bind)。其他格式的命名是因為歷史遺留的原因存在,避免使用它們。

$compile服務可以基于元素的名字,屬性名,類名,和注釋來匹配指令

所有Angular內部提供的指令都匹配屬性名,標簽名,注釋,或者類名。以下不同的方式都可以被解析到

<my-dir></my-dir><span my-dir="exp"></span><!-- directive: my-dir exp --><span class="my-dir: exp;"></span>

Best Practice: 優先利用標簽名和屬性名的方式使用指令。這樣子更容易理解指定的元素匹配到了哪個元素。

Best Practice: 注釋的方式通常被用在DOM API限制創建跨越多個元素的指令,比如說table元素,限制重復嵌套,這樣就要用注釋的方式。在AngularJS 1.2版本中,通過使用ng-repeat-start 和 ng-repeat-end 作為一個更好的方案來解決這個問題。在可能的情況下,推薦使用這種方式。

文本和屬性的綁定

在編譯過程中,編譯器會使用$interpolate服務來檢測匹配到的文本和屬性值是否包含內嵌表達式。這些表達式被注冊為watches,可以在digest循環時被更新。

<a ng-href="img/{{username}}.jpg">Hello {{username}}!</a>

ngAttr屬性的綁定

瀏覽器有些時候會對它認為合法的屬性值非常的挑剔(就是某些元素的屬性是不可以任意賦值的,否則會報錯)。

比如:

<svg> <circle cx="{{cx}}"></circle></svg>

使用這樣的寫法時,我們會發現控制臺中報錯Error: Invalid value for attribute cx="{{cx}}". .這是由于SVG DOM API的限制,你不能簡單的寫為cx="{{cx}}".

使用ng-attr-cx 可以解決這個問題

如果一個綁定的屬性使用ngAttr前綴(或者ng-attr), 那么在綁定的時候將會被應用到相應的未前綴化的屬性,這種方式允許你綁定到需要馬上被瀏覽器處理的屬性上面(比如SVG元素的circle[cx]屬性)。

所以,我們可以這樣寫來修復以上的問題:

<svg> <circle ng-attr-cx="{{cx}}"></circle></svg>

創建指令

首先我們來談論下注冊指令的API,跟controller一樣,指令是注冊在module上,不同的是,指令是通過module.directive API來注冊的。module.directive接受的是一個規范化的名字和工廠函數,這個工廠函數返回一個包含不同配置的對象,這個對象用來告訴$compile服務如何進行下一步處理。

工廠函數僅在編譯器第一次匹配到指令的時候調用一次。通常在工廠函數中執行初始化的工作。該函數使用$injector.invoke調用,所以它可以像controller一樣進行依賴注入。

Best Practice: 優先返回一個定義好的對象,而不是返回一個函數。

接下來,我們先會了解一些常見的例子,然后再深入了解不同的配置項的原理和編譯過程。

Best Practice: 為了避免與某些未來的標準命名沖突,最好前綴化你自己的指令,比如你創建一個<carousel>指令,它可能會產生沖突,加入HTML7引入相同的元素。推薦使用兩三個單詞的前綴(比如btfCarousel),同樣不能使用ng或者其他可能與angular未來版本起沖突的前綴。

以下的例子中,我們統一使用my前綴。

模板擴展的指令

當你有大量代表客戶信息的模板。這個模板在你的代碼中重復了很多次,當你改變一個地方的時候,你不得不在其他地方同時改動,這時候,你就要使用指令來簡化你的模板。

我們來創建一個指令,簡單的時候靜態模板來替換它的內容。

<div ng-controller="Ctrl">  <div my-customer></div> </div>

JS

angular.module('docsSimpleDirective', []) .controller('Ctrl', function($scope) { $scope.customer = {  name: 'Naomi',  address: '1600 Amphitheatre' }; }) .directive('myCustomer', function() { return {  template: 'Name: {{customer.name}} Address: {{customer.address}}' }; });

注意我們這里做了一些綁定,$compile編譯鏈接<div my-customer> </div>之后,它將會匹配子元素的指令。這意味著你可以組合一些指令。以下例子中你會看到如何做到這一點。

這個例子中,我們直接在template配置項里寫上模板,但是隨著模板大小的增加,這樣非常不優雅。

Best Practice: 除非你的模板非常小,否則更好的是分割成單獨的hmtl文件,然后使用templateUrl選項來加載。

假如你熟悉ngInclude,templateUrl跟它非常類似?,F在我們使用templateUrl方式重寫上面的例子:

<div ng-controller="Ctrl">  <div my-customer></div> </div>

JS:

angular.module('docsTemplateUrlDirective', []) .controller('Ctrl', function($scope) { $scope.customer = {  name: 'Naomi',  address: '1600 Amphitheatre' }; }) .directive('myCustomer', function() { return {  templateUrl: 'my-customer.html' }; });

my-customer.html

Name: {{customer.name}} Address: {{customer.address}}

非常好,但是如果我們想讓我們的指令匹配標簽名<my-customer>? 如果我們只是簡單的把<my-customer>元素放在hmtl上面,會發現沒有效果。

Note: 創建指令的時候,默認僅使用屬性的方式。為了創建一個能由元素名字觸發的指令,你需要用到restrict配置。

restrict配置可以按如下方式設置:
-'A' 僅匹配屬性名字
-'E' 僅匹配元素名字
-'AE' 可以匹配到屬性名字或者元素名

所以,我們可以使用 restrict: 'E'配置我們指令。

<div ng-controller="Ctrl">  <div my-customer></div> </div>

JS

angular.module('docsTemplateUrlDirective', []) .controller('Ctrl', function($scope) { $scope.customer = {  name: 'Naomi',  address: '1600 Amphitheatre' }; }) .directive('myCustomer', function() { return {  restrict: 'E',  templateUrl: 'my-customer.html' }; });

my-customer.html

Name: {{customer.name}} Address: {{customer.address}}

Note: 什么時候使用屬性名或元素名呢? 當創建一個含有自己模板的組件的時候,需要使用元素名,如果僅僅是為已有的元素添加功能的話,使用屬性名。

使用元素名做為myCustomer指令是非常正確的決定,因為你不是用一些'customer'行為來點綴元素,而是定義一個具有自己行為的元素作為customer組件。

隔離指令的作用域

上面我們的myCustomer指令已經非常好了,但是它有個致命的缺陷,我們在給定的作用域內僅能使用一次。

它現在的實現是,我們每次重用該指令的時候都要為它新創一個控制器。

<div ng-controller="NaomiCtrl"> <my-customer></my-customer></div><hr><div ng-controller="IgorCtrl"> <my-customer></my-customer></div>

JS

angular.module('docsScopeProblemExample', []) .controller('NaomiCtrl', function($scope) { $scope.customer = {  name: 'Naomi',  address: '1600 Amphitheatre' }; }) .controller('IgorCtrl', function($scope) { $scope.customer = {  name: 'Igor',  address: '123 Somewhere' }; }) .directive('myCustomer', function() { return {  restrict: 'E',  templateUrl: 'my-customer.html' }; });

my-customer.html

Name: {{customer.name}} Address: {{customer.address}}

這很明顯不是一個好的解決方案。

我們想要做的是能夠把指令的作用域與外部的作用域隔離開來,然后映射外部的作用域到指令內部的作用域。可以通過創建isolate scope來完成這個目的。這樣的話,我們使用指令的scope配置。

<div ng-controller="Ctrl"> <my-customer customer="naomi"></my-customer> <hr> <my-customer customer="igor"></my-customer></div>

JS

angular.module('docsIsolateScopeDirective', []) .controller('Ctrl', function($scope) { $scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' }; $scope.igor = { name: 'Igor', address: '123 Somewhere' }; }) .directive('myCustomer', function() { return {  restrict: 'E',  scope: {  customer: '=customer'  },  templateUrl: 'my-customer.html' }; });

my-customer.html

Name: {{customer.name}} Address: {{customer.address}}

首先看hmtl,第一個<my-customer>綁定內部作用域的customer到naomi。這個naomi我們在控制器中已經定義好了。第二個是綁定customer到igor。

現在看看scope是如何配置的。

//...scope: { customer: '=customer'},//...

屬性名(customer)是myCustomer指令上isolated scope的變量名。它的值(=customer)告訴編譯器綁定到customer屬性。

Note: 指令作用域配置中的'=attr'屬性名是被規范化過后的名字,比如要綁定<div bind-to-this="thing">中的屬性,你就要使用'=bindToThis'的綁定。

對于屬性名和你想要綁定的值的名字一樣,你可以使用這樣的快捷語法:

//...scope: { // same as '=customer' customer: '='},//...

使用isolated scope還有另外一個用處,那就是可以綁定不同的數據到指令內部的作用域。

在我們的例子中,我們可以添加另外一個屬性vojta到我們的作用域,然后在我們的指令模板中訪問它。

<div ng-controller="Ctrl">  <my-customer customer="naomi"></my-customer></div>

JS

angular.module('docsIsolationExample', []) .controller('Ctrl', function($scope) { $scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' }; $scope.vojta = { name: 'Vojta', address: '3456 Somewhere Else' }; }) .directive('myCustomer', function() { return {  restrict: 'E',  scope: {  customer: '=customer'  },  templateUrl: 'my-customer-plus-vojta.html' }; });

my-customer-plus-vojta.html

Name: {{customer.name}} Address: {{customer.address}}<hr>Name: {{vojta.name}} Address: {{vojta.address}}

注意到,{{vojta.name}}和{{vojta.address}}都是空的,意味著他們是undefined, 雖然我們在控制器中定義了vojta,但是在指令內部訪問不到。

就像它的名字暗示的一樣, 指令的isolate scope隔離了除了你添加到作用域:{}對象中的數據模型外的一切東西。這對于你要建立一個可重復使用的組件是非常有用的,因為它阻止了除了你想要傳入的數據模型外其他東西改變你數據模型的狀態。

Note: 正常情況下,作用域是原型繼承自父作用域。但是isolate scope沒有這樣的繼承。

Best Practice: 當你想要使你的組件在應用范圍內可重用,那么使用scope配置去創建一個isolate scopes

創建一個操作DOM的指令

在這個例子中,我們會創建一個顯示當前時間的指令,每秒一次更新DOM以正確的顯示當前的時間。

指令修改DOM通常是在link配置中,link選項接受一個帶有如下標簽的函數function link(scope,element,attrs) {...}其中:

-scope是angular scope對象
-element指令匹配的jqLite封裝的元素(angular內部實現的類jquery的庫)
-attrs是一個帶有規范化后屬性名字和相應值的對象

在我們的link函數中,我們更新顯示時間每秒一次,或者當用戶改變指定綁定的時間格式字符串的時候。我們也要移除定時器,當指令被刪除的時候,以避免引入內存泄露。

<div ng-controller="Ctrl2"> Date format: <input ng-model="format"> <hr/> Current time is: <span my-current-time="format"></span></div>

JS

angular.module('docsTimeDirective', []) .controller('Ctrl2', function($scope) { $scope.format = 'M/d/yy h:mm:ss a'; }) .directive('myCurrentTime', function($timeout, dateFilter) { function link(scope, element, attrs) {  var format,   timeoutId;  function updateTime() {  element.text(dateFilter(new Date(), format));  }  scope.$watch(attrs.myCurrentTime, function(value) {  format = value;  updateTime();  });  function scheduleUpdate() {  // save the timeoutId for canceling  timeoutId = $timeout(function() {   updateTime(); // update DOM   scheduleUpdate(); // schedule the next update  }, 1000);  }  element.on('$destroy', function() {  $timeout.cancel(timeoutId);  });  // start the UI update process.  scheduleUpdate(); } return {  link: link }; });

這里有很多東西值得注意的,就像module.controller API, module.directive中函數參數是依賴注入,因此,我們可以在Link函數內部使用$timeout和dataFilter服務。

我們注冊了一個事件element.on('$destroy', ...), 是什么觸發了這個$destory事件呢?

AngularJS會觸發一些特定的事件,當一個被angular編譯過的DOM元素被移除的時候,它會觸發一個$destory事件,同樣的,當一個angular作用域被移除的時候,它會向下廣播$destory事件到所有監聽的作用域。

通過監聽事件,你可以移除可能引起內存泄露的事件監聽器,注冊在元素和作用域上的監聽器在它們被移除的時候,會自動會清理掉,但是假如注冊一個事件在服務或者沒有被刪除的DOM節點上,你就必須手工清理,否則會有內存泄露的風險。

Best Practice:執行被移除的時候應該做一些清理的操作, 可以使用element.on('$destroy', ...)或者scope.on('$destroy', ...)來運行解除綁定的函數,

創建包裹其他元素的指令

我們現在已經實現了,使用isolate scopes傳遞數據模型到指令里面。但是有時候我們需要能夠傳遞一整個模板而不是字符串或者對象。讓我們通過創建'dialog box'組件來說明。這個'dialog box'組件應該能夠包裹任意內容。

要實現這個,我們使用transclude配置

<div ng-controller="Ctrl"> <my-dialog>Check out the contents, {{name}}!</my-dialog></div>

JS

angular.module('docsTransclusionDirective', []) .controller('Ctrl', function($scope) { $scope.name = 'Tobias'; }) .directive('myDialog', function() { return {  restrict: 'E',  transclude: true,  templateUrl: 'my-dialog.html' }; });

my-dialog.html

<div class="alert" ng-transclude></div>

這個transclude配置用來干嘛呢? transclude使帶有這個配置的指令的內容能夠訪問指令外部的作用域。

參照以下例子,注意到我們增加了一個link函數,在這個link函數內部我們重定義了name屬性的值為Jeff,那么現在這個{{name}}會被解析成哪個值呢?

<div ng-controller="Ctrl"> <my-dialog>Check out the contents, {{name}}!</my-dialog></div>

JS

angular.module('docsTransclusionDirective', []) .controller('Ctrl', function($scope) { $scope.name = 'Tobias'; }) .directive('myDialog', function() { return {  restrict: 'E',  transclude: true,  templateUrl: 'my-dialog.html',  link: function (element, scope) {  scope.name = 'Jeff';  } }; });

my-dialog.html

<div class="alert" ng-transclude></div>

一般,我們會認為{{name}}會被解析為Jeff,然而這里,我們看到這個例子中的{{name}}還是被解析成了Tobias.

transclude配置改變了指令相互嵌套的方式,他使指令的內容擁有任何指令外部的作用域,而不是內部的作用域。為了實現這個,它給指令內容一次訪問外部作用域的機會。

這樣的行為對于包裹內容的指令是非常有意義的。因為如果不這樣的話,你就必須分別傳入每個你需要使用的數據模型。如果你需要傳入每個要使用的數據模型,那么你就無法做到適應各種不同內容的情況。

Best Practice: 僅當你要創建一個包裹任意內容的指令的時候使用transclude:true。

下一步,我們增加一個按鈕到'dialog box'組件里面,允許用戶使用指令綁定自己定義的行為。

<div ng-controller="Ctrl">  <my-dialog ng-hide="dialogIsHidden" on-close="dialogIsHidden = true">  Check out the contents, {{name}}!  </my-dialog></div>

JS

angular.module('docsIsoFnBindExample', []) .controller('Ctrl', function($scope, $timeout) { $scope.name = 'Tobias'; $scope.hideDialog = function () {  $scope.dialogIsHidden = true;  $timeout(function () {  $scope.dialogIsHidden = false;  }, 2000); }; }) .directive('myDialog', function() { return {  restrict: 'E',  transclude: true,  scope: {  'close': '&onClose'  },  templateUrl: 'my-dialog-close.html' }; });

my-dialog-close.html

<div class="alert"> <a href class="close" ng-click="close()">×</a> <div ng-transclude></div></div>

我們想要通過在指令的作用域上調用,來運行我們傳遞進去的函數,但是這個函數是運行在定義時候的上下文(js通常都是這樣子的)。

先前我們看到如何scope配置使用'=prop',但是在上文的例子中,我們使用'&prop','&'綁定開放了一個函數到isolated scope,允許 isolated scope調用它,同時維持原來函數的作用域(這里的作用域都是指$scope)。所以當一個用戶點擊x時候,就會運行Ctrl控制器的close函數。

Best Practice: 當你的指令想要開放一個API去綁定特定的行為,在scope配置中使用'&prop'.

創建一個添加事件監聽器的指令

先前,我們使用link函數創建一個操作DOM元素的指令,基于上面的例子,我們創建一個在元素上添加事件監聽的指令。

舉個例子,假如我們想要創建一個讓用戶可拖拽的元素,該怎么做呢?

Drag ME

JS

angular.module('dragModule', []). directive('myDraggable', function($document) { return function(scope, element, attr) {  var startX = 0, startY = 0, x = 0, y = 0;  element.css({  position: 'relative',  border: '1px solid red',  backgroundColor: 'lightgrey',  cursor: 'pointer'  });  element.on('mousedown', function(event) {  // Prevent default dragging of selected content  event.preventDefault();  startX = event.screenX - x;  startY = event.screenY - y;  $document.on('mousemove', mousemove);  $document.on('mouseup', mouseup);  });  function mousemove(event) {  y = event.screenY - startY;  x = event.screenX - startX;  element.css({   top: y + 'px',   left: x + 'px'  });  }  function mouseup() {  $document.unbind('mousemove', mousemove);  $document.unbind('mouseup', mouseup);  } } });

創建相互通信的指令

你可以通過在模板使用指令來組合任何指令。

有時候,你想要一個指令從其他的指令上面創建

想象你想要一個帶有tab的容器,容器的內容對應于激活的tab。

<my-tabs>  <my-pane title="Hello">  <h5 id="creating-custom-directives_source_hello">Hello</h5>  <p>Lorem ipsum dolor sit amet</p>  </my-pane>  <my-pane title="World">  <h5 id="creating-custom-directives_source_world">World</h5>  <em>Mauris elementum elementum enim at suscipit.</em>  <p><a href ng-click="i = i + 1">counter: {{i || 0}}</a></p>  </my-pane></my-tabs>

JS

angular.module('docsTabsExample', []) .directive('myTabs', function() { return {  restrict: 'E',  transclude: true,  scope: {},  controller: function($scope) {  var panes = $scope.panes = [];  $scope.select = function(pane) {   angular.forEach(panes, function(pane) {   pane.selected = false;   });   pane.selected = true;  };  this.addPane = function(pane) {   if (panes.length == 0) {   $scope.select(pane);   }   panes.push(pane);  };  },  templateUrl: 'my-tabs.html' }; }) .directive('myPane', function() { return {  require: '^myTabs',  restrict: 'E',  transclude: true,  scope: {  title: '@'  },  link: function(scope, element, attrs, tabsCtrl) {  tabsCtrl.addPane(scope);  },  templateUrl: 'my-pane.html' }; });

my-tabs.html

<div class="tabbable"> <ul class="nav nav-tabs"> <li ng-repeat="pane in panes" ng-class="{active:pane.selected}">  <a href="" ng-click="select(pane)">{{pane.title}}</a> </li> </ul> <div class="tab-content" ng-transclude></div></div>

my-pane.html

<div class="tab-pane" ng-show="selected" ng-transclude></div>

myPane指令有一個require:'^myTabs'的配置,當指令使用這個配置,$compile服務叫myTabs的指令并獲取它的控制器實例,如果沒有找到,將會拋出一個錯誤。'^'前綴意味著指令在它的父元素上面搜索控制器(沒有'^'前綴的話,指令默認會在自身的元素上面搜索指定的指令)。

這里myTabs的控制器是來自何處呢?通過使用controller配置可以為指令指定一個控制器, 上問例子中myTab就是使用這個配置。就像ngController, 這個配置為指令的模板綁定了一個控制器。

再看我們的myPane's定義,注意到link函數的最后一個參數: tabCtrl,當一個指令包含另一個指令(通過require方式),它會接收該指令的控制器實例作為link函數的第四個參數,利用這個,myPane可以調用myTabs的addPane函數。

精明的讀者可能想知道link跟controller之間的區別,最基本的區別就是控制器開放一個API(就是這個控制器實例可以被其他實例讀取到),link函數可以通過require與控制器交互。

Best Practice: 當你要開放一個API給其他指令的時候使用控制器,否則使用link函數。

總結

這里我們講解了一個些指令的主要使用案例。每一個都可以作為你創建自己指令的很好的起點。

如果你想更深入的了解編譯的處理過程,可以查看compiler guide相關內容

$compile API頁面有directive每個配置項的具體解釋,可以參閱。

希望本文所述對大家AngularJS程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美亚洲日本网站| 亚洲精品自拍视频| 亚洲永久在线观看| 欧美一级片在线播放| 亚洲精品99久久久久| 欧美日韩国产色视频| 欧美亚洲在线视频| 精品人伦一区二区三区蜜桃网站| 日韩精品视频免费| 亚洲女成人图区| 国产精品日韩欧美综合| 国产欧美一区二区三区四区| 色悠悠久久久久| 国产精品美乳在线观看| 青青草99啪国产免费| 久久久在线免费观看| 亚洲成人久久久| 精品视频www| 91av成人在线| 成人在线视频网| 一本色道久久88亚洲综合88| 国产一区二区三区视频在线观看| 精品露脸国产偷人在视频| 日本精品久久中文字幕佐佐木| 国产成人高潮免费观看精品| 国产精品九九九| 日韩在线观看免费高清完整版| 亚洲国产私拍精品国模在线观看| 国产欧美日韩最新| 久久噜噜噜精品国产亚洲综合| 最近2019免费中文字幕视频三| 在线观看精品国产视频| 亚洲少妇中文在线| 国产精品色婷婷视频| 色综合色综合网色综合| 欧美成人免费va影院高清| 色琪琪综合男人的天堂aⅴ视频| 亚洲欧美中文日韩在线| 精品国产欧美一区二区三区成人| 欧美成人激情视频免费观看| 中文字幕亚洲情99在线| 亚洲精品狠狠操| 欧美www视频在线观看| 亚洲国产精品中文| 国产成人极品视频| 在线播放日韩欧美| 一区二区三欧美| 国产亚洲欧美视频| 国产日韩精品在线播放| 亚洲国产精品系列| 神马久久久久久| 国产精品 欧美在线| 亚洲精品狠狠操| 国产精品香蕉国产| 在线观看欧美日韩国产| 超碰97人人做人人爱少妇| 欧美精品18videosex性欧美| 日韩网站免费观看| 伊人久久久久久久久久| 95av在线视频| 久久久久久久亚洲精品| 国产精品视频在线播放| 国产精品欧美亚洲777777| 欧美精品久久久久| 国产美女精品视频| 九九热视频这里只有精品| 国产精品激情av在线播放| 国产日韩在线观看av| 日韩精品一二三四区| 日韩网站免费观看高清| 欧美成人免费va影院高清| 成人在线视频福利| 欧美最猛性xxxx| 国产suv精品一区二区| 91理论片午午论夜理片久久| 色综合久久久久久中文网| 欧美成人激情视频免费观看| 日韩电影大片中文字幕| 国产精品网站视频| 久久久人成影片一区二区三区| 欧美激情第1页| 日本亚洲欧美三级| 精品伊人久久97| 九色成人免费视频| 日韩在线观看av| 亚洲国产精品va在线| 中文字幕精品影院| 日韩av色在线| 中文字幕亚洲欧美在线| 欧美在线观看日本一区| 午夜精品99久久免费| 欧美激情喷水视频| 国产精品一区二区三区久久| 国产成人aa精品一区在线播放| 色偷偷91综合久久噜噜| 欧美成人在线影院| 亚洲网在线观看| 清纯唯美日韩制服另类| 久久久久久国产精品久久| 尤物99国产成人精品视频| 久久天天躁日日躁| 黄色一区二区在线| 国产脚交av在线一区二区| 在线精品91av| 国产精品一区二区三区毛片淫片| 777午夜精品福利在线观看| 亚洲激情在线视频| 亚洲tv在线观看| 亚洲一区二区三区四区在线播放| 久精品免费视频| 91精品免费久久久久久久久| 欧美电影院免费观看| 国产精品成人一区二区三区吃奶| 精品女厕一区二区三区| 国产色综合天天综合网| 国产性猛交xxxx免费看久久| 色噜噜狠狠狠综合曰曰曰88av| 狠狠躁18三区二区一区| 欧美日韩ab片| 亚洲伊人久久大香线蕉av| 6080yy精品一区二区三区| 日韩资源在线观看| 中文字幕亚洲字幕| 2020欧美日韩在线视频| 搡老女人一区二区三区视频tv| 成人免费观看网址| 亚洲天堂av在线播放| 精品亚洲夜色av98在线观看| 91精品国产91| 国产精品99免视看9| 亚洲精品一区二三区不卡| 中文字幕久久久av一区| 国产成人精品999| 国产在线精品成人一区二区三区| 欧美乱大交xxxxx另类电影| 精品久久久久久国产| 日本一本a高清免费不卡| 亚洲欧美日韩一区二区三区在线| 久久精品99久久香蕉国产色戒| 久久精品国产一区二区三区| 亚洲毛茸茸少妇高潮呻吟| 国产精品三级美女白浆呻吟| 日韩精品中文字幕在线| 国产精品第10页| 欧美成人久久久| 91中文精品字幕在线视频| 日韩一区二区三区xxxx| 69av在线播放| 91久久久精品| 国产精品久久久久久影视| 日韩av中文在线| 91亚洲精品久久久久久久久久久久| 日韩欧美在线国产| 国产97人人超碰caoprom| 伊人久久男人天堂| 亚洲欧洲在线播放| 亚洲最大福利视频网| 亚洲人成电影在线播放| 成人在线小视频| 97国产在线视频| 中文字幕九色91在线| 在线精品国产成人综合| 久久亚洲精品成人| 国产精品免费福利|