【vue】组件之动态与异步

动态组件

<component v-bind:is=""></component>实现动态组件。

<body>
    <div id="root">
        <component v-bind:is="currentId"></component>
        <button v-on:click="handleClick">toggle</button>
    </div>
</body>
import Vue from "vue";

Vue.component("one-component",{
    template:"<div>hello</div>",
    mounted:function(){
        console.log("hello:enter mounted")
    }
});
Vue.component("two-component",{
    template:"<div>world</div>",
    mounted:function(){
        console.log("world:enter mounted");
    }
})
const vm = new Vue({
    el:"#root",
    data:{
        currentId:"one-component"
    },
    methods:{
        handleClick:function(){
            if(this.currentId === "one-component"){
                this.currentId = "two-component";
            }else if(this.currentId === "two-component"){
                this.currentId = "one-component";
            }
        }
    }
});

在这里插入图片描述
首次加载网页,渲染"hello"所在组件;
从"hello"到"world",渲染"world"所在组件;
从"world"回到"hello",重新渲染"hello"所在组件;
从"hello"再到"world",重新渲染"world"所在组件;
怎么保存组件状态,避免反复重新渲染组件?keep-alive

keep-alive
<body>
    <div id="root">
        <keep-alive>
            <component v-bind:is="currentId"></component>
        </keep-alive>
        <button v-on:click="handleClick">toggle</button>
    </div>
</body>

在这里插入图片描述
使用<keep-alive></keep-alive>后,"hello"所在组件、"world"所在组件仅在首次加载时渲染了一次,随后的切换没有重新渲染。

异步组件
<body>
    <div id="root">
        <my-component></my-component>
    </div>
</body>
import Vue from "vue";

Vue.component("my-component",function(resolve){
    setTimeout(function(){
        resolve({
            template:"<div>hello world</div>"
        })
    },3000);
}
);

const vm = new Vue({
    el:"#root"
});

在这里插入图片描述

动态导入

1

<!-- index.html -->
<body>
    <div id="root">
        <home></home>
    </div>
</body>
//index.js
import Vue from "vue";
import home from "./home.vue";
const vm = new Vue({
    el:"#root",
    render:h => h(home)
});
//home.vue
<template>
    <div>
        <async-welcome v-if="isShow"/>
        <button v-on:click="handleClick">login</button>
    </div>
</template>

<script>
export default {
    data:function(){
        return {
            isShow:false
        }
    },
    components:{
        "async-welcome":() => import("./welcome")
    },
    methods:{
        handleClick:function(){
            this.isShow = true;
        }
    }
}
</script>
//welcome.vue
<template>
    <div>welcome</div>
</template>

在这里插入图片描述

处理加载状态

在这里插入图片描述

服务端
{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node ./app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.11.6",
    "@babel/preset-env": "^7.11.5",
    "babel-loader": "^8.1.0",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^4.3.0",
    "express": "^4.17.1",
    "html-webpack-plugin": "^4.4.1",
    "http-proxy-middleware": "^1.0.5",
    "koa": "^2.13.0",
    "koa-server-http-proxy": "^0.1.0",
    "koa-webpack-dev-middleware": "^2.0.2",
    "style-loader": "^1.2.1",
    "vue-loader": "^15.9.3",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-middleware": "^3.7.2"
  },
  "dependencies": {
    "vue": "^2.6.12"
  }
}
//webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin} = require("clean-webpack-plugin");
const {VueLoaderPlugin} = require("vue-loader");

module.exports = {
    mode:"development",
    devtool:"cheap-source-map",
    entry:{
        "index":"./src/index.js"
    },
    output:{
        filename:"[name].bundle.js",
        path:path.join(__dirname,"dist"),
        publicPath:"/"
    },
    resolve:{
        modules:[path.join(__dirname,"node_modules")],
        extensions:[".vue",".js",".json"],
        alias:{
            "vue$":"vue/dist/vue.esm.js"
        }
    },
    module:{
        rules:[
            {
                test:/\.vue$/,
                include:/src/,
                use:["vue-loader"]
            },
            {
                test:/\.js$/,
                use:{
                    loader:"babel-loader",
                    options:{
                        presets:["@babel/preset-env"]
                    }
                }
            },
            {
                test:/\.css$/,
                use:["style-loader","css-loader"]
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:"./src/index.html"
        }),
        new CleanWebpackPlugin(),
        new VueLoaderPlugin()
    ]
}

服务端的搭建既可以用Express,也可以用Koa。
需要注意的是,这两种框架使用的中间件不同,需要适配,比如
Express+webpack-dev-middleware+http-proxy-middleware
Koa+koa-webpack-dev-middleware+koa-server-http-proxy

  • 基于Express的服务器端搭建
const webpack = require("webpack");
const config = require("./webpack.config.js");
const compiler = webpack(config);

const express = require("express");
const app = express();
const webpackDevMiddleware = require("webpack-dev-middleware");
app.use(webpackDevMiddleware(compiler,{
    publicPath:config.output.publicPath
}));

const {createProxyMiddleware} = require("http-proxy-middleware");
app.use("/data",createProxyMiddleware({
    target:"http://www.weather.com.cn",
    changeOrigin:true
}));

app.listen(3000,function(){
    console.log("listening on *:3000");
});
  • 基于Koa的服务端搭建
const webpack = require("webpack");
const config = require("./webpack.config.js");
const compiler = webpack(config);

const Koa = require("koa");
const app = new Koa();
const webpackDevMiddleware = require("koa-webpack-dev-middleware");
app.use(webpackDevMiddleware(compiler,{
    publicPath:config.output.publicPath
}));

const httpProxy = require("koa-server-http-proxy");
app.use(httpProxy("/data",{
    target:"http://www.weather.com.cn",
    changeOrigin:true
}))

app.listen(3000,function(){
    console.log("listening on *:3000");
});
客户端
<!-- index.html -->
<body>
    <div id="root">
        <my-component></my-component>
    </div>
</body>
//index.js
import Vue from "vue";
import loadingComponent from "./loading-component.vue";
import errorComponent from "./error-component.vue";

Vue.component("my-component",() => ({
  component: import('./weather-component.vue'),
  loading: loadingComponent,
  error: errorComponent,  
}))

const vm = new Vue({
    el:"#root"
});
// error-component.vue
<template>
    <div>天气信息加载失败!</div>
</template>
// loading-component.vue
<template>
 <div>正在加载天气信息...</div>
</template>
// weather-component.vue
<template>
    <div v-if="isShow">
        <div>所在城市:{{city}}</div>
        <div>今日天气:{{weather}}</div>
        <div>最低气温:{{temp1}}</div>
        <div>最高气温: {{temp2}}</div>
    </div>
</template>

<script>
export default {
    data:function(){
        return {
            isShow:false,
            city:"",
            weather:"",
            temp1:"",
            temp2:""
        }
    },
    mounted:function(){
        const self = this;
        fetch("data/cityinfo/101240101.html")
        .then(function(response){
            return response.json();
        }).then(function({weatherinfo}){
            const {city,weather,temp1,temp2} = weatherinfo;
            self.isShow = true;
            self.city = city;
            self.weather = weather;
            self.temp1 = temp1;
            self.temp2 = temp2;
        })
    }
}
</script>

在这里插入图片描述

  • error: errorComponent
Vue.component("my-component",() => ({
  component: import('./weather-component.vue'),
  loading: loadingComponent,
  error: errorComponent,  
  delay:200,
  timeout:1,
}))

timeout默认是Infinite,我们试试把timeout设置得很小,比如1
如果异步组件加载超时,则会显示出errorComponent
在这里插入图片描述

  • loading: loadingComponent
function getComponent(){
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(import("./weather-component.vue"));
        },1000);
    })
}
Vue.component("my-component",() => ({
  component:getComponent(),
  loading: loadingComponent,
  error: errorComponent
}))

在异步组件还没有加载完成的这段时间里,显示loadingComponent
在上述代码中,我们调用setTimeout延时1s加载异步组件,在延时的这样时间里,我们看到的是loadingComponent的内容。
在这里插入图片描述

参考文档

vue之异步组件
使用webpack-dev-middleware
npm之koa-webpack-dev-middleware
github之koa-webpack-dev-middleware
koa代理之koa-server-http-proxy

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值