异步组件

在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。

我们在指定路由所对应的组件,或是,在注册组件时,可以使用异步组件。

Demo.vue

在这里插入图片描述

<template>
    <div>
        <!-- 当第一次点击async1此按钮时,才会发送请求:http://localhost:8081/js/src_test_Async1_vue.js,获取下面的/async1对应的组件,由于它是异步组件,所以要先获取组件渲染函数,
             async2同理,
             asyncNo不是异步组件,所以,在刚开始就加载了。 -->
        <el-button @click="$router.push('/async1')">async1</el-button>
        <el-button @click="$router.push('/async2')">async2</el-button>
        <el-button @click="$router.push('/asyncNo')">asyncNo</el-button>

        <hr/>
        
        
        <!-- 当第一次点击此按钮时, 才会发送请求:http://localhost:8081/js/async3.js,获取下面的Async3的组件渲染函数。
             后面都不会加载了,因为已经有了这个组件。注意,这里的加载不是指创建 Async3 这个组件实例,而是这个组件渲染函数 要有组件渲染函数,然后应用该组件,才会有组件实例-->
        
        <el-button @click="async3Show = !async3Show">showAsync3</el-button>
       
        <div v-if="async3Show">
            <Async3/>
        </div>
        
    </div>
</template>

<script>

export default {
    name: 'Demo',
    data() {
        return {
            async3Show: false
        }
    },
    components: {
    
    	/* 可以在工厂函数中返回一个 Promise,所以把 webpack 2 和 ES2015 语法加在一起,我们可以这样使用动态导入 */
        Async3: () => import(/* webpackChunkName: "async3"*/"@/test/Async3"),
        
        /*这个特殊的 `require` 语法将会告诉 webpack 自动将你的构建代码切割成多个包,这些包会通过 Ajax 请求加载*/
        // Async3: resolve => require(['@/test/Async2.vue'], resolve), // 这种方式也可以实现异步组件
        
    }
}
</script>

<style>

</style>

Async1.vue

<template>
    <div>
        我是异步组件1
        <el-button @click="$router.push('/demo')">/demo</el-button>
    </div>
</template>

<script>

/* 异步组件:当第一次切换到当前组件时候,才会去后台请求异步组件渲染函数,请求完了之后,下面这句代码才会执行,然后根据这个渲染函数创建组件实例 */
console.log('异步组件1...');

export default {
    name: 'Async1',
    components: {
    },
    created() {
        console.log('我是异步组件1 created');
    }
}
</script>

<style>

</style>

Async2.vue

<template>
    <div>
        我是异步组件2
        <el-button @click="$router.push('/demo')">/demo</el-button>
    </div>
</template>

<script>

/* 异步组件:当第一次切换到当前组件时候,才会去后台请求异步组件渲染函数,请求完了之后,下面这句代码才会执行,然后根据这个渲染函数创建组件实例 */
console.log('异步组件2...');

export default {
    name: 'Async2',
    components: {
    },
    created() {
        console.log('我是异步路由组件2 created');
    }
}
</script>

<style>

</style>

Async3.vue

<template>
    <div>
        我是异步组件3
        <el-button @click="$router.push('/demo')">/demo</el-button>
    </div>
</template>

<script>

/* 异步组件:当第一次切换到当前组件时候,才会去后台请求异步组件渲染函数,请求完了之后,下面这句代码才会执行,然后根据这个渲染函数创建组件实例 */
console.log('异步组件3...');

export default {
    name: 'Async3',
    components: {
    },
    created() {
        console.log('我是异步路由组件3 created');
    }
}
</script>

<style>

</style>

AsyncNo.vue

<template>
    <div>
        我不是异步路由
        <el-button @click="$router.push('/demo')">asyncNo</el-button>
    </div>
</template>

<script>

/* 这个在没有切换到该组件时, 就已经被router.js中引入执行了,只会执行一次 */
console.log('非异步组件...');

export default {
    name: 'AsyncNo',
    components: {
    },
    created() {
        console.log('我是非异步路由组件 created');
    }
}
</script>

<style>

</style>

异步组件处理加载状态

在这里插入图片描述

Demo.vue

<template>
    <div>
        
        <el-button @click="async4Show = !async4Show">showAsync4</el-button>
        
        <div v-if="async4Show">
            <Async4/>
        </div>
        
    </div>
</template>

<script>

import LoadingComponent  from './Loading.vue';
import ErrorComponent  from './Error.vue';

export default {

    name: 'Demo',
    
    data() {
        return {
        
            async4Show: false,
            
        }
    },
    
    components: {
       
        Async4: ()=>{
            return {
                // 需要加载的组件 (应该是一个 `Promise` 对象)
                component: import('@/test/Async4'),
                // 异步组件加载时使用的组件
                loading: LoadingComponent,
                // 加载失败时使用的组件
                error: ErrorComponent,
                // 展示加载时组件的延时时间。默认值是 200 (毫秒)
                delay: 200,
                // 如果提供了超时时间且组件加载也超时了,
                // 则使用加载失败时使用的组件。默认值是:`Infinity`
                timeout: 500
            }
        },
    }
}
</script>

<style>

</style>

Async4.vue

<template>
    <div>
        我是异步组件4
        <el-button @click="$router.push('/demo')">/demo</el-button>
    </div>
</template>

<script>

/* 异步组件:当第一次切换到当前组件时候,才会去后台请求异步组件渲染函数,请求完了之后,下面这句代码才会执行,然后根据这个渲染函数创建组件实例 */
console.log('异步组件4...');

export default {
    name: 'Async4',
    components: {
    },
    created() {
        console.log('我是异步路由组件4 created');
    }
}
</script>

<style>

</style>

Loading.vue

<style lang="scss">
    body {
        margin: 0;
    }
    .modal {
        background: #202020;
        height: 100vh;
        width: 100vw;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .loading {
        position: relative;
        width: 50px;
        height: 50px;
        div {
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            margin: auto;
            position: absolute;
            width: 5px;
            height: 20px;
            border-radius: 5px;
            background-color: #ff7300;
            animation: loading-spin 1s infinite;
        }
    }
    @keyframes loading-spin {
        0% {
            opacity: 0;
        }
        100% {
            opacity: 1;
        }
    }
    .loading .item1 {
        transform: rotate(30deg) translate(0,-120%);
        animation-delay: 1.1s;

    }
    .loading .item2 {
        transform: rotate(60deg) translate(0,-120%);
        animation-delay: 1s;
    }
    .loading .item3 {
        transform: rotate(90deg) translate(0,-120%);
        animation-delay: 0.9s;

    }
    .loading .item4 {
        transform: rotate(120deg) translate(0,-120%);
        animation-delay: 0.8s;

    }
    
    .loading .item5 {
        transform: rotate(150deg) translate(0,-120%);
        animation-delay: 0.7s;

    }
    .loading .item6 {
        transform: rotate(180deg) translate(0,-120%);
        animation-delay: 0.6s;
    }
    .loading .item7 {
        transform: rotate(210deg) translate(0,-120%);
        animation-delay: 0.5s;
    }
    .loading .item8 {
        transform: rotate(240deg) translate(0,-120%);
        animation-delay: 0.4s;

    }
    .loading .item9 {
        transform: rotate(270deg) translate(0,-120%);
        animation-delay: 0.3s;

    }
    .loading .item10 {
        transform: rotate(300deg) translate(0,-120%);
        animation-delay: 0.2s;

    }
    .loading .item11 {
        transform: rotate(330deg) translate(0,-120%);
        animation-delay: 0.1s;

    }
    .loading .item12 {
        transform: rotate(360deg) translate(0,-120%);
        animation-delay: 0s;

    } 
</style>
<template>
    <div class="modal">
        <div class="loading">
            <div class="item1"></div>
            <div class="item2"></div>
            <div class="item3"></div>
            <div class="item4"></div>
            <div class="item5"></div>
            <div class="item6"></div>
            <div class="item7"></div>
            <div class="item8"></div>
            <div class="item9"></div>
            <div class="item10"></div>
            <div class="item11"></div>
            <div class="item12"></div>
        </div>
    </div>
</template>

<script>

export default {
    name: 'loading',
    components: {
    }
}
</script>


Error.vue

<template>
    <div>
        加载出错啦
    </div>
</template>

<script>

export default {
    name: 'Error',
    components: {
    }
}
</script>

<style>

</style>
Logo

前往低代码交流专区

更多推荐