vue11----前端優化、路由懶加載(異步組件)、keep-alive、localStorage二次封裝、vue-lazyload圖片懶加載、mint-ui、封裝加載loading條、axios請求

### 優化

    一、加載速度的優化
        ①雪碧圖---->base6四、iconfont
        ②代碼壓縮
        ③圖片視頻壓縮
        ④cdn緩存
        ⑤路由懶加載(異步組件) 首頁引入的大文件進行分批次引入

 

    二、運行效率優化
        ①減小http請求,頁面打開以後基本不涉及到數據更改
            <keep-alive include="['a','b']" exclude="['a','b']"></keep-alive>
 
            正常的組件切換的時候執行建立和銷燬,加上keep-alive後,組件保存到緩存中,不會執行建立和銷燬。
        
        ②數據本地化(localStorage session(能夠用keep-alive代替) cookie)
            a、發起ajax前,先看一下本地緩存有沒有,若是有就在緩存中取,若是沒有再發起請求
            b、localStorage的二次封裝
                (1)考慮兼容問題
                (2)簡化讀取與存儲
                (3)有時間限制
            c、圖片懶加載
                ui框架
                插件:vue-lazyload

 

    三、用戶體驗優化
        ①加載體驗
        ②加載的loading條

 

### 路由懶加載(異步組件)(router.js)

    原理:將每一個組件都打成一個包,這樣首頁引入的大文件就進行分批引入。
 
    實現:將全部的同步組件引入方式改成異步組件引入方式。
        // import Recommend from "pages/Recommend.vue";
        // import Singer from "pages/Singer.vue";
        // import Detail from "pages/Detail.vue";
        // 改成路由懶加載方式引入:引入組件的方式從同步變爲異步
        const Recommend=()=>import("pages/Recommend.vue");
        const Singer=()=>import("pages/Singer.vue");
        const Detail=()=>import("pages/Detail.vue");
    此時,npm run build後在dist/js中多一個 chunk-00e2fa9f.7be196b5.js 文件。注意:npm run build後dist/js中的map文件能夠所有刪除。

 

### <keep-alive></keep-alive>(App.vue)

    原理:<keep-alive>是vue的一個內置組件,被<keep-alive>包裹的組件,不會反覆的經歷建立與銷燬,它在第一次建立後就會保存在緩存中,下次頁面切換時直接從緩存中讀取。
 
    場景:頁面打開後,基本涉及到數據更改的組件用<keep-alive>包裹,<keep-alive>和<template>同樣,不會顯示在頁面上。
 
    生命週期:加上keep-alive後產生的兩個生命週期:activated、deactivated
        created() {
            console.log("歌手建立")
        },
        mounted() {
            console.log("歌手掛載")
        },
        activated() {
            console.log("歌手緩存激活,進入keep-alive")
        },
        deactivated() {
            console.log("歌手緩存停用,離開keep-alive")
        },
        第一次進入歌手頁面,會觸發建立、掛載、緩存激活,離開時觸發緩存停用,後面再進入和離開只會觸發緩存激活和緩存停用。這樣用keep-alive包裹的組件不進行數據請求了,以此來減小http請求,若是須要數據請求,在activated生命週期進行數據請求。
 
    屬性:<keep-alive include="" exclude="" max=5></keep-alive>
        include:包括,這裏填寫的組件是將被緩存的組件,屬性值爲字符串或正則
        exclude:排除,這裏填寫的組件是不須要被緩存的組件(實時更新的組件),屬性值爲字符串或正則
        max:最多能緩存多少個組件,屬性值爲Number
 
        注意:
            一、include 和 exclude 屬性容許組件有條件地緩存。兩者均可以用逗號分隔字符串、正則表達式或一個數組來表示:
                <!-- 逗號分隔字符串 -->
                <keep-alive include="a,b">
                    <component :is="view"></component>
                </keep-alive>

                <!-- 正則表達式 (使用 `v-bind`) -->
                <keep-alive :include="/a|b/">
                    <component :is="view"></component>
                </keep-alive>

                <!-- 數組 (使用 `v-bind`) -->
                <keep-alive :include="['a', 'b']">
                    <component :is="view"></component>
                </keep-alive>
            二、include和exclude不能同時使用
 
    例子:App.vue中給router-view套上keep-alive標籤:
        <keep-alive>
            <router-view></router-view>
        </keep-alive>
    此時,在推薦和歌手組件來回切換的時候,在Network裏的js,就會進行緩存,不會一直請求。

 

### 數據本地化:localStorage的二次封裝

    思路:
        (1)考慮兼容問題
        (2)簡化讀取與存儲
        (3)有時間限制
    
    代碼實現:
        ①在utils中新建localStorage.js文件:
            export default{
                set(key,data,expiresTime){
                    let obj={
                        data:data,
                        ctime:(new Date()).getTime(),//時間戳,同Date.now()
                        expiresTime:expiresTime||1000*60*60 // 若是沒有傳過時時間,則設置過時時間一個小時
                    }
                    localStorage.setItem(key,JSON.stringify(obj));
                },
                get(key){
                    let obj=JSON.parse(localStorage.getItem(key));
                    let getItem=(new Date()).getTime();
                    if(getItem-obj.ctime>=obj.expiresTime){
                        // 若是超時
                        localStorage.removeItem(key);
                        return null;
                    }else{
                        // 未超時
                        return obj.data;
                    }
                }
            }
        ②main.js中引入並註冊到Vue對象中:
            import LocalStorage from "utils/localStorage.js";
            Vue.prototype.$localStorage=LocalStorage;
        ③在任意組件,如Singer.vue中,經過this.$localStorage對象可使用set()和get():
            this.$localStorage.set("name","吳小明")
            console.log(this.$localStorage.get("name"))

 

### 圖片懶加載插件:vue-lazyload(Singer.vue)

    ①下載依賴:
        npm install vue-lazyload
    ②引入和添加配置項(main.js):
        import VueLazyLoad from "vue-lazyload";
        Vue.use(VueLazyLoad,{
            preLoad:1.3,                               // 預加載
            error:require("./assets/musicLogo.png"),   // 錯誤時顯示
            loading:require("./assets/musicLogo.png"), // 加載時顯示
            attempt:1                                  // 每次加載多少張
        });
    ③v-lazy指令(Singer.vue):
        將須要圖片懶加載的img中 :src 替換爲 v-lazy:
            <img :src="info.avatar">
            替換爲
            <img v-lazy="info.avatar">
            此時,在Singer.vue中Network的img只加載了首屏的圖片,隨着屏幕滾動,加載更多的圖片。

 

### UI框架 

    pc端:iView框架:https://www.iviewui.com/
    移動端:mint-ui

 

### mint-ui(Rank.vue)

    ①下載依賴:
        npm install mint-ui
    ②main.js中作全局引入,任何組件均可以用:
        import MintUI from "mint-ui";
        import "mint-ui/lib/style.css";
        Vue.use(MintUI);
    ③Rank.vue中引入想要使用的組件(Toast提示和loading條):
        import {Toast,Indicator} from "mint-ui";
    ④設置Toast提示的按鈕和點擊事件:
        <button @click="toast">toast</button>


        methods: {
            toast(){
                Toast({
                    message:"點擊我了,操做成功",   // 信息
                    position:"center",  // 位置
                    duration:3000       // 持續時間
                });
            }
        }
    ⑤模擬數據加載時的loading條:
        created() {
            Indicator.open({
                text:"加載中",
                spinnerType:"fading-circle"
            });
            setTimeout(() => {
                Indicator.close();
            }, 2000);
        }
    ⑥在main.js中已經引入mint-ui和css文件的前提下,能夠直接在組件中使用mt-button組件(Toast()須要在使用的時候在組件中進行引入):
        <mt-button type="default">default</mt-button>
        <mt-button type="primary">primary</mt-button>
        <mt-button type="danger">danger</mt-button>

 

### 封裝加載loading條(Recommend.vue)

    ①建立Loading組件:
        <template>
            <div class="loading">
                <img :src="img">
            </div>
        </template>
        <script>
        // 以base64的方式引入圖片
        import img from "../assets/loading.gif";
        export default {
            data() {
                return {
                    img:img
                }
            },
        }
        </script>
        <style lang="less">
        @import "~style/index.less";
        .loading{
            position: fixed;
            top: 0;bottom: 0;
            left: 0;right: 0;
            margin: auto;
            display: flex;
            justify-content: center;
            align-items: center;
            img{
                .w(30);
                .h(30);
            }
        }
        </style>
    ②Recommend.vue中引入組件,而且在data中聲明 loading:true
        import Loading from "components/Loading.vue";

        data() {
            return {
                loading:true,
                songList:[]
            }
        }
    ③對ul中數據進行loading條優化,Loading組件和ul是二選一的關係:
        <Loading v-if="loading"></Loading>
        <ul v-else class="songList">
                <!-- -->
            <li v-for="(item,index) in songList" :key="index" @click="goDateil(item.creator.encrypt_uin)">
                <img :src="item.imgurl">
                <div class="info">
                    <h2>{{item.creator.name}}</h2>
                    <p>{{item.dissname}}</p>
                </div>
            </li>
        </ul>
    ④在拿到songList數據的同時,設置 this.loading=false;
        axios.get(url,(err,data)=>{
        }).then((data)=>{
            this.songList=data.data.list;
            this.loading=false;
        });

 

### axios請求以post方式請求 x-www 格式的數據(demo)

    原理:axios請求格式默認爲json,有的時候須要請求 x-www-form-urlencoded 的格式,此時頁面會報404,須要將 content-type 屬性設置爲 application/x-www-form-urlencoded ,再將data參數用qs.stringify()進行轉化。
 
    ①下載axios和qs依賴:
        npm install axios qs
    ②main.js中引入axios,並設置給Vue:
        import axios from "./utils/axios.js";
        Vue.prototype.$axios=axios;
    ③根目錄下新建vue.config.js文件處理跨域:
        module.exports={
            devServer:{
                port:8989,
                proxy:{
                    "/maoEr":{
                        target:"https://www.missevan.com",// 目標服務器路徑
                        changeOrigin:true,// 是否容許改變源,默認爲true
                        pathRewrite:{// 重寫路徑
                            "^/maoEr":""
                        }
                    },
                }
            }
        }
    ④App.vue中作數據請求(引入qs:import qs from "qs";):
        mounted() {
            let url="/maoEr/site/getcomment";
            let data={
                order:1,
                pagesize:10,
                type:1,
                eId:1284079,
                p:1
            }
            const options={
                method:"POST",
                headers:{"content-type":"application/x-www-form-urlencoded"},
                data:qs.stringify(data),// 須要下載qs依賴,npm i qs,node中queryString()有一樣效果
                url:url,
            }
            this.$axios(options).then((data)=>{
                console.log(data)
            });
        }
    注意:若是使用node中的queryString有同樣的效果,能夠不用下載qs依賴。
        ①先引入queryString:
            const querystring = require('querystring');
        ②
         data:qs.stringify(data),    
             替換爲
          data:querystring.stringify(data),

 

### nginx代理(demo)

    線上環境:npm run build 打包成一個靜態文件夾,丟到服務器目錄下,上線完成。
 
    場景:解決npm run build以後的代理失效
 
    原理:在vue.config.js中配置的代理服務器是由本地的npm run serve啓動的服務器作支持,而npm run build後的index.html沒有服務器支持,代理失效,數據請求所有失效。
 
    注意:npm run build後的index.html直接打開會報錯,此時將其中全部的css和js文件前面加上 . ,表示當前路徑下。
 
    步驟:
        ①下載nginx:http://nginx.org/en/download.html
        ②將dist文件夾拷貝到nginx/html文件夾中
        ③雙擊nginx.exe,cmd打開nginx目錄,輸入nginx -s reload,沒有報錯就成功了
        ④在地址欄輸入當前電腦的ip,能夠進入welcome to nginx,至關於雙擊打開index.html,在地址後面加上 /dist 能夠打開 npm run build 後的項目。此時打開Network,能夠發現請求地址由 http://localhost:52330/maoEr/site/getcomment 變爲 http://192.168.43.185/maoEr/site/getcomment
        ⑤nginx/conf/nginx.conf文件下設置跨域代理:
            location /maoEr {
                proxy_pass https://www.missevan.com/;#注意這個域名後面有 / ,若是是ip不用加 /
            }
        ⑥遠程服務器上雙擊nginx.exe,nginx文件夾進入cmd,輸入nginx -s reload

 

    nginx命令:
        nginx -s reload
        start nginx
        nginx -s stop

 

### 前端攔截 前端安全

    一、鑑權 token session+cookie
    二、攔截 路由攔截器 路由守衛 路由導航

 

### 路由守衛

    一、全局前置守衛(全部的路由跳轉都會通過這個函數):(router/index.js)
        router.beforeEach((to,from,next)=>{
            console.log("去哪裏",to)
            console.log("從哪來",from)
            let token=false;
            if(to.name=="About"){
                if(token){
                    next();
                }else{
                    next("/login");
                }
            }else{
                next();
            }
        })
        場景:控制某些頁面未登陸狀況下不可進,跳轉至登陸頁面。
 
    二、路由獨享守衛(路由配置項中使用,只對當前路由起做用):(router/index.js)
        {
            path: '/login',
            name: 'Login',
            component: () => import('../views/Login.vue'),
            beforeEnter: (to, from, next) => {
                console.log("去哪兒",to)
                console.log("從哪來",from)
                next();
            }
        }
    三、組件內守衛:(About.vue)
        (1)進入路由前(此時路由尚未進來,組件未建立,沒有this):
            beforeRouteEnter(to, from, next) {
                console.log("組件進入前")
                next();
            }
        (2)路由更新時:
 
            組件複用時,例如用動態導航傳參(在路由中更改about的path爲 /about/:id,經過params接收參數),在mounted生命週期中只有第一次能獲取到參數,這會形成在詳情頁的地址欄更換,但頁面不變。此時,能夠用到beforeRouterUpdate(),能夠用to.params.id獲取到參數。
            beforeRouterUpdate(to, from, next) {
                console.log("組件更新",to.params.id)
                next();
            }
            另外,能夠經過watch監聽獲取參數:
                watch: {
                    $route(newValue){
                        console.log("watch",newValue.params.id)
                    }
                }
        (3)路由離開時,能夠在離開前作一些判斷:
            beforeRouteLeave(to, from, next) {
                console.log("組件要離開",this)
                // console.log("去哪兒", to);
                // console.log("從哪來", from);
                let state = confirm("肯定要離開嗎");
                if (state) {
                    next();
                }
            }

 

### mint-ui下拉刷新,上拉加載更多

    ①下載依賴:
        npm install mint-ui
    ②main.js中作全局引入:
        import MintUI from "mint-ui"
        import "mint-ui/lib/style.css"
        Vue.use(MintUI)
    ③Home.vue中:
        <template>
            <div class="home">
                這裏是首頁
                <mt-loadmore
                    :top-method="loadTop"
                    :bottom-method="loadBottom"
                    :bottom-all-loaded="allLoaded"
                    ref="loadmore"
                >
                    <ul>
                        <li v-for="(item,index) in list" :key="index">{{item.name}}</li>
                    </ul>
                </mt-loadmore>
            </div>
        </template>
        <script>
        export default {
            data() {
                return {
                    list: [
                        { name: "AAA" },
                        { name: "BBB" },
                        { name: "CCC" },
                        { name: "DDD" },
                        { name: "EEE" },
                        { name: "FFF" },
                        { name: "RRR" },
                        { name: "HHH" },
                        { name: "NNN" }
                    ],
                    allLoaded: false
                };
            },
            methods: {
                loadTop() {
                    let url = "/api/city/city/getHotCityList?version=6.0.4&referer=2";
                    this.$axios
                        .get(url, () => {})
                        .then(data => {
                            this.list = data.data.hot_city_List; // 拿到數據後讓頁面回到原位
                            this.$refs.loadmore.onTopLoaded();
                        });
                },
                loadBottom() {
                    setTimeout(() => {
                        this.list = this.list.concat([
                            { name: "窗前明月光" },
                            { name: "疑是地上霜" },
                            { name: "舉頭望明月" },
                            { name: "低頭思故鄉" }
                        ]);
                        console.log(this.list);
                        this.allLoaded = false;
                        this.$refs.loadmore.onBottomLoaded();
                    }, 1000);
                }
            }
        };
        </script>
        <style>
        .home {
            overflow: scroll;    // 注意:若是上拉函數沒法觸發,是由於這裏沒有設置超出滾動
        }
        li  {
            height: 50px;
            font-size: 20px;
        }
        .mint-loadmore-text  {
            font-size: 20px !important;
        }
        .mint-loadmore-content {
            font-size: 20px !important;
        }
        </style>

 

### Q:

    一、本身封裝過哪些組件和模塊?
        組件:loading條的封裝
        模塊:localStorage的二次封裝
相關文章
相關標籤/搜索