整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          vue引入外部js文件并使用

          在Vue中引入外部的JavaScript文件,可以使用以下幾種方法:

          1. 使用`<script>`標簽引入外部的JavaScript文件。在Vue的HTML模板中,可以直接使用`<script>`標簽來引入外部的JavaScript文件。例如,如果要引入一個名為`external.js`的文件,可以在Vue組件的模板中添加以下代碼:

          ```html

          <template>

          <div>

          <!-- Vue組件的內容 -->

          </div>

          </template>

          <script src="/path/to/external.js"></script>

          ```

          請注意,`<script>`標簽應該放在Vue組件的模板之后,這樣才能正確引入和使用外部的JavaScript文件。

          2. 使用`import`語句引入外部的JavaScript文件。在Vue的JavaScript代碼中,可以使用ES6的`import`語句來引入外部的JavaScript文件。例如,如果要引入一個名為`external.js`的文件,可以在Vue組件的JavaScript代碼中添加以下代碼:

          ```javascript

          import '/path/to/external.js';

          export default {

          // Vue組件的選項

          }

          ```

          請注意,`import`語句必須放在Vue組件的JavaScript代碼的頂部,這樣才能正確引入和使用外部的JavaScript文件。

          3. 在Vue的`index.html`文件中引入外部的JavaScript文件。如果要在整個Vue應用中都使用某個外部的JavaScript文件,可以在Vue的`index.html`文件中直接引入該文件。在`index.html`文件的`<head>`標簽中添加以下代碼:

          ```html

          <head>

          <!-- 其他的HTML代碼 -->

          <script src="/path/to/external.js"></script>

          </head>

          ```

          請注意,這種方法會在整個Vue應用中都引入外部的JavaScript文件,而不僅僅是某個特定的Vue組件。



          ??、Vue和其他兩大框架的區別

          • Angular 學習成本太高
          • React 代碼可讀性差
          • Vue 學習成本較低 很容易上手
            VUE官方: https://cn.vuejs.org/v2/guide/comparison.html

          ?2??、Vue是什么

          • Vue是一套用于構建用戶界面的漸進式框架 "前端框架"
          • 讓程序員脫離自己操作DOM 專注于寫邏輯和操作數據
          • Vue的核心庫只關注視圖層 易上手 便于與第三方庫或既有的項目整合
          • 當與現代化的工具鏈以及各種支持的庫結合使用時 Vue也完全能夠為復雜的單頁應用提供驅動

          ?3??、MVVM

          • M
            model 數據
          • V
            view 頁面
          • VM
            viewModel Vue實例
            DOM監聽(DOM Listeners)
            數據綁定(Date Bindings)

          ?4??、Vue指令

          ?4??.?1?? v-text

          說明: 文本數據渲染 用法: v-text = "Vue實例中的數據" => 簡寫 {{Vue實例中的數據}}

          相當于JavaScript中的innerText

          ?4??.?1??.?2?? v-text指令 和 {{ }}插值表達式 的區別

          • v-text 會直接替換元素中的所有內容
          • {{ }} 只會替換插值表達式中的占位符

          ?4??.?2?? v-html

          說明: HTML渲染數據 用法:v-html = "Vue實例中的數據" 會解析html結構 渲染至頁面

          相當于JavaScript中的innerHTML

          ?4??.?2??.?1?? v-html指令 和 v-text指令的區別

          • v-html 會將數據解析成html 渲染至頁面
          • v-text 只會輸出成文本(字符串形式)

          注意: 在網站上動態渲染任意的 HTML 是非常危險的!!! 因為容易導致 XSS 攻擊 只在可信內容上使用 v-html 絕對不要用在用戶通過(提交)的內容上使用

          ?4??.?3?? v-on

          說明: 事件綁定(綁定事件監聽器) 用法: v-on:事件名 = "事件處理函數" => 簡寫 @事件名 = "事件處理函數"

          ?4??.?3??.?1?? 詳細用法

          • @事件名.修飾符 = "事件處理函數"
          • 邏輯比較少的可以直接寫在行內
          • 邏輯較多的寫到 methods 中 注意: 操作Vue實例上的數據要跟上 this
          • 可以通過實參傳遞($event) 獲取事件參數e

          $event.target 獲取當前事件觸發的DOM元素 $event.path[0](el.path[0]) 也可以獲取當前事件觸發的DOM元素 path數組中有從觸發事件源的元素的所有上一級元素 直到window 實參不傳遞(沒有任何參數) 默認在形參中第一個就是事件參數
          實參傳遞 就必須傳遞$event 來獲取獲取事件參數

          ?4??.?3??.?2?? 事件修飾符

          • .stop
            阻止事件冒泡
          • .prevent
            阻止事件默認行為
          • .once
            只觸發一次回調
          • .native
            監聽組件根元素的原生事件
            很重要!有些第三方組件可能內部并沒有設置原生的事件 就可以通過.native來觸發事件

          面試問及

          之前在使用餓了么UI的時候給一個組件添加一個原生的事件 但是一直觸發不了 后面查閱文檔發現這個組件內部并沒有注冊我使用的原生事件 事件修飾符.native就可以直接監聽并觸發組件的原生事件

          • .capture
            添加事件偵聽器時使用 capture 模式
          • .{keyCode | keyAlias}
            只當事件是從特定鍵觸發時才觸發回調
          • .left
            (2.2.0版本) 只當點擊鼠標左鍵時才觸發
          • .right
            (2.2.0版本) 只當點擊鼠標右鍵時才觸發
          • .middle
            (2.2.0版本) 只當點擊鼠標中鍵時才觸發
          • .self
            只當事件使用偵聽器綁定的元素本身觸發時才觸發回調
          • .passive
            (2.3.0版本)以{ passive:true } 模式添加偵聽器

          ?4??.?4?? v-bind

          說明: 屬性綁定(行內屬性) 用法: v-bind:屬性名="Vue實例中的數據" => 簡寫 :屬性名="Vue實例中的數據" 當Vue實例中的數據改變之后 頁面會同步更新

          ?4??.?4??.1?? 屬性綁定修飾符

          • .prop
            被用于綁定 DOM 屬性 (property)
          • .camel
            (2.1.0+) 將 kebab-case 特性名轉換為 camelCase. (從 2.1.0 開始支持)
          • .sync
            (2.3.0+) 語法糖,會擴展成一個更新父組件綁定值的 v-on 偵聽器

          ?4??.?4??.2?? 對象的方式綁定class

          • :class = "{'red' : isRed}"

          isRed = true 就有red這個類 isRed = false 就沒有red這個類 isRed 在 Vue 實例data中聲明

          • 默認的class 和 :class(綁定的class) 一起使用不會沖突 后面的會作為追加或者移除來解析

          class = "red" :class = "{'yellow' : isYellow}"

          ?4??.?4??.3?? 對象的方式綁定style

          • :style = "{fontSize : mySize + 'px'}"
          • 樣式名需要使用駝峰命名法
          • 后面的mySize需要在Vue實例data中定義

          ?4??.?5?? v-model

          說明: 雙向數據綁定 用法: v-model = "Vue實例中的數據"

          ?4??.?5??.?1?? 雙向

          • 視圖層
          • 數據層
            數據能夠自動的從內存中顯示到頁面上去

          ?4??.?5??.?2?? 雙向綁定修飾符

          • .lazy
            懶載入 當表單屬性失去光標或按下回車鍵后 再將頁面中的數據和Vue實例中的數據雙向綁定
          • .trim
            輸入的數據首位空格過濾
          • .number
            輸入字符串轉為有效的數字

          注意: v-model 只能設置給from表單屬性

          ?4??.?6?? v-for

          說明: 循環渲染 用法: v-for = "(item,index) in items" :key = "index"

          items是源數據數組 item是被迭代的數組元素的別名 index是被迭代的數組元素的下標(索引)

          ?4??.?6??.?1?? :key

          • 數據唯一標識綁定
          • v-for默認行為試著不改變整體 而是替換元素 迫使其重新排序的元素需要提供一個key(用戶刪除數據后 數據需重新排列序號 就可以使用key來實現)
          • 數據實現重用和重新排序現有的元素
          • 值最好為字符串或數值類型(唯一的)

          ?4??.?6??.?2?? 遍歷數組注意點

          • Vue本身只是監視了Vue實例Data中數組的改變(監視內存地址) 沒有監視數組內部數據的改變
          • (變異方法)Vue重寫了數組中的一系列改變數組內部數據的方法(先調用原生的方法 再更新頁面) 所以實現了使用數組提供的方法 數組內部改變 界面自動改變

          push() pop() shift() unshift() splice() sort() reverse() ...

          • this.arr[index] = 新值

          這種修改數組中的元素是無法實現數據改變后頁面會同步改變(只會修改data中的數據 但是頁面不會同步改變)

          • splice()的增刪改
            增 this.arr.splice(index,0,新值)
            刪 this.arr.splice(index,1)
            改 this.arr.splice(index,1,新值)

          ?4??.?7?? v-if,v-else,v-else-if

          說明: 條件(表達式或布爾值)判斷渲染 用法: v-if = "表達式或布爾值" v-else-if = "表達式或布爾值" v-else

          ?4??.?7??.?1?? 注意

          v-if 和 v-else-if 后面必須跟表達式或布爾值 v-else-if 和 v-else 不能獨立使用 必須跟在 v-if 后面

          ?4??.?8?? v-show

          說明: 條件渲染 用法: v-show = "表達式或布爾值" 根據表達式或布爾值的真假切換元素的display屬性

          ?4??.?8??.?1?? 注意

          v-show 不支持 <template>元素 也不支持 v-else

          ?4??.?9?? v-if vs v-show

          都是用來判斷渲染數據的

          • v-if

          1.有較高的切換性能消耗 2.惰性渲染 第一次如果條件為false 則不會渲染到頁面 需要等后面條件切換后才會進行第一次渲染 3.條件切換是切換DOM數中這個元素的移除或添加 4.如果運行時條件很少改變則使用v-if

          • v-show

          1.有較高的初始渲染消耗 2.初始渲染 不管條件 第一次加載頁面的時候都會渲染到頁面 3.條件切換只是切換元素的display屬性 4.如果運行時條件會非常頻繁的切換則使用v-show

          ?4??.??1??0?? v-cloak

          說明: 這個指令保存在這個元素上 直到關聯實例結束編譯

          ?4??.??1??0??.?1?? 詳細說明

          插值表達式在網絡較滿的情況下可能會出現數據閃爍問題 可以通過給實例(#app)盒子添加一個 v-cloak 指令 通過這個指令的特性(如頁面中還有插值表達式就會存在這個指令 如果頁面的插值表達式都被替換成數據 就會自動移除這個標簽) 配合css [v-cloak]{display:none|opacity:0}來解決數據閃爍的問題

          ?4??.??1??1?? v-once

          說明: 這個指令添加的元素 內部的胡子語法只會在第一次渲染的時候執行解析一次 后面數據發生改變后也不會觸發更新

          ?4??.??1??1??.?1?? 用途

          某些元素只需要解析一次 后續不需要更新 就可以使用這個指令 提升性能


          ?5??、Vue實例

          ?5??.?1?? el

          • 與頁面中的元素綁定
          • 指定根element(選擇器)
          • 可以寫id、class、標簽選擇器
            建議使用id 因為id是唯一的 一個Vue實例綁定一個頁面元素
          • 注意: 不支持綁定body和html

          ?5??.?2?? data

          • 數據對象
          • 初始化數據(頁面可以訪問)
          • 可以在里面寫對象、字符串、數值、數組、...

          ?5??.?3?? methods

          • 方法對象
          • 可以在里面聲明一些方法
            可以通過this.xxx 獲取Vue實例上的數據或方法
          • 注意: 不要使用箭頭函數 會改變this指向

          ?5??.?4?? computed

          • 計算屬性
          • 可以在里面聲明一些函數
            必須要有 return 值
          • 計算屬性函數中如果使用到了data中的數據 這些數據發生改變后 就會重新執行這個計算屬性函數 將最新的計算結果返回出去
            執行時機:初始化顯示執行和函數中用到了data中的數據變化后會執行
          • 在頁面中直接用插值表達式使用計算屬性{{計算屬性函數名}} 計算屬性本質就是一個方法 但是使用的時候是將這些方法的方法名當作屬性使用 計算屬性的值就是return出來的值
          • getter 和 setter

          1.使用get和set函數 需要把計算屬性函數改成計算屬性對象 2.計算屬性默認執行get方法(根據相關的數據計算返回當前屬性的值) 3.當計算數學值自身改變后執行set方法 4.可以用來計算稅前和稅后的互推算

          • 計算屬性存在緩存 多次讀取只執行一次getter函數
            緩存 => {計算屬性名:"數據結果"} 鍵值對

          ?5??.?5?? watch

          • 偵聽屬性
          • 可以偵聽data中的屬性和一些非DOM元素的改變
          • 可以獲取數據改變前的值和改變后的值
            形參(newVal,oldVal) => (改變后的值,改變前的值)
          • 深度偵聽
            watch默認無法偵聽復雜數據類型 需要偵聽復雜數據類型 得使用深度偵聽
          watch:{
              XXX:{   
                  deep:true,
                  handler(newVal,oldVal){
                      // 處理代碼
                  }
              }
          }
          
          • 偵聽路由 hash
          watch: {
            // watch里面的 $router 這些對象前面不要帶this
            "$route.path"(newVal, oldVal) {
              if (newVal.indexOf("/login") >= 0) {
                this.welcom = "歡迎登陸";
              }
              if (newVal.indexOf("/register") >= 0) {
                this.welcom = "歡迎注冊";
              }
            }
          }
          
          • 子組件偵聽路由的變化
            watch: {
              $route: function(newVal,oldVal) {
                console.log(this.$route.path);
              }
            }
          
          • 面試問及:
            使用或偵聽器嗎 在Vue中碰到過什么bug

          1.偵聽器用來檢測數據的改變 2.當偵聽的那個數據發生改變后就會觸發偵聽器中的對應函數 3.一般我更多的使用是用偵聽路由的變化 => 重新獲取數據(如搜索在對應的router-view中顯示對應的數據) 4.之前碰到過一個坑點 偵聽器默認無法偵聽復雜數據類型 5.后面使用深度偵聽 depp:true 來解決了這個問題 6.或者偵聽精確到對象中的那個值也可

          ?5??.?6?? computed和watch的區別

          • watch里面的方法只能對那個方法名的屬性名做偵聽
          • computed里面可以對那個方法中所有使用到了的data中的屬性名做偵聽
          • watch里面無須return
          • computed需要return

          ?5??.?7?? components

          • 私有組件
          • 后面會有全局組件 更詳細

          ?5??.?8?? filters

          • 過濾器
            聲明全局過濾器 一定要在實例化Vue之前聲明
          • 全局過濾器
          Vue.filter("formatData", (形參=管道符前面的數據,形參=想要傳入的數據...) => {
              處理數據; `返回`處理之后的數據
          });
          
          • 局部過濾器
          filters:{ 
              formatTime(形參=管道符前面的數據,形參=想要傳入的數據...){
                  處理數據; `返回`處理之后的數據  }
           }
          
          • 在頁面中使用
            {{data | formatTime | formatTime1 | ...}}
          • 一個過濾器是一個函數 需要接收一個參數 參數就是處理的數據 (可以不傳 默認是 管道符前面的數據) 可以做一些邏輯處理后 再將處理好的數據返回出去
          • 不修改數據的情況下 修改數據的顯示效果 過濾器不會修改源數據

          ?6??、Vue實例中的this

          • this就是當前實例化出來的Vue對象(Vue實例)
          • Vue構造函數內部解析時 會把data、methods等中的值直接設置給這個實例化出來的Vue實例對象
          • 最終直接通過這個Vue實例對象即可訪問data中的數據以及methods中的方法等

          ?7??、Vue實例屬性

          ?7??.?1?? vm.$data

          獲取data中的所有數據

          ?7??.?2?? vm.$options

          用于當前Vue實例的初始化選項 可以獲取自定義選項

          new Vue({
            customOption: 'foo',
            created: function () {
              console.log(this.$options.customOption) // => 'foo'
            }
          })
          

          ?7??.?3?? vm.$refs

          • 通過給元素設定ref屬性在Vue實例中獲取這個元素
          • 頁面元素 ref="jack"
          • Vue實例獲取 this.$refs.jack
            返回的是一個DOM對象
          • 如果ref重名后面的會把前面的覆蓋

          ?8??、Vue組件

          ?8??.?1?? 什么是組件

          組件的出現就是為了拆分Vue實例的代碼量 能夠讓我們以不同的組件來劃分不同的功能模塊 需要什么功能就去調用對應的模塊即可 局部功能界面

          ?8??.?2?? 組件化和模塊化的區別

          • 模塊化
            是從代碼的邏輯角度去劃分的 方便代碼分層開發 保證每個功能模塊的職能單一
          • 組件化
            是從UI界面的角度進行劃分的 前端的組件化方便UI組件的重用

          ?8??.?3?? 全局組件

          ?8??.?3??.?1?? 用法

          Vue.component('組件名',{參數})

          ?8??.?3??.?2?? 注意

          組件名請使用小寫 大寫需要駝峰命名法

          Vue.component('sayHiBaby',{參數})
          頁面中標簽使用 <say-hi-baby></say-hi-baby>
          

          ?8??.?3??.?3?? 組件參數

          • props:['xxx']

          父向子傳參 通過 props 向子組件傳遞數據 可以在組件實例中通過 this.xxx 拿到傳遞過來的值 高級寫法(props驗證)

          props:{
            xxx:{
              // 數據類型
              type:"String",
              // 必須傳遞
              required:"true",
              // 默認值
              default:"mystring"
              ....
            }
          }
          

          props可以傳遞任何數據類型 包括函數

          • data(){ return{ } }
            組件中的數據data是一個函數 將數據寫在返回出去的對象中即可

          為什么組件的data是一個函數 而Vue實例的data是一個對象?

          1.每一個Vue組件都是一個Vue實例 2.都是通過new Vue() 創建出來的 3.如果data是一個對象的話 那么這些組件的引用指向就會相同 4.一個的值修改后 其他的值也會修改(這是JavaScript語法的特性) 5.如果data是一個函數 函數中再返回一個對象 6.那么每個Vue組件都有了自己的作用域 互不干擾

          • template
            模版
            動態的HTML頁面 包括一些JavaScript語法代碼
            注意: 如果模版中包含多個標簽 需要在最外層加一個div 作為根標簽
          • 其他參數和Vue實例的一致

          ?9??、Vue生命周期鉤子

          Vue生命周期鉤子 || Vue生命周期函數 Vue提供給開發者一系列的回調函數 讓我們可以在Vue的各個階段添加自定義的邏輯處理

          ?9??.?1?? 三大階段

          ?9??.?1??.?1?? 初始化顯示

          創建期間的生命周期函數(1次)

          • beforeCreate()
            Vue實例被創建 但date和methods數據中的數據還沒有被設置上去(未初始化)
          • created()
            data和methods以及被初始化(已被設置在Vue實例上)但是還未開始模版編譯
            常用 如果要操作data中的數據和methods中的方法 最早只能在created中調用
          • beforeMount()
            開始解析模版編譯 把數據和結構(模版)關聯起來 但現在頁面上還不能看到數據
          • mounted()
            數據掛載完畢 頁面中可以看到數據 當這個鉤子函數執行完畢 創建期間的所有的生命鉤子全部執行完
            常用 發送ajax請求 啟動定時器等異步任務 操作DOM中的節點

          Vue渲染解析插值表達式 并不是在頁面中直接渲染解析 而是將整個掛載在Vue實例的模版 拿到內存中去解析 等全部解析完成后 再一次性的渲染到頁面(批量) (因為有可能頁面中有很多一樣的data中的值 如果是在頁面中直接渲染解析會很耗性能)

          ?9??.?1??.?2?? 更新顯示

          運行期間的生命周期函數(0次-多次)

          • beforeUpdate()
            頁面中的數據還是舊的 但Vue實例中的數據已經被更新 數據還未同步
          • updated()
            頁面和Vue實例中的數據已同步

          ?9??.?1??.?3?? 銷毀

          銷毀期間的生命周期函數(1次)

          • beforeDestory()
            開始進入銷毀階段 Vue實例中的方法和數據還能使用 還未真正銷毀
            常用 做收尾工作 如:清除定時器...
          • destoryed()
            已被完全銷毀 Vue實例中的數據和方法不能再使用

          想要銷毀Vue實例 調用 vm.$destroy() 即可 注意: 這個方法方法并不會銷毀Vue實例的一些如 定時器或計時器等方法 會造成 '內存泄漏' 所以在完全銷毀之前 需要在 beforeDestory 鉤子中清除定時器等...


          ??1??0??、父子組件傳參

          ??1??0??.?1?? 父傳子

          • 子組件中定義 props 屬性 props:['num','max','min']
          • 父組件中使用子組件時 <comSon num='xxx' max='xx' :min='x'></comSon>

          ??1??0??.?2?? 子傳父

          • 子組件中 特定的時候 觸發 this.$emit('事件名A','參數')
          • 父組件中 <com @事件名A="自己methods中的方法"></com>

          ??1??1??、VueRouter

          ??1??1??.?1?? 前端路由

          url地址和組件之間的關系

          ??1??1??.?2?? 如果是模塊工程化(VueCLI)中使用VueRouter

          必須添加 Vue.use(VueRouter)

          import Vue from 'vue'
          import VueRouter from 'vue-router'
          Vue.use(VueRouter)
          

          ??1??1??.?3?? 路由起步代碼

          ??1??1??.?3??.?1?? HTML

          • router-link
            使用 router-link 來導航 最后會被渲染成a標簽
            可以通過 tag屬性 來設置最后被渲染的標簽
            to屬性 指定跳轉的鏈接
          <router-link to="/login" tag="span">登陸</router-link>
          <router-link to="/logout" tag="span">注冊</router-link>
          
          • router-view
            router-view 路由出口 路由匹配到的組件將渲染到這里
          <router-view></router-view>
          

          ??1??1??.?3??.?2?? JavaScript

          • 定義組件
          const login = { template: "#tempLogin" };
          const logout = { template: "#tempLogout" };
          
          • 定義路由
          const routes = [
            { path: "/login", component: login },
            { path: "/logout", component: logout }
          ];
          
          • 創建路由
          const router = new VueRouter({
            routes
          });
          
          • 綁定路由
            在Vue實例中 綁定router
          new Vue({
            el:"xxx",
            router
          })
          

          ??1??1??.?4?? 路由高亮

          設置路由匹配成功后 router-link 的樣式屬性

          • active-class 模糊匹配
            to設置的路由和url上面的路由只要前面的/xxx 匹配成功就會添加樣式
          /login => /login/user
          觸發 添加樣式
          
          • exact-active-class 全部匹配
            to設置的路由和url上的路由必須全部匹配才會添加樣式
          /login/user => /login/user
          觸發 添加樣式
          

          ??1??1??.?5?? 聲明式導航

          點了跳轉 沒有任何邏輯 類似于(a標簽設置了href) <router-link to="地址">XXX</router-link>

          ??1??1??.?6?? 編程式導航

          跳轉的同時執行其他需要執行的邏輯 router.push('地址')

          ??1??1??.?7?? 動態路由匹配

          • 將原本 router-link to 中的地址 /user => /user/:id
            :id 只是一個占位
          • 切換路由 /user => /user/123
          • 可以在組件中通過 this.$route.params.(id) 獲取傳遞過來的數據

          ??1??1??.?8?? 路由重定向

          • redirect : "跳轉的新地址"
          • {path:"地址1",redirect:"跳轉到的新地址2"}
          • 能夠實現 匹配到地址1之后 立刻跳轉到地址2

          ??1??1??.?9?? 前置導航守衛

          • 導航<路由> 當路由發生改變后 就會觸發導航守衛再進行路由跳轉
          const router = new VueRouter({ ... })
          router.beforeEach((to, from, next) => {
            // ...
            next()
          })
          

          to

          去哪個路由 一般通過to來判斷對應路由做對應處理

          from

          來自哪個路由

          next()

          必須next()才可以繼續跳轉頁面(像node"express"里面的中間件)

          • 執行時機 比組件的beforeCreate還要早

          1.判斷登陸狀態 如判斷token... 2.可以在跳轉路由時先判斷這個頁面這個用戶是否有權限訪問... 3.可以每次路由跳轉前都提示用戶跳轉至什么頁面...

          ??1??1??.??1??0?? 路由元信息

          • 給路由配置一個標示 配合導航守衛定位到這個路由 做一些對這個路由的邏輯處理
          • 給路由規則中配置一個meta對象
            meta: { requiresAuth: true }
          • 在導航守衛中就可以通過 to.meta.requiresAuth 是否為true 來判斷是否是對應路由

          ??1??1??.??1??1?? 嵌套路由

          • 在需要使用嵌套路由的組件中 找到需要動態替換的位置
            <router-view></router-view>
          • 修改路由規則
            在需要嵌套路由的組件的路由規則中添加 children:[ ]
            注意 嵌套路由的path不要加 /
          { path: '/user', component: User,
            children: [
              {
                path: 'index',
                component: Index
              }
            ]
          }
          

          ??1??1??.?1??2?? 統一404頁面

          配置錯誤路由規則

          • 錯誤路由
            {path:"/NotFound",component:NotFound}
          • 配置404
            {path:"*",redirect:'.NotFound'}
            注意 :這個匹配必須寫在路由規則的最下面 (當上面的路由匹配規則都不成功就會執行這個路由 然后跳轉到404錯誤頁面)

          ??1??1??.?1??3?? 路由懶加載

          • 當打包構建應用是 JavaScript 包會變得非常大 影響頁面加載 路由懶加載 把不同路由對應的組件分割成不同的代碼塊 當路由被訪問的時候才加載對應組件
          • 將原先 在router.js 中的 import Foo from "./Foo.vue"; 修改成 const Foo = () => import('./Foo.vue') 其他不變 即可
          • 路由懶加載并不能提速 只是把時間分開了 總時間沒變

          ??1??2??、資源請求

          ??1??2??.?1?? Axios

          ??1??2??.?1??.?1?? Axios是什么?

          Axios是一個基于 promise(實現了鏈式調用) 的 HTTP 庫 可以用在瀏覽器和 Node.js 中 專注于發請求 專注于網絡請求的一個庫`

          ??1??2??.?1??.?2?? CDN

          <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

          ??1??2??.?1??.?3?? .then

          成功回調

          ??1??2??.?1??.?4?? .catch

          失敗回調

          ??1??2??.?1??.?5?? get請求

          // 為給定 ID 的 user 創建請求
          axios.get('/user?ID=12345')
            .then(function (response) {
              console.log(response);
            })
            .catch(function (error) {
              console.log(error);
            });
          
          // 可選地,上面的請求可以這樣做
          axios.get('/user', {
              params: {
                ID: 12345
              }
            })
            .then(function (response) {
              console.log(response);
            })
            .catch(function (error) {
              console.log(error);
            });
          

          ??1??2??.?1??.?6?? post請求

          axios.post('/user', {
              firstName: 'Fred',
              lastName: 'Flintstone'
            })
            .then(function (response) {
              console.log(response);
            })
            .catch(function (error) {
              console.log(error);
            });
          

          ??1??2??.?1??.?7?? 基地址

          基礎的地址應用 沒有必要每次都寫 可以直接抽離出來

          axios.defaults.baseURL = '設置的基地址'
          Vue.prototype.$axios = axios
          

          axios填寫路徑時后面直接寫對應的路徑即可 前面的公共部分不需在寫(寫了也不會影響)

          ??1??2??.?1??.?8?? 設置跨域攜帶cookie

          axios.defaults.withCredentials = true

          ??1??2??.?1??.?8??.?1?? 面試問及

          • 坑點 axios 跨域默認不攜帶cookie
          • 某個項目 登陸狀態的判斷 后端用的是cookie
          • 登陸成功之后 服務器返回了cookie 標記登陸
          • 但axios在請求不同源的接口時 默認不會攜帶cookie
          • 所以后端接口后續一直無法獲取登陸狀態
          • 抓包后檢測網絡請求 發現瀏覽器并沒有把服務器返回的cookie給保留
          • 所以導致每次都沒設置成功cookie (set-cookie)
          • 設置 axios.defaults.withCredentials = true
          • 允許跨域攜帶cookie 這樣瀏覽器就能在跨域的時候存下cookie
          • 瀏覽器中無法直接查看跨域的cookie 瀏覽器隱藏了 可以通過抓包查看

          ??1??2??.?1??.?9?? 創建克隆對象 多基地址設置

          const xxx = axios.create({
            // 即地址
            baseURL: 'https://some-domain.com/api/',
            // 可以統一設置請求頭
            headers: {Authorization: token}
          });
          xxx.get()
          xxx.post()
          
          • 只需要使用axios的create創建多個副本 每個副本設置一個不同的基地址
          • 請求某個基地址的時候 使用該副本的對應方法即可

          ??1??2??.?1??.?1??0?? Axios攔截器

          ??1??2??.?1??.?1??0??.?1?? 請求攔截器

          axios.interceptors.request.use(function (config) {
              // 可以在發請求之前在這里設置一些請求頭
              `config.headers.Authorization=token`
              return config;
            }, function (error) {
              // Do something with request error
              return Promise.reject(error);
            });
          

          ??1??2??.?1??.?1??0??.?2?? 響應攔截器

          axios.interceptors.response.use(function (response) {
             // 可以在獲取響應數據之后設置一些提示 如獲取失敗/成功
             `response.data.code == 200?`
              return response;
            }, function (error) {
              // Do something with response error
              return Promise.reject(error);
            });
          
          • 可以在響應攔截器中判斷token是否造假
          • 是造假則可以直接清除本地的token...

          ??1??2??.?2?? vue-resource

          vue-resource已經不再更新 推薦使用Axios


          ??1??3??、Vue動畫鉤子

          ??1??3??.?1?? Vue動畫鉤子是什么?

          Vue提供的讓程序員可以在動畫的各個時機 添加 自定義邏輯 的鉤子 也可稱之為 動畫鉤子或動畫函數

          ??1??3??.?2?? Vue動畫的理解

          • 操作 css 和 trasition 或 animation
          • Vue 會給目標元素添加/移除特定的 class
          • 過渡的相關類名
          // 指定顯示的transition
          xxx-enter-active
          // 指定隱藏的transition
          xxx-leave-active
          // 指定隱藏時的樣式
          xxx-enter/xxx-leave-to
          

          ??1??3??.?3?? 單個元素動畫

          transition標簽包裹

          ??1??3??.?4?? 列表過渡動畫

          transition-group標簽包裹

          ??1??3??.?5?? name

          動畫樣式的開始類名

          ??1??3??.?6?? tag

          解析為的標簽名

          ??1??3??.?7?? 過渡類名參數

          • v-enter:
            定義進入過渡的開始狀態。在元素被插入之前生效,在元素被插入之后的下一幀移除。
          • v-enter-active
            定義進入過渡生效時的狀態。在整個進入過渡的階段中應用,在元素被插入之前生效,在過渡/動畫完成之后移除。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函數。
          • v-enter-to
            2.1.8版及以上 定義進入過渡的結束狀態。在元素被插入之后下一幀生效 (與此同時 v-enter 被移除),在過渡/動畫完成之后移除。
          • v-leave
            定義離開過渡的開始狀態。在離開過渡被觸發時立刻生效,下一幀被移除。
          • v-leave-active
            定義離開過渡生效時的狀態。在整個離開過渡的階段中應用,在離開過渡被觸發時立刻生效,在過渡/動畫完成之后移除。這個類可以被用來定義離開過渡的過程時間,延遲和曲線函數。
          • v-leave-to
            2.1.8版及以上 定義離開過渡的結束狀態。在離開過渡被觸發之后下一幀生效 (與此同時 v-leave 被刪除),在過渡/動畫完成之后移除。

          ??1??3??.?8?? 動畫時機

          • 條件渲染 (使用 v-if)
          • 條件展示 (使用 v-show)
          • 動態組件
          • 組件根節點
          • 動態的增刪元素 就會觸發進入動畫 以及移除動畫

          ??1??3??.?9?? 動畫鉤子代碼

          ??1??3??.?9??.?1?? HTML

          <transition
            v-on:before-enter="beforeEnter"
            v-on:enter="enter"
            v-on:after-enter="afterEnter"
            v-on:enter-cancelled="enterCancelled"
          
            v-on:before-leave="beforeLeave"
            v-on:leave="leave"
            v-on:after-leave="afterLeave"
            v-on:leave-cancelled="leaveCancelled"
          >
            <!-- ... -->
          </transition>
          

          ??1??3??.?9??.?2?? JavaScript

          // ...
          methods: {
            // --------
            // 進入中
            // --------
          
            beforeEnter: function (el) {
              // ...
            },
            // 當與 CSS 結合使用時
            // 回調函數 done 是可選的
            enter: function (el, done) {
              // ...
              done()
            },
            afterEnter: function (el) {
              // ...
            },
            enterCancelled: function (el) {
              // ...
            },
          
            // --------
            // 離開時
            // --------
          
            beforeLeave: function (el) {
              // ...
            },
            // 當與 CSS 結合使用時
            // 回調函數 done 是可選的
            leave: function (el, done) {
              // ...
              done()
            },
            afterLeave: function (el) {
              // ...
            },
            // leaveCancelled 只用于 v-show 中
            leaveCancelled: function (el) {
              // ...
            }
          }
          

          ??1??3??.??1??0?? 過渡動畫生命周期



          ??1??4??、VueX

          ??1??4??.1?? Vuex是什么?

          • 集中管理所有組件的數據
          • 可以把它理解為是一個倉庫
          • 將組件中公有的數據都抽到VueX中
          • VueX中的數據 所有的組件都可以獲取 所有的組件都可以修改

          ??1??4??.2?? 起步

          ??1??4??.2??.1?? 下載

          npm install vuex --save

          ??1??4??.2??.2?? 創建VueX倉庫

          import Vue from 'vue'
          import Vuex from 'vuex'
          
          Vue.use(Vuex)
          
          const store = new Vuex.Store({
            state: {
            // 數據
              count: 0
            },
            mutations: {
              // 方法
              increment (state) {
                state.count++
              }
            }
          })
          
          new Vue({
              el:xxx,
              // 掛載到Vue實例上
              store
          })
          

          ??1??4??.2??.3?? 在組件中獲取VueX的數據

          • HTML
            {{$store.state.count}}
          • JavaScript
            this.$store.state.count

          ??1??4??.2??.4?? 在組件中修改VueX的數據

          • VueX修改數據必須通過 mutations 中的方法修改數據
            this.$store.commit(''mutations中的方法,'參數')

          ??1??4??.3?? VueX - state

          • 數據
          • 所有組件的都可以使用 獲取數據

          ??1??4??.4?? VueX - mutation

          • 方法 修改state中的數據

          ??1??5??、VueCLI

          ??1??5??.1?? 單文件組件

          ??1??5??.1??.1?? 用一個文件能夠包含組件的所有內容

          • 結構
          <template>
          </template>
          
          • 邏輯
          <script>
          export default {
          }
          </script>
          
          • 樣式
          <style>
          </style>
          

          ??1??5??.1??.2?? 單文件開發的好處

          • 更利于編碼
          • 利于后期維護
          • 一個文件包含了所有內容

          ??1??5??.2?? 什么是Vue-CLI

          • 腳手架
          • 可以把.vue文件翻譯成瀏覽器可以識別的內容
          • 自動刷新瀏覽器
          • 自動壓縮代碼
          • 自動的把高版本的JavaScript翻譯成低版本的JavaScript
          • 作為代理服務器
          • ...

          把很多開發中需要用到的功能整合到了一起 讓Vue開發人員專注于邏輯代碼即可 是用webpack配置出來的

          ??1??5??.3?? 搭建一個腳手架

          vue create 項目名 <= 項目名不要有中文!!!不要大些 cd 項目名 npm run serve

          ??1??5??.4?? Vue-CLI搭建項目的本質

          • 創建文件夾
          • 下載第三方模塊
          • 創建項目的基本結構
          • 設置各個文件之間的關系
          • 創建git倉庫

          1??5??.5?? Vue-cli項目結構

          • main.js
            主要的文件 所有和頂級Vue實例相關的都放到這里
          • App.vue
            最頂級的組件 僅次于Vue實例 看到的頂級頁面結構一般都放在這里
          • /components
            組件的文件夾
          • /assets
            靜態資源

          1??5??.6?? 搭建webpack-vue腳手架(詳細版本)

          npm init webpack "項目名" cd "項目名" npm instal npm run dev

          最后一步選 No, I will handle that myself 自己再npm i 下載速度會快一點


          1??5??.7?? webpack-vue項目結構

          |-- build : webpack 相關的配置文件夾(基本不需要修改) 
                  |-- dev-server.js : 通過 express 啟動后臺服務器
          |-- config: webpack 相關的配置文件夾(基本不需要修改)
                  |-- index.js: 指定的后臺服務的端口號和靜態資源文件夾
          |-- node_modules 
          |-- src : 源碼文件夾
                  |-- components: vue 組件及其相關資源文件夾 
                  |-- App.vue: 應用根主組件
                  |-- main.js: 應用入口 js
          |-- static: 靜態資源文件夾
          |-- .babelrc: babel 的配置文件
          |-- .eslintignore: eslint 檢查忽略的配置
          |-- .eslintrc.js: eslint 檢查的配置
          |-- .gitignore: git 版本管制忽略的配置
          |-- index.html: 主頁面文件
          |-- package.json: 應用包配置文件
          |-- README.md: 應用描述說明的 readme 文件
          

          1??5??.8?? Vue-CLI項目編碼

          1??5??.8??.1?? 編碼位置

          • 組件的邏輯直接寫在xxx.vue中
          • 靜態資源放在assets文件夾下面 直接使用對應路徑引用即可

          1??5??.8??.2?? 引入css

          • 全局引入
            main.js => import "路徑"
          • 局部引入
            組件內的script標簽 => @import url("路徑")

          1??5??.8??.3?? 注冊組件

          • 全局組件
            引入在main.js中
            import 組件 from 地址
            Vue.component('組件名',組件)
            任意地方都可以使用 將組件名作為標簽名 一次注冊 全部使用
          • 局部組件
            在需要用到這個組件的地方 導入import 組件名 form '地址'
            導入后 設置給components 就可以在導入的組件中通過組件名使用該組件
            根據使用的位置 決定局部或者全局注冊 只在某些地方用 用局部組件
          • 組件中的name屬性
            直接在組件的內部寫name:值即可
            不能用中文
            寫了只會 Chrome的Vue插件中就可以看見這個名字 更加利于檢索 利于編碼

          1??5??.8??.4?? 整合路由

          1??5??.8??.4??.1?? 下包

          npm install vue-router

          1??5??.8??.4??.2?? 導包

          import VueRouter from 'vue-router'

          1??5??.8??.4??.3?? 用包

          • 創建路由規則
            在components文件夾下創建一個組件xxx.vue
            import 組件名 from '組件路徑'
            const routes = [{path:"/xxx/:xx},component:組件名]
          • 創建路由對象
          `const router = new VueRouter({
              routes
          })`
          
          • 設置給Vue實例
          `new Vue({
              router
          })`
          

          1??5??.8??.4??.4?? 編碼位置

          • 導入 注冊路由 main.js
          • router-link router-view app.vue
          • 添加組件components
          • 靜態資源assets

          1??5??.9?? 在Vue中使用其他插件

          • 可以將插件寫到Vue原型中 這樣在其他組件中都可以使用這個插件
          • (main.js)Vue.prototype.$XXX = XXX
          • (其他組件) this.$XXX
          • $XXX 的$的目的是 區分是Vue自帶的屬性還是后面自定義在原型中的屬性

          1??5??.9??.1?? 面試問及

          • Vue原型用過沒
          • 為了共享 將插件設置在Vue原型上
          • 所有組件都是Vue的實例
          • 所有在其他組件中 可以通過 this.$XXX 獲取

          1??5??.1??0?? css預處理與css作用域

          1??5??.1??0??.1?? css預處理

          1??5??.1??0??.1??.1??使用less

          • 下載
            -npm install -D less-loader less
          • 使用
            <style lang='less'></style> 也可以直接導入less文件

          1??5??.1??0??.1??.2?? 使用sass

          • 下載
            -npm install -D sass-loader node-sass
          • 使用
            <style lang='scss'></style> 也可以至今導入scss文件

          1??5??.1??0??.2?? css作用域

          • 為style標簽 添加 scoped 屬性即可
          • 生成樣式,和渲染組件時

          為元素添加隨機屬性 樣式中添加屬性選擇器 2者結合 就把css的作用范圍 約束

          • 為了不影響其他 可以添加這個屬性
          • 注意
            樣式的屬性是隨機生成的 如果要修改樣式
            直接修改在scoped中的樣式 不要抽離成樣式文件導入

          1??5??.1??1?? ES6模塊化語法

          1??5??.1??1??.1?? 默認導出導入

          • 導出
            export default xxx 只能寫一個 如果需要暴露多個 可以在default后面寫對象
          • 導入
            import xxx from "模塊"

          1??5??.1??1??.2?? 按名字導出導入

          • 導出
            export const bbb 導出和導入的名字必須一樣
          • 導入
            import {bbb} from "模塊"

          1??5??.1??2?? Vue全家桶

          • Vue
          • axios
          • Vue-router
          • 餓了么ui

          餓了么前端團隊開發的PC端的基于Vue的組件 內部封裝了很多現成的組件 在VueCLI中使用elementUI npm i element-ui import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) 有些組件并沒有在組件內部使用原生事件 但是有些情況需要一些原生事件 就可以使用.native修飾符來觸發

          • Vuex

          ??1??6??、擴展

          ??1??6??.1?? link 和 @import 的區別

          ??1??6??.1??.1?? link

          • link是html提供引入樣式的標簽
          • link沒有兼容性問題
          • 可以通過JavaScript來控制link標簽 修改樣式文件路徑
          • 會和html一起加載

          ??1??6??.1??.2?? @import

          • @import是提供的提供導入樣式的方法
          • @import有兼容問題 ie5以下不支持
          • 不能通過JavaScript來操縱@import
          • 等html全部加載完畢后再加載@import

          ??1??6??.2?? JavaScript數組方法

          • arr.filter()

          返回所有匹配成功的值 創建一個新數組, 其包含通過所提供函數實現的測試的所有元素 (數組過濾)

          const oldArr = ["dajsk", "dkjdklas", "kgjftlk", "ksf", "ds", "mfksjjks"];
          let res = oldArr.filter((val, index) => val.indexOf("d") != -1); // 返回所有匹配成功的值
          console.log(res); // [ 'dajsk', 'dkjdklas', 'ds' ]
          
          • arr.find()

          返回匹配的第一個值 返回數組中滿足提供的測試函數的第一個元素的值 沒有匹配成功返回undefined

          const oldArr = ["dajsk", "dkjdklas", "kgjftlk", "ksf", "ds", "mfksjjks"];
          let res1 = oldArr.find((val, index) => val.indexOf("d") != -1); // 返回匹配的第一個值
          console.log(res1); // dajsk
          
          • arr.map()

          將匹配成功的值做對應的計算后再次返回 創建一個新數組 其結果是該數組中的每個元素都調用一個提供的函數后返回的結果

          const oldArrMap = [3, 4, 7, 1, 8, 5];
          let res2 = oldArrMap.map((val, index) => {
            // 將匹配成功的值做對應的計算后再次返回
            if (val > 5) {
              val = val * 2;
            }
            return val;
          });
          console.log(res2); // [ 3, 4, 14, 1, 16, 5 ]
          

          因為這些方法都是返回的新數組 并沒有覆蓋原來的數組所以可以繼續鏈式調用數組的方法繼續過濾

          • arr.forEach()

          遍歷數組 方法對數組的每個元素執行一次提供的函數

          const oldArrForEach = [3, 6, 8, 2, 8, 0];
          let num = 0;
          oldArrForEach.forEach((val, index) => {
            num += val;
          });
          console.log(num); // 27
          oldArrForEach.forEach((val, index) => {
            if (index == 2) return console.log(val); // 8
          });
          

          ??1??6??.3?? 解決跨域方案

          • CORS
            服務器設置允許訪問 響應一個響應頭
            存在低版本不識別這個響應頭
          • JSONP
            瀏覽器script的src支持跨域訪問 發送一個callback去服務器
            服務器接收callback 返回一個函數的調用攜帶數據
            瀏覽器接收到返回值當作js執行 執行代碼

          注意 需要在瀏覽器聲明callback去的函數 需要在script請求前聲明 兼容性強 只能發送get請求

          • flash
            現已不用 蘋果不支持flash
          • sliverlight
          • WebSocket
          • postmessage
          • iframe
          • ...

          ??1??6??.4?? 接口的請求方法和restful api

          網絡請求設計方法時 考慮到數據的操作主要:增刪改查 方法的命名可以體現這個操作 一般常用的就是get和post

          1. GET(SELECT):從服務器取出資源(一項或多項).
          2. POST(CREATE):在服務器新建一個資源.
          3. PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源).
          4. PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性).
          5. DELETE(DELETE):從服務器刪除資源.
          6. HEAD:獲取資源的元數據.
          7. OPTIONS:獲取信息,關于資源的哪些屬性是客戶端可以改變的.

          ??1??6??.5?? Cookie、Session、token、localStorage、sessionStorage

          ??1??6??.5??.1?? Cookie

          • 用來解決http 是無狀態 的
          • 什么是無狀態?

          每次請求 瀏覽器和服務器交互完畢后 彼此并沒有留下什么 繼續請求 也無法判斷你是誰 如登陸功能 為了能夠保存一些信息 服務器返回響應報文時 會偷偷的帶一個響應頭 作用是在瀏覽器中偷偷保存一些信息set-cookie 瀏覽器接收到這個響應頭后 會在本地保存這個響應頭 第二次請求時 瀏覽器就會自動帶上這個信息去服務器 服務器接收到這個信息 就知道你是誰了 ajax跨域請求 默認不攜帶cookie 需要設置 跨域cookie在瀏覽器中無法看到 需要抓包

          ??1??6??.5??.2?? Session

          Seesion 是將用戶數據存儲在服務器中 通過sessionId來驗證查找服務器中的用戶信息 sessionId一般是存放在瀏覽器的cookie中的

          所以Session需要配合瀏覽器的cookie或者瀏覽器的其他存儲技術一起使用

          ??1??6??.5??.3?? token

          和cookie差不多 也可以記錄登陸狀態 服務器生成的 通過用戶瀏覽器版本、用戶信息...生成的一個密鑰

          瀏覽器不會自動保存 可以接口本地存儲來保存token 瀏覽器不會自動攜帶發送 每次請求接口時可以通過headers攜帶存儲的token headers{ Authorization :token }

          ??1??6??.5??.4?? localStorage

          可以把數據存儲到本地(瀏覽器) 只要用戶不刪除 則會一直保存 每個域名都是獨立的保存數據 不同域名不能互相訪問 長久保存數據可以存儲到 localStorage 可以存儲5M數據

          • 保存數據 localStorage.setItem(key,value)
          • 獲取數據 localStorage.getItem(key) => 如果沒有這個數據 則返回 null
          • 刪除一個數據 localStorage.removeItem(key)
          • 清空所有數據 localStorage.clear()

          ??1??6??.5??.5?? sessionStorage

          短暫存儲數據 可以多頁面傳值 相當于localStorage會更安全 瀏覽器關閉后就不會保存了 可以存儲5M數據

          • 保存數據 sessionStorage.setItem(key,value)
          • 獲取數據 sessionStorage.getItem(key) => 如果沒有這個數據 則返回 null
          • 刪除一個數據 sessionStorage.removeItem(key)
          • 清空所有數據 sessionStorage.clear()

          ??1??7??、Xmind筆記


          很多都是自己的話去解釋和理解 可能會存在錯誤 或者有錯別字 歡迎指出謝謝

          若有感興趣的小伙伴,需要VUE學習文檔思維導圖原圖的,關注我,私信回復獲?。篤UE學習文檔思維導圖


          作者:藍海00
          轉載鏈接:https://www.jianshu.com/p/125ce0c89603

          目開發中遇到導入表格常見的就是excel和csv 格式,一般情況下我們會前端首先得到這個表格里面的數據,然后再把數據發送給后端,也有的是直接上傳文件傳給后臺后臺自己處理,這樣就不好控制上傳前預覽和處理數據,如果不需要預覽直接上傳的需求,那還是直接上傳文件交給后臺處理,本文實例是基于vue+elementu-ui 表格去實現。

          需要的依賴庫--papaparse,xlsx


          https://www.papaparse.com/


          1.安裝

           

          主站蜘蛛池模板: 在线精品国产一区二区三区| 国产成人无码精品一区二区三区| 亚洲AV永久无码精品一区二区国产 | 黑巨人与欧美精品一区| 精品一区中文字幕| 亚洲综合一区二区| 人妻少妇一区二区三区| 国产中文字幕一区| 色窝窝免费一区二区三区| 一区二区三区视频在线| 红桃AV一区二区三区在线无码AV | 91福利国产在线观一区二区| 亚洲国产精品一区二区九九| 狠狠综合久久av一区二区 | 国产精品成人一区二区| 日本精品一区二区三本中文| 国产对白精品刺激一区二区| 亚洲国产精品自在线一区二区| A国产一区二区免费入口| 深夜福利一区二区| 日美欧韩一区二去三区| 成人区人妻精品一区二区不卡| 美女毛片一区二区三区四区| 无码AV中文一区二区三区| 亚洲一区二区三区自拍公司| 久久精品中文字幕一区| 亚洲视频一区二区| 一区二区三区在线播放| 亚洲国产激情一区二区三区| 日韩精品一区二区三区不卡| 国产人妖在线观看一区二区| 久久久无码精品人妻一区| 亚洲AV无码一区二区乱子仑| 中文精品一区二区三区四区| 亚洲色精品三区二区一区| 国产乱码精品一区二区三区麻豆 | 亚洲第一区二区快射影院| 91成人爽a毛片一区二区| 亚拍精品一区二区三区| 国产乱码精品一区二区三区中| 国模私拍福利一区二区|