Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 日本一区二区三区在线视频,日韩在线视频二区,亚洲精品亚洲九十七页

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          開發(fā)者成長Vue.js 中有哪些性能陷阱

          內(nèi)心深處對(duì)游戲的熱愛,讓我一直渴望能自己制作一些電子游戲。幾個(gè)月前我開始將這種夢(mèng)想變?yōu)楝F(xiàn)實(shí),并第一次參加了全球游戲大賽(Global Game Jam)。我和我的團(tuán)隊(duì)使用 Vue.js 構(gòu)建了一個(gè)名為“ ZeroDaysLeft ”的游戲,其形式是 Web 端的單頁面應(yīng)用程序。這款游戲的主題是環(huán)境保護(hù),我們考慮到商業(yè)活動(dòng)對(duì)地球環(huán)境的影響,希望就這個(gè)話題做一些有益的探討。使用 Vue.js 制作的游戲并不多。我的團(tuán)隊(duì)遲到了一天,然后用猜拳的方式選擇了我們要用的框架;我們飛快地寫完了代碼,并在周末結(jié)束時(shí)做出了游戲的可運(yùn)行版本。在本地測(cè)試時(shí)一切都很順利。自然,我們?yōu)樽约旱谝淮螌懗鰜淼挠螒蜃髌犯械阶院溃⑾Mc世界分享它。

          可是問題出現(xiàn)了——當(dāng)我們構(gòu)建好應(yīng)用并開始查詢域時(shí),內(nèi)存占用爆表了。它幾乎沒法正常運(yùn)行,不管換什么機(jī)器都會(huì)卡住不動(dòng),即使在強(qiáng)大的基于 Intel i7 處理器的系統(tǒng)上程序也會(huì)崩潰。游戲大賽的時(shí)間限制把我們拉回了現(xiàn)實(shí),我們決定擱置生產(chǎn)性能問題,這樣起碼我們能做出一款能在自己的設(shè)備上運(yùn)行的完整游戲。就像大部分的“已完成”項(xiàng)目一樣,第二天我們就把它拋在腦后了。

          但我自己沒法釋懷。它一直困擾著我。問題是出在 Vue.js 上嗎?是 Netlify 嗎?還是因?yàn)槲覀兊娜∏纱a?我必須找出答案。

          調(diào)查性能下降的原因

          我首先使用 Lighthouse 進(jìn)行了快速測(cè)試。所幸 Firefox 為此提供了一個(gè)瀏覽器插件。下面就是我得到的結(jié)果。

          89%的數(shù)字挺不錯(cuò)的。實(shí)際上,與許多流行的網(wǎng)站相比,這個(gè)表現(xiàn)相當(dāng)出色。這個(gè)測(cè)試指出了一些潛在問題,例如速度指數(shù)和第一次有意義且有內(nèi)容的繪制步驟等。從理論上講,解決這些問題會(huì)進(jìn)一步提高分?jǐn)?shù),但不一定能解決應(yīng)用面臨的嚴(yán)重性能問題。

          我們的游戲中有一些圖像和音頻素材資源,但是兩者都不至于讓游戲卡死在那里。我們也可以對(duì)這些已經(jīng)優(yōu)化過的資源再過度優(yōu)化一遍,但這可能根本就無濟(jì)于事。

          這個(gè)測(cè)試無法讓我們真正找出可能導(dǎo)致這一性能問題的原因。于是我開始想:“該不會(huì)是 Vue 的問題吧?”這種想法會(huì)冒出來也沒什么理由,但要是不檢查一下就是蠢了。我檢查了已部署站點(diǎn)的控制臺(tái),結(jié)果空白一片。但警告往往不會(huì)在生產(chǎn)中顯示。當(dāng)我在本地進(jìn)行相同操作時(shí),一堆 Vue 警告讓我吃了一驚。

          像大多數(shù)開發(fā)人員一樣,我對(duì)控制臺(tái)警告沒那么在意,覺得它們只是警告,而不代表錯(cuò)誤;所以我一般會(huì)把注意力集中在其他地方。或許消除這些警告可以解決我的生產(chǎn)問題,我決定深入研究每個(gè)問題并修復(fù)它們。

          所有這些警告均來自我創(chuàng)建的、用來顯示名為 Cards.vue 選項(xiàng)的組件,因此這個(gè)組件可能需要大量重寫。

          我決定按順序解決這些控制臺(tái)警告。

          > [Vue warn]: Avoid using non-primitive value as key, use string/number value instead.
           found in 
           ---> <Cards> at src/components/Cards.vue

          Vue.js 有很多指令,讓我們能更直觀地使用框架,比如說 v-for 就可以快速將數(shù)組渲染為列表。使用它時(shí),我們需要一個(gè) :key 才能有效地重渲染組件。但我們將一個(gè)對(duì)象用作了一個(gè)鍵,這是非原始值,因此導(dǎo)致了這個(gè)錯(cuò)誤。我決定將 index.description 用作一個(gè)新鍵,因?yàn)樗且粋€(gè)字符串,并且在值發(fā)生更改時(shí)可以更好地重新渲染。

          > [Vue warn]: Duplicate keys detected: '[object Object]'. This may cause an update error.
          found in
          ---> <Cards> at src/components/Cards.vue

          將 :key 更改為一個(gè)字符串(index.description)來解決上一個(gè)錯(cuò)誤,就能解決這個(gè)重復(fù)鍵的錯(cuò)誤。我們只能將字符串類型寫入 DOM,因此當(dāng)我們傳遞一個(gè)要渲染的對(duì)象時(shí),該對(duì)象將轉(zhuǎn)換為等效的字符串(即 [object Object]);并且因?yàn)檫@以前是我們的鍵,所以每個(gè)對(duì)象都將轉(zhuǎn)換為 [object Object](除非對(duì)象有不同的值),進(jìn)而會(huì)出現(xiàn)重復(fù)鍵警告。現(xiàn)在既然鍵不是對(duì)象,警告就會(huì)消失,效率也會(huì)提升。

          > [Vue warn]: You may have an infinite update loop in a component render function.
          found in
          ---> <Cards> at src/components/Cards.vue

          就一個(gè)非常模糊的警告來說,這個(gè)警告似乎是最重要的:無限循環(huán)意味著內(nèi)存消耗。這條消息并沒有告訴我們可能出了什么問題,但它確實(shí)暗示了問題與組件中的 render 函數(shù)有關(guān)。也許是因?yàn)槲覀儗懙拇a比較取巧,因此觸發(fā)了不間斷的更新,并占用了大量的計(jì)算能力,以至于使瀏覽器和設(shè)備崩潰。

          這條警告至少告訴我們要檢查 Cards.vue,所以我的第一個(gè)想法是檢查組件中的反應(yīng)屬性,因?yàn)檫@可能會(huì)導(dǎo)致錯(cuò)誤。反應(yīng)屬性在更改后會(huì)觸發(fā)重新渲染。

          我們正在顯示 index.days 和 index.description 中的數(shù)據(jù)。但我們不會(huì)更改這些數(shù)據(jù),我們從 cardInfo 數(shù)組獲得 index。

          我們使用這段代碼對(duì)數(shù)組中的元素進(jìn)行隨機(jī)排序,然后將前四個(gè)元素顯示為玩家選擇的選項(xiàng)。當(dāng)用戶單擊一個(gè)選項(xiàng)時(shí)將調(diào)用 effects() 函數(shù),它除了會(huì)計(jì)算一個(gè)動(dòng)作如何影響游戲狀態(tài)外,還使用 cardInfo 上的拼接原型刪除前四個(gè)元素。

          在 Vue 這種使用虛擬 DOM 的框架里,用上諸如 cardInfo 之類的反應(yīng)屬性后,每當(dāng)數(shù)據(jù)屬性的值更改時(shí)都會(huì)觸發(fā)重新渲染。在我們的應(yīng)用里,我們會(huì)直接使用 sort() 原型來更改它,然后刪除元素來重新排序。所有這些都會(huì)觸發(fā)“無限”的重新渲染,從而引發(fā)警告。

          我決定更改數(shù)據(jù)過濾的邏輯,并停止對(duì)反應(yīng)屬性 cardInfo 的多次更改。我安裝了 lodash.shuffle 并定義了一個(gè)計(jì)算屬性 shuffledList(),它將創(chuàng)建一個(gè)名為 list 的 cardInfo 副本。我對(duì)其應(yīng)用了隨機(jī)排序操作,并返回了一個(gè)“frozen”結(jié)果,然后拆分開來顯示四張卡片。我們使用了 Object.freeze(),它將使我們返回的對(duì)象不可變,從而完全停止了所有重新渲染操作。

          至此,問題解決了。

          掉進(jìn)框架的坑

          老實(shí)說,當(dāng)我剛開始調(diào)查性能下降原因的時(shí)候,還覺得我肯定要優(yōu)化很多資源才能解決問題。最后這個(gè)結(jié)果說明,在使用許多框架抽象時(shí)我們都必須非常小心——特別是在 Vue 中更是如此,只有在必要時(shí)才使用某條指令,而且用法一定不能出錯(cuò),因?yàn)樗鼈兘^對(duì)有自己的代價(jià)。

          這還讓我開始思考自己做過的其他工作,其中應(yīng)用程序可能會(huì)因?yàn)榭蚣芏霈F(xiàn)不必要的性能問題。大多數(shù)現(xiàn)代的前端框架都有很多抽象,使我們能更輕松地為 Web 制作應(yīng)用程序。但我們應(yīng)該牢記一點(diǎn),那就是使用這些東西可能會(huì)引發(fā)潛在的性能問題。

          我經(jīng)常使用 Vue.js,所以決定探索一些我以前用過的指令,以前我用這些指令的時(shí)候完全沒考慮過它們可能對(duì)應(yīng)用程序帶來的性能影響。其中有三條非常流行的指令進(jìn)入了我的視線。

          • v-if 和 v-show

          這兩條指令都是用來有條件地渲染元素的,但是它們背后的工作機(jī)制卻大不相同,因此用法也大相徑庭。v-if 一開始不會(huì)渲染組件,而只在條件為真時(shí)才渲染組件。這意味著當(dāng)你多次切換組件的可見性時(shí),就會(huì)不斷重新渲染。如果你要多次更改組件的可見性,那就不要使用這個(gè)功能。這會(huì)影響你的性能。

          v-show 是一個(gè)很好的替代品。不管你是否啟用 CSS 都會(huì)渲染你的組件,但是只會(huì)根據(jù)條件是 true 還是 false 來決定組件是否可見。這種方法確實(shí)有其缺點(diǎn),因?yàn)樗粫?huì)將非必要組件的渲染推遲到你需要它們?cè)谄聊簧蠈?shí)際出現(xiàn)的時(shí)候。如果你的初始渲染沒那么復(fù)雜,那么它就很合適。

          • v-for

          這條指令通常用來從數(shù)組中渲染列表。它有一個(gè)特殊的語法,形式為 item in list,其中 list 是源數(shù)據(jù)數(shù)組,而 item 是要迭代的數(shù)組元素的別名。默認(rèn)情況下,Vue 在源數(shù)據(jù)數(shù)組上添加 watchers,每當(dāng)發(fā)生更改時(shí)它就會(huì)觸發(fā)重新渲染。這種持續(xù)的重新渲染可能會(huì)對(duì)應(yīng)用程序性能產(chǎn)生不利影響。如果你只想可視化對(duì)象,那么 Object.freeze() 是一個(gè)很好的解決方案,可以大大提高性能。但是請(qǐng)務(wù)必記住,你將無法更新組件或編輯對(duì)象數(shù)據(jù)。

          在這個(gè)研究過程中我還意識(shí)到,Lighthouse 可能檢查的是以更直接的方式影響用戶體驗(yàn)的應(yīng)用性能指標(biāo),所以接下來我的疑問就是如何跟蹤服務(wù)器上的應(yīng)用程序性能。

          我們是不是太依賴直覺,是不是在假設(shè)開發(fā)人員知道自己在做什么,假設(shè)他們遵循的是最佳實(shí)踐?不管怎樣,這次經(jīng)歷讓我對(duì)單頁應(yīng)用程序的性能產(chǎn)生了不同的看法。大家可以在 GitHub 上查看上述項(xiàng)目的存儲(chǔ)庫,也歡迎大家在 Twitter 上和我打招呼。

          JavaScript 中,Vue 是一種流行的前端框架,它具有簡潔的語法、高效的渲染能力和rich的組件庫。Vue 的設(shè)計(jì)目標(biāo)是為開發(fā)者提供一種簡單易用的方式來構(gòu)建用戶界面,同時(shí)保持高性能和可擴(kuò)展性。


          Vue 的核心庫是極小的,只關(guān)注視圖層,而且可以與其他庫或框架很好地集成。這使得 Vue 適合用于構(gòu)建單頁應(yīng)用程序(SPA)和Progressive Web Apps(PWA)。

          Vue 的組件系統(tǒng)是它的核心特性之一,允許開發(fā)者使用小型、獨(dú)立且易于重用的代碼塊來構(gòu)建用戶界面。Vue 組件可以傳遞數(shù)據(jù)和方法,同時(shí)還支持兩向數(shù)據(jù)綁定和異步組件加載。

          Vue 還提供了一套豐富的直接指令,例如v-if、v-for和v-model,使得開發(fā)者能夠方便地操作 DOM 元素。

          Vue 的響應(yīng)式系統(tǒng)是它的另一個(gè)重要特性,允許開發(fā)者根據(jù)數(shù)據(jù)的變化來實(shí)時(shí)更新 DOM,從而達(dá)到高效的數(shù)據(jù)驅(qū)動(dòng)開發(fā)。

          Vue 還提供了一個(gè)強(qiáng)大的工具鏈,包括官方的命令行界面(CLI)、開發(fā)工具(DevTools)和豐富的社區(qū)支持。

          總之,Vue 是一個(gè)優(yōu)秀的前端框架,適合于構(gòu)建富互動(dòng)的用戶界面,同時(shí)具有簡單易學(xué)的特點(diǎn),并且擁有強(qiáng)大的社區(qū)和文檔支持。

          ue的使用相信大家都很熟練了,使用起來簡單。但是大部分人不知道其內(nèi)部的原理是怎么樣的,今天我們就來一起實(shí)現(xiàn)一個(gè)簡單的vue

          Object.defineProperty()

          實(shí)現(xiàn)之前我們得先看一下Object.defineProperty的實(shí)現(xiàn),因?yàn)関ue主要是通過數(shù)據(jù)劫持來實(shí)現(xiàn)的,通過get、set來完成數(shù)據(jù)的讀取和更新。

          var obj = {name:'wclimb'}
          var age = 24
          Object.defineProperty(obj,'age',{
           enumerable: true, // 可枚舉
           configurable: false, // 不能再define
           get () {
           return age
           },
           set (newVal) {
           console.log('我改變了',age +' -> '+newVal);
           age = newVal
           }
          })
           
          > obj.age
          > 24
           
          > obj.age = 25;
          > 我改變了 24 -> 25
          > 25
          

          從上面可以看到通過get獲取數(shù)據(jù),通過set監(jiān)聽到數(shù)據(jù)變化執(zhí)行相應(yīng)操作,還是不明白的話可以去看看Object.defineProperty文檔。

          流程圖



          image

          html代碼結(jié)構(gòu)<div id="wrap">
           <p v-html="test"></p>
           <input type="text" v-model="form">
           <input type="text" v-model="form">
           <button @click="changeValue">改變值</button>
           {{form}}
          </div>
          

          js調(diào)用

          new Vue({
           el: '#wrap',
           data:{
           form: '這是form的值',
           test: '<strong>我是粗體</strong>',
           },
           methods:{
           changeValue(){
           console.log(this.form)
           this.form = '值被我改變了,氣不氣?'
           }
           }
           })
          

          Vue結(jié)構(gòu)

          class Vue{
           constructor(){}
           proxyData(){}
           observer(){}
           compile(){}
           compileText(){}
          }
          class Watcher{
           constructor(){}
           update(){}
          }
          
          • Vue constructor 構(gòu)造函數(shù)主要是數(shù)據(jù)的初始化
          • proxyData 數(shù)據(jù)代理
          • observer 劫持監(jiān)聽所有數(shù)據(jù)
          • compile 解析dom
          • compileText 解析dom里處理純雙花括號(hào)的操作
          • Watcher 更新視圖操作

          Vue constructor 初始化

          class Vue{
           constructor(options = {}){
           this.$el = document.querySelector(options.el);
           let data = this.data = options.data; 
           // 代理data,使其能直接this.xxx的方式訪問data,正常的話需要this.data.xxx
           Object.keys(data).forEach((key)=> {
           this.proxyData(key);
           });
           this.methods = options.methods // 事件方法
           this.watcherTask = {}; // 需要監(jiān)聽的任務(wù)列表
           this.observer(data); // 初始化劫持監(jiān)聽所有數(shù)據(jù)
           this.compile(this.$el); // 解析dom
           }
          }
          

          上面主要是初始化操作,針對(duì)傳過來的數(shù)據(jù)進(jìn)行處理

          proxyData 代理data

          class Vue{
           constructor(options = {}){
           ......
           }
           proxyData(key){
           let that = this;
           Object.defineProperty(that, key, {
           configurable: false,
           enumerable: true,
           get () {
           return that.data[key];
           },
           set (newVal) {
           that.data[key] = newVal;
           }
           });
           }
           }
          

          上面主要是代理data到最上層,this.xxx的方式直接訪問data

          observer 劫持監(jiān)聽

          class Vue{
           constructor(options = {}){
           ......
           }
           proxyData(key){
           ......
           }
           observer(data){
           let that = this
           Object.keys(data).forEach(key=>{
           let value = data[key]
           this.watcherTask[key] = []
           Object.defineProperty(data,key,{
           configurable: false,
           enumerable: true,
           get(){
           return value
           },
           set(newValue){
           if(newValue !== value){
           value = newValue
           that.watcherTask[key].forEach(task => {
           task.update()
           })
           }
           }
           })
           })
           }
           }
          

          同樣是使用Object.defineProperty來監(jiān)聽數(shù)據(jù),初始化需要訂閱的數(shù)據(jù)。

          把需要訂閱的數(shù)據(jù)到push到watcherTask里,等到時(shí)候需要更新的時(shí)候就可以批量更新數(shù)據(jù)了。下面就是;

          遍歷訂閱池,批量更新視圖。

          set(newValue){
           if(newValue !== value){
           value = newValue
           // 批量更新視圖
           that.watcherTask[key].forEach(task => {
           task.update()
           })
           }
          }
          

          compile 解析dom

          class Vue{
           constructor(options = {}){
           ......
           }
           proxyData(key){
           ......
           }
           observer(data){
           ......
           }
           compile(el){
           var nodes = el.childNodes;
           for (let i = 0; i < nodes.length; i++) {
           const node = nodes[i];
           if(node.nodeType === 3){
           var text = node.textContent.trim();
           if (!text) continue;
           this.compileText(node,'textContent') 
           }else if(node.nodeType === 1){
           if(node.childNodes.length > 0){
           this.compile(node)
           }
           if(node.hasAttribute('v-model') && (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA')){
           node.addEventListener('input',(()=>{
           let attrVal = node.getAttribute('v-model')
           this.watcherTask[attrVal].push(new Watcher(node,this,attrVal,'value'))
           node.removeAttribute('v-model')
           return () => {
           this.data[attrVal] = node.value
           }
           })())
           }
           if(node.hasAttribute('v-html')){
           let attrVal = node.getAttribute('v-html');
           this.watcherTask[attrVal].push(new Watcher(node,this,attrVal,'innerHTML'))
           node.removeAttribute('v-html')
           }
           this.compileText(node,'innerHTML')
           if(node.hasAttribute('@click')){
           let attrVal = node.getAttribute('@click')
           node.removeAttribute('@click')
           node.addEventListener('click',e => {
           this.methods[attrVal] && this.methods[attrVal].bind(this)()
           })
           }
           }
           }
           },
           compileText(node,type){
           let reg = /\{\{(.*?)\}\}/g, txt = node.textContent;
           if(reg.test(txt)){
           node.textContent = txt.replace(reg,(matched,value)=>{
           let tpl = this.watcherTask[value] || []
           tpl.push(new Watcher(node,this,value,type))
           if(value.split('.').length > 1){
           let v = null
           value.split('.').forEach((val,i)=>{
           v = !v ? this[val] : v[val]
           })
           return v
           }else{
           return this[value]
           }
           })
           }
           }
           }
          

          這里代碼比較多,我們拆分看你就會(huì)覺得很簡單了

          首先我們先遍歷el元素下面的所有子節(jié)點(diǎn),node.nodeType === 3 的意思是當(dāng)前元素是文本節(jié)點(diǎn),node.nodeType === 1 的意思是當(dāng)前元素是元素節(jié)點(diǎn)。因?yàn)榭赡苡械氖羌兾谋镜男问剑缂冸p花括號(hào)就是純文本的文本節(jié)點(diǎn),然后通過判斷元素節(jié)點(diǎn)是否還存在子節(jié)點(diǎn),如果有的話就遞歸調(diào)用compile方法。下面重頭戲來了,我們拆開看:

          if(node.hasAttribute('v-html')){
           let attrVal = node.getAttribute('v-html');
           this.watcherTask[attrVal].push(new Watcher(node,this,attrVal,'innerHTML'))
           node.removeAttribute('v-html')
          }
          

          上面這個(gè)首先判斷node節(jié)點(diǎn)上是否有v-html這種指令,如果存在的話,我們就發(fā)布訂閱,怎么發(fā)布訂閱呢?只需要把當(dāng)前需要訂閱的數(shù)據(jù)push到watcherTask里面,然后到時(shí)候在設(shè)置值的時(shí)候就可以批量更新了,實(shí)現(xiàn)雙向數(shù)據(jù)綁定,也就是下面的操作

          that.watcherTask[key].forEach(task => {
           task.update()
          })
          

          然后push的值是一個(gè)Watcher的實(shí)例,首先他new的時(shí)候會(huì)先執(zhí)行一次,執(zhí)行的操作就是去把純雙花括號(hào) -> 1,也就是說把我們寫好的模板數(shù)據(jù)更新到模板視圖上。

          最后把當(dāng)前元素屬性剔除出去,我們用Vue的時(shí)候也是看不到這種指令的,不剔除也不影響

          至于Watcher是什么,看下面就知道了

          Watcher

          class Watcher{
           constructor(el,vm,value,type){
           this.el = el;
           this.vm = vm;
           this.value = value;
           this.type = type;
           this.update()
           }
           update(){
           this.el[this.type] = this.vm.data[this.value]
           }
          }
          

          之前發(fā)布訂閱之后走了這里面的操作,意思就是把當(dāng)前元素如:node.innerHTML = '這是data里面的值'、node.value = '這個(gè)是表單的數(shù)據(jù)'

          那么我們?yōu)槭裁床恢苯尤ジ履兀€需要update做什么,不是多此一舉嗎?

          其實(shí)update記得嗎?我們?cè)谟嗛喅乩锩嫘枰扛拢褪峭ㄟ^調(diào)用Watcher原型上的update方法。

          最后

          以下是總結(jié)出來最全前端框架視頻,包含: javascript/vue/react/angualrde/express/koa/webpack 等學(xué)習(xí)資料。

          【領(lǐng)取方式】

          關(guān)注頭條 前端全棧架構(gòu)丶第一時(shí)間獲取最新前端資訊學(xué)習(xí)

          手機(jī)用戶可私信關(guān)鍵詞 【前端】即可獲取全棧工程師路線和學(xué)習(xí)資料!


          主站蜘蛛池模板: 国产在线视频一区| 精品一区中文字幕| 麻豆视频一区二区三区| 动漫精品第一区二区三区| 亚洲一区二区三区免费视频| 天堂不卡一区二区视频在线观看| 久久精品动漫一区二区三区| 无码精品前田一区二区| 国产精品538一区二区在线| 蜜臀AV一区二区| 久久人妻av一区二区软件| 国产精品区AV一区二区| 一区二区三区精品视频| 日韩一区二区三区视频| 精品一区二区三区无码免费直播| 成人免费一区二区三区在线观看| 男插女高潮一区二区| 在线播放偷拍一区精品| 无码人妻精品一区二区三区久久久 | 国产AV一区二区三区无码野战| 无码国产精品一区二区高潮| 成人无号精品一区二区三区| 日韩精品中文字幕视频一区| 精品日韩一区二区三区视频| 国产精品区一区二区三| 日韩美女视频一区| 国产婷婷色一区二区三区深爱网| 夜精品a一区二区三区| 国产一区二区好的精华液| 在线免费视频一区二区| 日韩一区二区精品观看| 国产一区二区三区小向美奈子| 免费一区二区三区四区五区| 国产a久久精品一区二区三区| 国产高清在线精品一区| 日韩一区二区三区不卡视频 | 精品国产免费观看一区| 日韩成人一区ftp在线播放| 国产伦精品一区二区三区无广告| 在线电影一区二区三区| 国产精品亚洲高清一区二区|