成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

深入了解Vue中的自定義指令

深入了解Vue中的自定義指令

前端(vue)入門到精通課程:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調試工具:點擊使用

準備:自定義指令介紹

除了核心功能默認內置的指令 (v-modelv-show等),Vue 也允許注冊自定義指令。注意,在 Vue2.0 中,代碼復用和抽象的主要形式是組件。然而,有的情況下,你仍然需要對普通 DOM 元素進行底層操作,這時候就會用到自定義指令。【學習視頻分享:vue視頻教程、web前端視頻】

作為使用Vue的開發者,我們對Vue指令一定不陌生,諸如v-modelv-onv-forv-if等,同時Vue也為開發者提供了自定義指令的api,熟練的使用自定義指令可以極大的提高了我們編寫代碼的效率,讓我們可以節省時間開心的摸魚~

對于Vue的自定義指令相信很多同學已經有所了解,自定義指令的具體寫法這里就不細講了,官方文檔很詳細。 但是不知道各位同學有沒有這種感覺,就是這個技術感覺很方便,也不難,我也感覺學會了,就是不知道如何去應用。這篇文檔就是為了解決一些同學的這些問題才寫出來的。

PS:這次要講的自定義指令我們主要使用的是vue2.x的寫法,不過vue3.x不過是幾個鉤子函數有所改變,只要理解每個鉤子函數的含義,兩者的用法差別并不大。

試煉:實現v-mymodel

我的上篇文章說到要自己實現一個v-model指令,這里使用v-myodel模擬一個簡易版的,順便再領不熟悉的同學熟悉一下自定義指令的步驟和注意事項。

定義指令

首先梳理思路:原生input控件與組件的實現方式需要區分,input的實現較為簡單,我們先實現一下input的處理。 首先我們先定義一個不做任何操作的指令

Vue.directive('mymodel', {         //只調用一次,指令第一次綁定到元素時調用。在這里可以進行一次性的初始化設置。         bind(el, binding, vnode, oldVnode) {         },         //被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中),需要父節點dom時使用這個鉤子         inserted(el, binding, vnode, oldVnode) {         },         //所在組件的 VNode 更新時調用,**但是可能發生在其子 VNode 更新之前**。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細的鉤子函數參數見下)。         update(el, binding, vnode, oldVnode) {         },         //指令所在組件的 VNode **及其子 VNode** 全部更新后調用。         componentUpdated(el, binding, vnode, oldVnode) {         },         只調用一次,指令與元素解綁時調用。         unbind(el, binding, vnode, oldVnode) {         }, })
登錄后復制

上面的注釋中詳細的說明了各個鉤子函數的調用時機,因為我們是給組件上添加input事件和value綁定,因此我們在bind這個鉤子函數中定義即可。所以我們把其他的先去掉,代碼變成這樣。

Vue.directive('mymodel', {         //只調用一次,指令第一次綁定到元素時調用。在這里可以進行一次性的初始化設置。         bind(el, binding, vnode, oldVnode) {          } })
登錄后復制

簡單說一下bind函數的幾個回調參數,el是指令綁定組件對應的dombinding是我們的指令本身,包含namevalueexpressionarg等,vnode就是當前綁定組件對應的vnode結點,oldVnode就是vnode更新前的狀態。

接下來我們要做兩件事:

  • 綁定input事件,同步inputvalue值到外部
  • value值綁定,監聽value的變化,更新到inputvalue

這對于input原生組件比較容易實現:

//第一步,添加inout事件監聽 el.addEventListener('input', (e) => {    //context是input所在的父組件,這一步是同步數據    vnode.context[binding.expression] = e.target.value; }) //監聽綁定的變量 vnode.context.$watch(binding.expression, (v) => {      el.value = v; })
登錄后復制

這里解釋一下上面的代碼,vnode.context是什么呢,他就是我們指令所在組件的上下文環境,可以理解就是指令綁定的值所在的組件實例。不熟悉vnode結構的同學建議先看一下官方的文檔,不過文檔描述的比較簡單,不是很全面,所以最好在控制臺log一下vnode的對象看一下它具體的結構,這很有助于我們封裝自定義指令,對理解Vue原理也很有幫助。

我們可以通過context[binding.expression]獲取v-model上到綁定的值,同樣可以修改它。上面的代碼中我們首先通過在添加的input事件中操作vnode.context[binding.expression] = e.target.value同步inputvalue值到外部(context),與使用@input添加事件監聽效果是一樣的;然后我們需要做第二件事,做value值的綁定,監聽value的變化,同步值的變更到inputvalue上,我們想到我們可以使用Vue實例上的額$watch方法監聽值的變化,而context就是那個Vue實例,binding.expression就是我們想要監聽的屬性,如果我們這樣寫

參考vue實戰視頻講解:進入學習

<input v-mymodel='message'/>
登錄后復制

那么binding.expression就是字符串'message'。所以我們想下面的代碼這樣監聽綁定的響應式數據。

//監聽綁定的變量 vnode.context.$watch(binding.expression, (v) => {      el.value = v; })
登錄后復制

至此,inputv-mymodel的處理就完成了(當然input組件還有typecheckbox,radio,select等類型都需要去特別處理,這里就不再一一處理了,感興趣的同學可以自己嘗試去完善一下),但是對于非原生控件的組件,我們要特殊處理。 因此我們完善代碼如下:

Vue.directive('mymodel', {         //只調用一次,指令第一次綁定到元素時調用。在這里可以進行一次性的初始化設置。         bind(el, binding, vnode, oldVnode) {            //原生input組件的處理            if(vnode.tag==='input'){                 //第一步,添加inout事件監聽                 el.addEventListener('input', (e) => {                    //context是input所在的父組件,這一步是同步數據                    vnode.context[binding.expression] = e.target.value;                 })                 //監聽綁定的變量                 vnode.context.$watch(binding.expression, (v) => {                      el.value = v;                 })            }else{//組件             }         } })
登錄后復制

接下來我們要處理的是自定義組件的邏輯,

//vnode的結構可以參見文檔。不過我覺得最直觀的方法就是直接在控制臺打印處理 let {     componentInstance,     componentOptions,     context } = vnode; const {    _props } = componentInstance; //處理model選項 if (!componentOptions.Ctor.extendOptions.model) {   componentOptions.Ctor.extendOptions.model = {         value: 'value',         event: 'input'   } } let modelValue = componentOptions.Ctor.extendOptions.model.value; let modelEvent = componentOptions.Ctor.extendOptions.model.event; //屬性綁定,這里直接修改了屬性,沒有想到更好的辦法,友好的意見希望可以提出 _props[modelValue] = binding.value; context.$watch(binding.expression, (v) => {      _props[modelValue] = v; }) //添加事件處理函數,做數據同步 componentInstance.$on(modelEvent, (v) => {      context[binding.expression] = v; })
登錄后復制

聲明一下,上面的實現不是vue源碼的實現方式,vue源碼中實現v-model更加復雜一點,是結合自定義指令、模板編譯等去實現的,因為我們是應用級別的封裝,所以采用了上述的方式實現。

實現此v-mymodel需要同學去多了解一下VnodeComponentAPI,就像之前說的,最簡單的方法就是直接在控制臺中直接打印出vnode對象,組件的vnode上有Component的實例componentInstance

接下來簡單說一下上面的代碼,首先我們可以在componentOptions.Ctor.extendOptions上找到model的定義,如果沒有的話需要設置默認值valueinput,然后分別對想原生input的處理一樣,分別監聽binding.expression的變化和modelEvent事件即可。

需要注意的是,我們上面的代碼直接給_prop做了賦值操作,這實際上是不符合規范的,但是我目前沒有找到更好的方法去實現,有好思路的同學可以在評論區留言指教。

下面?是完整的源碼:

應用實踐:4個實用的自定義指令

上文我們通過封裝v-mymodel為各位同學展示了如何封裝和使用自定義指令,接下來我把自己在生產實踐中使用自定義指令的一些經驗分享給大家,通過實例,我相信各位同學能夠更深刻的理解如何在在應用中封裝自己的指令,提高效率。

權限控制

下面我們定義一個v-permission指令用于全平臺的權限控制

  • role:角色控制;
  • currentUser:當前登錄人判斷;當前用戶是否是業務數據中的創建人或者負責人
  • bussinessStatus:業務狀態判斷;
  • every:與操作;
  • some:或操作;

示例代碼

//定義權限類型 const permissionType = {     ROLE: 'role',     CURRENTUSER:'currentUser',     BUSSINESSSTATUS: 'bussinessStatus',     MIX_EVERY: 'every',     MIX_SOME: 'some' } export default {     //只調用一次,指令第一次綁定到元素時調用     bind: function () {     },     //當前vdom插入到真實dom時,因為是對dom的樣式操作,在這里操作     inserted: function (el, binding) {         let show = false;         show=processingType(binding.arg,binding.value);          el.style.display = `${show ? 'inline-block' : 'none'}`     },     //所在組件的VNode更新時調用,狀態更新后需要更新顯示狀態     update: function (el, binding) {         //避免無效的模板更新         if(binding.value===binding.oldValue) return;         let show = false;         show=processingType(binding.arg,binding.value);          el.style.display = `${show ? 'inline-block' : 'none'}`     },     //指令所在組件的 VNode 及其子 VNode 全部更新后     componentUpdated: function (el, binding) {     },     unbind: function () {     }, } //處理不同類型的權限控制 function processingType(type,value){     let values=[];     switch (type) {         case permissionType.ROLE:             return permissionByRole(value);         case permissionType.CURRENTUSER:             return permissionCreater(value);         case permissionType.BUSSINESSSTATUS:             return permissionBusinessStatus(value);         case permissionType.MIX_EVERY:             for(let type in value){                 values.push(processingType(type,value[type]))             }             return values.every(v=>{                 return v;             })         case permissionType.MIX_SOME:             for(let type in value){                 values.push(processingType(type,value[type]))             }             return values.some(v=>{                 return v;             })         default:             return false;     } } //業務狀態判斷 function permissionBusinessStatus(bindingValue){    return bindingValue.status==bindingValue.value; } //當前用戶? function permissionCreater(bindingValue){     const userInfo = JSON.parse(sessionStorage.CDTPcookie);     // console.log(userInfo.userInfo.id,bindingValue)     if(bindingValue instanceof Array){         return bindingValue.some(v=>{             return userInfo.userInfo.id==v;         })     }     return userInfo.userInfo.id==bindingValue; } //角色控制 export function permissionByRole(bindingValue) {     //這里也可以是store里的用戶信息     const userInfo = JSON.parse(sessionStorage.userInfo);       let roles = []     if (userInfo) {         roles = userInfo.roleList     }     let show = false;     if (bindingValue instanceof Array) {         return roles.some(role => {//多角色處理             return bindingValue.some(item => {                 return role.roleCode === item             })         })     } else if (typeof bindingValue == 'string') {         show = roles.some(role => {             return role.roleCode === bindingValue;         })     }     return show; }
登錄后復制

簡單說一下上面?指令的定義思路和使用方法。整體思路就是通過processingType處理權限邏輯,使用el.style.display控制組件顯示或隱藏。我在這里從日常應用中提取了一些通用的processingType中的權限處理方式,方便大家理解也供大家參考。

下面逐一說一下權限指令各個類型的使用方法:

//角色權限 <component v-permission:role='leader'></component> //判斷當前登錄人 <component v-permission:currentUser='orderInfo.createUser'></component> //判斷業務狀態 <component v-permission:bussinessStatus='{status:orderStatus.RUNNING,value:orderInfo.status}'></component> //角色是leader或者是當前訂單的創建者,有權限 <component v-permission:some="{role:'leader',currentUser:'orderInfo.createUser'}"></component> //角色是leader并且是當前訂單的創建者,有權限 <component v-permission:every="{role:'leader',currentUser:'orderInfo.createUser'}"></component>
登錄后復制

輸入限制

v-input 輸入框限制,限制數字、保留n位小數點等。

export default {     inserted: function (el, binding, vnode) {         el.addEventListener('input', function (e) {             if (binding.arg == 'toFixed') {                 //限制輸入n位小數點                 toFiexd(e.target, vnode, binding.value)             } else {                 //限制數字輸入                 Integer(e.target, vnode)             }         })     }, } function toFiexd(target, vnode, v) {     console.log(v);     let ln = 2;     if (v) {         ln = v;     }     var regStrs = [         ['^0(\d+)$', '$1'], //禁止錄入整數部分兩位以上,但首位為0         ['[^\d\.]+$', ''], //禁止錄入任何非數字和點         ['\.(\d?)\.+', '.$1'], //禁止錄入兩個以上的點         ['^(\d+\.\d{' + ln + '}).+', '$1'] //禁止錄入小數點后兩位以上     ];     for (var i = 0; i < regStrs.length; i++) {         var reg = new RegExp(regStrs[i][0]);         target.value = target.value.replace(reg, regStrs[i][1]);     }     //對于封裝的像el-input組件,因為其需要通過input事件同步狀態     if(vnode.componentInstance){       vnode.componentInstance.$listeners.input(target.value)     } } function Integer(target, vnode) {     let valueStr = target.value     if (valueStr.length == 1) {         //第一個數字不為0         valueStr = valueStr.replace(/[^0-9]/g, "");     } else {         //只能輸入正整數         valueStr = valueStr.replace(/D/g, "");     }     target.value = valueStr;     if(vnode.componentInstance){       vnode.componentInstance.$listeners.input(target.value)     } }
登錄后復制

這里需要特別注意的是下面這行代碼

vnode.componentInstance.$listeners.input(target.value)
登錄后復制

我們為什么需要添加這一句呢,我們明明已經為target.value做了賦值。
實際上這一句代碼相當于指令作用組件內部的$emit('input',target.value),這是因為如果我們是在antd或者elementui中的輸入框組件上添加我們定義的v-input指令,直接為target.value賦值是不能生效的,修改的只是原生input控件value值,并沒有修改自定義組件的value,還需要通過觸發input事件去同步組件狀態,修改value值。(這里不了解為什么需要觸發input事件區同步狀態的同學了解一下v-model的語法糖原理即可理解, 使用方法:

<!-- 限制輸入兩位小數數字 --> <input v-input:toFixed="2"/> <!-- 限制輸入正整數 --> <el-input v-input:integer/>
登錄后復制

內容處理

我們也可以通過自定義指令做對內容到處理,比如

  • 空值處理

  • 數字千分數逗號分割

export default {     bind:function(){     },     inserted:function(el,binding){         dealContent(el,binding)     },     update:function(el,binding){         dealContent(el,binding)     },     componentUpdated:function(){     },     unbind:function(){     }, } function dealContent(el,binding){    const {arg}=binding;    if(arg=='empty'){        if(!el.textContent){//空值顯示             el.textContent=binding.value||'暫無數據';         }    }else if(arg=='money'){//金額千分位逗號分割,如10000000顯示為100,000,00         if (binding.value) {             el.textContent = dealMoney(binding.value);         }else {             el.textContent = dealMoney(el.textContent);         }    } }
登錄后復制

千分位分割代碼:

//金額處理 export function dealMoney(money, places = 2) {     const zero = `0.00`;     if (isNaN(money) || money === '') return zero;     if (money && money != null) {         money = `${money}`;         let left = money.split('.')[0]; // 小數點左邊部分         let right = money.split('.')[1]; // 小數點右邊         // 保留places位小數點,當長度沒有到places時,用0補足。         right = right ? (right.length >= places ? '.' + right.substr(0, places) : '.' + right + '0'.repeat(places - right.length)) : ('.' + '0'.repeat(places));         var temp = left.split('').reverse().join('').match(/(d{1,3})/g); // 分割反向轉為字符串然后最多3個,最少1個,將匹配的值放進數組返回         return (Number(money) < 0 ? '-' : '') + temp.join(',').split('').reverse().join('') + right; // 補齊正負號和貨幣符號,數組轉為字符串,通過逗號分隔,再分割(包含逗號也分割)反向轉為字符串變回原來的順序     } else if (money === 0) {         return zero;     } else {         return zero;     } }
登錄后復制

使用方法:

<span v-content:empty="'無'">{{message}}</span> <!-- 金額千分位逗號分割 --> <span v-content:money>100000</span>
登錄后復制

文件預覽

v-preview方便的實現文件預覽功能

  • 預覽圖片;

  • 預覽文件;

  • 其他預覽類業務功能

import {isOffic,isPdf,isImage} from '@/utils/base' import {previewWithOffice} from '@/utils/fileUtils.js' export default {     inserted:function(el,binding){         el.onclick=function(e){             let params = binding.value             if(isOffic(params.name)){                 e.preventDefault()                 e.stopPropagation()                 previewWithOffice(params.url)//使用office在線預覽打開             }else if(isPdf(params.name) || isImage(params.name)){                 e.preventDefault()                 e.stopPropagation()                 if(params.url){//直接打開url                     previewFile(params)                 }             }         }     },     //指令所在組件的 VNode 及其子 VNode 全部更新后     componentUpdated: function (el, binding) {         el.onclick=function(e){             let params = binding.value             if(isOffic(params.name)){                 //使用插件預覽Office文件                 e.preventDefault()                 e.stopPropagation()                 previewWithOffice(params.url)             }else if(isPdf(params.name) || isImage(params.name)){                //預覽圖片和pdf等能直接打開的文件                 e.preventDefault()                 e.stopPropagation()                 previewFile(params)             }         }     },     unbind(el){        el.onclick=null;     } } //預覽圖片和pdf等能直接打開的文件 function previewFile(params) {     let a = document.createElement("a");     a.download = params.name     a.href = params.url;     a.target = "_blank";     a.click();     a = null; }
登錄后復制

使用方法:

<!-- 預覽圖片 --> <image :src='url' v-preview="{name:file.name,url:file.url}"></image> <!-- 預覽文件 --> <span v-preview="{name:file.name,url:file.url}">{{file.name}}</span>
登錄后復制

試著自己實現

各位同學可以試著自己實現一個v-loading的加載中的指令,通過設置一個bool值來設置容器的加載狀態。 如有疑問可以在評論區留言。

總結

本文主要講了如下幾件事:

  • vue自定義指令介紹
  • 實現一個v-model
  • 通用的自定義指令使用技巧

(學習視頻分享:web前端開發、編程基礎視頻)

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
韩国18禁电影风暴尺度大| 暗交小拗女一区二| 1000部无遮挡拍拍拍免费视频| 最新国产AV无码专区亚洲AVY| 中文中文字幕成人无码AⅤ| AV成人午夜无码一区二区| 波多野结衣的影片| 国产超碰AV人人做人人爽| 国产色无码精品视频免费| 精品少妇爆乳无码AⅤ区| 林静公交车被做到高C| 欧美裸体XXXX| 爽到高潮无码视频在线观看| 亚欧洲精品在线视频免费观看| 亚洲欧美国产成人综合不卡| 中文字幕人妻三级中文无码视频| WWW射我里面在线观看| 各种少妇正面着BBW撒尿视频| 国产三级在线观看完整版| 久久精品国产亚洲AV麻豆甜 | 国产综合无码一区二区色蜜蜜 | 又大又粗又爽又黄的少妇毛片 | 肉丝超薄丝袜交一区二区| 无罩大乳的熟妇正在播放| 亚洲中文字幕无码中文字在线| CHINESE熟女老太HD| 国产成人剧情AV麻豆映画| 精品久久久久中文字幕日本| 农场主的女儿们 美国2| 少妇被 到高潮喷出白浆av| 亚洲妇熟XXXX妇色黄无码| 18禁裸乳无遮挡免费网站| 丰满的人妻HD高清日本| 寂寞骚妇被后入式爆草抓爆| 欧美大屁股XXXX高跟欧美黑人| 天天摸夜夜添狠狠添婷婷| 亚洲中文字幕码在线电影| 差差漫画页面免费漫画欢迎你| 黑人处破女免费播放| 女生自己动手奖励自己的好处| 婷婷丁香六月激情综合啪| 一面膜上边一面膜下边韩国| 差差差很疼无掩盖在线观看| 精品国产一区二区AV麻豆不卡| 欧美性受XXXX88喷潮| 亚洲 无码 国产精品| 99久久免费国产精品四虎99久久精品免费看国产一区二区 | 厨房征服丰满熟妇少妇人妻| 精品毛卡卡1卡2卡3麻豆| 人妻少妇aB又紧又爽精品视频| 亚洲AV无码成人影片在线观看| 99精品久久99久久久久| 国产性猛交╳XXX乱大交| 欧美极品JIZZHD欧美| 亚洲AV麻豆AⅤ无码电影| av 成人 亚洲无码| 和人妻隔着帘子按摩中字| 人妻少妇乱子伦无码专区| 亚洲精品无码久久久久APP| 槽溜2021入口一二三四| 精品一区二区无码免费| 少妇人妻无码专用视频| 再深点灬舒服灬太大了下载| 国产成人综合亚洲精品| 女人越喊男人越往里寨电视剧| 亚洲AV成人片无码网站| YW尤物AV无码国产在线看| 久久99精品久久只有精品| 色哟哟在线视频精品一区| 在线观看亚洲av| 国产欧美VA欧美VA香蕉在| 欧美最厉害的喷水VIDEOS| 亚洲国产精品久久久久秋霞1| 人妻无码AⅤ中文字幕系列| 蜜臀AV网站在线| AK福利利电影在线看视频| 黑人巨茎大战欧美白妇| 日产精品乱码卡一卡2卡三网站| 亚洲精品无码日韩国产不卡Av| 二虎进入温如玉160章小说| 民工把我奶头掏出来了怎么办 | 高潮VIDEOSSEX潮喷另类| 美国白人未成年RAPPER豆瓣| 亚洲Aⅴ无码专区在线观看q| 成人网站在线观看丰满少妇电影| 麻豆妓女爽爽一区二区三| 亚洲A级成人片在线观看| 丰满少妇A级毛片野外| 欧美疯狂性受XXXXX喷水| 亚洲一线产区二线产区区别在哪里| 国产精品爆乳在线播放第一人称| 人妻aⅴ无码一区二区色戒| 一本一道AV无码中文字幕麻豆 | 亚洲V国产V天堂A无码二区| 番茄TODO社区免费看片| 欧美熟老妇人多毛OOXⅩ| 永久免费AV网站| 精品日产一区二区三区| 性饥渴的农村熟妇在线视频| 丰满人妻熟妇乱又伦精品 | 无码成人黄动漫在线观看| 不卡无码人妻一区三区| 欧美国产成人精品一区二区三区| 一区二区三区AV高清免费波多 | 女主快穿到各个世界做小三| 亚洲中文字幕无码永久在线| 护士趴下光屁股翘臀被打的作文| 天堂AⅤ大芭蕉伊人AV| 厨房玩丰满人妻HD完整版视频| 欧亚一二精品在免费看| 19岁MACBOOKPRO高清| 久久婷婷大香萑太香蕉AV人| 亚洲国产综合无码一区二区BT下| 国产精品爽爽ⅤA在线观看| 少妇极品熟妇人妻无码| 成人无遮挡裸免费视频在线观看| 欧美性猛交XXXX乱大交极品| 97精品依人久久久大香线蕉97| 毛豆日产精品卡2卡3卡4卡免费| 亚洲最大成人一区久久久| 久久av蜜臀人妻一区二区三区| 亚洲国产成人精品福利在线观看| 国精产品一区一区三区有限公司| 天天综合天天爱天天做| 国产成人无码精品一区二区三区 | 亚洲精品无码AV天堂| 黑人狂桶女人高潮嗷嗷叫小说| 亚洲AV无码AV日韩AV网站| 国产香港明星裸体XXXX视频| 无人免费观看视频在线观看| 国产精品美女久久久浪潮AV| 无码久久精品国产亚洲AV影片| 国产成人无码一区二区在线播放| 天天狠天天透天干天干| 国产精品久久这里只有精品 | 娇妻呻吟黑人又粗又大视频| 亚洲成在人线在线播放无码| 禁欲少校大哥的囚禁| 亚洲色无码国产精品网站可下载 | 视频一区二区三区免费| 国产成人8X视频网站| 午夜A级毛片免费观看| 国产在线精品无码AV不卡顿| 亚洲AV影院一区二区三区| 黄网站色视频免费观看| 亚洲女和黑人最新AV| 久久亚洲精品无码爱剪辑 | 奶头从情趣内衣下露了出来AV | 西西人体艺术,国模人体| 哈昂~哈昂够了太多了男男| 欧美巨大XXXX做受| 野花日本大全免费观看中文7 | 亚洲AV成人一区二区三区观看在 | 国产无套粉嫩白浆在线| 亚洲AV无码专区亚洲AV漫画| 精品无码乱码AV| 在线观看国产精品乱码APP| 女人18片毛片60分钟| 波多野42部无码喷潮在线| 天堂中文А√在线| 国产熟妇XXXXXⅩ性Ⅹ交| 亚洲人成无码区在线观看| 免费A级毛片出奶水| 班长哭着说不能再C了视频| 少妇又紧又深又湿又爽视频| 国产玉足榨精视频在线观看| 亚洲日韩中文无码久久| 男同桌上课用手指进去了好爽| 成年免费A级毛片免费看无码| 玩弄JaPan白嫩少妇HD小说| 黑人与亚洲女人XXXXXXXⅩ| 野花香在线视频免费观看第一集| 女人18毛片A级毛片免费视频| 成年无码动漫AV片在线尤物| 洗澡被公强玩好舒服肉欲小说| 久久精品国产亚洲AV忘忧草18| 99精品视频一区在线观看| 日韩精品无码人成视频| 国产男男GaYGaY无套| 亚洲自国产拍揄拍| 秋霞电影院yy2933| 国产精品亚洲二区在线观看| 亚洲午夜久久久久久久久电影网| 欧美粗大强交18P直喷水| 国产精品久久久久久久久免费 | 久久精品国产一区二区三区不卡| CAOPORN最新地址| 无码人妻久久久久一区二区三区91| 精品国产AV色欲果冻传媒 | 日本熟妇人妻XXXXX野外呻| 国产女人18毛片水真多1| 中文字幕AV一区二区三区人妻少| 色妺妺AⅤ爽爽影院偷拍| 精品熟女少妇A∨免费久久 | 人妻无码不卡中文字幕在线视频| 国产精品亚洲VA在线| 中国少妇内射XXXHD| 私人电影院免费看吗| 久久亚洲色WWW成人男男| 国产AV无码专区亚洲AⅤ|