Vue动态组件和keep-alive保持组件状态

1.动态组件

动态组件:顾名思义,动态组件就是可以动态的切换组件的显示
需求:根据不同的状态显示不同的状态

1.1 使用 v-ifv-show 切换组件

示例代码如下:

    <style>
         *{
            margin: 0;
            padding: 0;
        }
        li{
            list-style: none;
        }
        #app{
            width: 100vw;
            height:100vh;
        }
        .option ul{
            display: flex;
            position: fixed;
            left: 0;
            right:0;
            bottom:0;
            height:50px;
            border-top:2px solid #FFCA28;
        }

      
        .option ul li{
            flex: 1;
            text-align:center;
            line-height: 50px;
            font-size:22px;
            color:#fff;
            background: #FFCA28;
        }

        .content{
            position: fixed;
            top:0;
            left:0;
            right:0;
            bottom: 52px;
            background:#C5E1A5;
            padding:30px;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="content">
            <home v-if = "current == 'Home'"></home>
            <my-com  v-if = "current == 'MyCom'"></my-com> 
            <about v-if = "current == 'About'"></about>
        </div>
        <div class="option">
            <ul>
                <li @click="handleClick('Home')">Home</li>
                <li @click="handleClick('MyCom')">Content</li>
                <li @click="handleClick('About')">About</li>
            </ul>
        </div>
    </div>
    <script>
        let Home= ({
            template:`
           		<h2>我是home组件</h2>
           		<input type = "text">
            `,
        })

        let MyCom = {
            template:`
                <h2>Article组件</h2>
            `,
       }

        let About= ({
            template:`
                <h2>我是About组件</h2>
            `,
        })
        let vm = new Vue({
            el:"#app",
            data:{
                current:"Home"
            },
            methods:{
                handleClick(value){
                    this.current = value
                }
            },
            components: {
                Home,About,MyCom
            }
        })
    </script>
</body>

页面的显示效果如下:
在这里插入图片描述
虽然这样可以实现我们想要的效果,但是是非常不友好的做饭,假如我们有很多的组件需要切换,那么就要写很多的v-if 来实现切换.

所以Vue 帮我们提供了动态组件来解决这个问题.

1.2 动态组件的基本用法

在不同的组件之间的切换,动态组件是非常好用且高效的办法.

通过使用保留的 <component>元素,并对 is 属性进行绑定,我们就可以在同一挂载点切换多个组件,使用动态组件重新写上面的案例

将上面案例中的如下代码:

            <home v-if = "current == 'Home'"></home>
            <my-com  v-if = "current == 'MyCom'"></my-com> 
            <about v-if = "current == 'About'"></about> 

替换为这句代码就可以实现相同的效果:

            <component :is="current"></component>

此时的 is 属性的值是通过 v-bind 指令动态绑定到 data 属性中的数据,此时编译后的is的值是哪一个组件的名字就会显示哪一个组件.

2.keep-alive在动态组件上的使用

当我们在这些组件之间切换的是,有时候就会希望保持某些组件的状态,以此来避免重复渲染带来的问题.

比如说我们当前在登录页面,输入了登录的信息,但是不小心点到了注册页面,当我们返回到登录页面的额时候就会希望保留我们已经输入过的登录信息,就需要用到keep-alive.

keep-alive一般用于组件的切换,否则组件在切换时,会频繁的创建和删除组件,不太好,这样也没法在组件切换是保存之前状态.

2.1 不使用keep-alive

如果我们不使用keep-alive,就会在每次切换组件的时候,先删除旧的组件,然后渲染新的组件.

每个组件也都有自己的生命周期,我们把生命周期 函数添加上看看是不是每次切换组件都是在重新创建和删除组件.看看会先渲染新的组件还是先删除旧的组件???

示例代码如下:

 <div id="app">
        <div class="content">
         	 <component :is="current"></component>
		</div>
        <div class="option">
            <ul>
                <li @click="handleClick('Home')">Home</li>
                <li @click="handleClick('MyCom')">Content</li>
                <li @click="handleClick('About')">About</li>
            </ul>
        </div>
    </div>
    <script>
        let Home= ({
            template:`
            <div>
				 <h2>我是home组件</h2> 
				 <input type = "text" /> 
			</div>
           
            `,
            beforeCreate () {
               console.log("Home beforeCreate") 
            },
            created () {
               console.log("Home Create") 
            },
            beforeMount () {
                console.log("Home beforeMount");
            },
            mounted () {
                console.log("Home mounted");
            },
            beforeDestroy () {
                console.log("Home beforeDestroy");
            },
            destroyed () {
                console.log("Home destroyed");
            },
            activated(){
                // 当前组件处于活跃状态 ,
                console.log('activate')
            },
            deactivated(){
                // 当前组件不处于活跃状态, 冻结
                console.log("deactivate")
            }
        })

        let MyCom = {
            template:`
                <h2>Article组件</h2>
            `,
            beforeCreate () {
               console.log("MyCom beforeCreate") 
            },
            created () {
               console.log("MyCom Create") 
            },
            beforeMount () {
                console.log("MyCom beforeMount");
            },
            mounted () {
                console.log("MyCom mounted");
            },
            beforeDestroy () {
                console.log("MyCom beforeDestroy");
            },
            destroyed () {
                console.log("MyCom destroyed");
            }
        }

        let About= ({
            template:`
                <h2>我是About组件</h2>
            `,
        })
        let vm = new Vue({
            el:"#app",
            data:{
                current:"Home"
            },
            methods:{
                handleClick(value){
                    this.current = value
                }
            },
            components: {
                Home,About,MyCom
            }
        })
    </script>

我将页面从home页切换到content页面,观察一下打印的信息:
在这里插入图片描述
通过这些生命周期的钩子函数的打印,我们可以发现:
在切换组件的时候.会在虚拟DOM 已经准备添加时删除旧的组件,然后再渲染新的DOM元素.

因为每次组件切换都是新创建的组件,都是全新的,那么在组件切换前的组件状态将没发保存.

2.2使用keep-alive

但是在这个案例中,我们更希望那些标签的Home组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个<keep-alive> 元素将其动态组件包裹起来。

将上面示例代码中的如下内容:

<component :is="current"></component>

替换为

            <keep-alive exclude="MyCom,About">
                <component :is="current"></component>
            </keep-alive>

注:exclude 属性中的内容的意思是里面的组件不要被keep-alive保持组件的状态.

仔细观察上图中vue 显示内容的变换,当我们从 home 切换到 contentAbout 时,home 组件的显示颜色会变浅而不是消失.而 ContentAbout 都会消失.且我们在 home 页面 input 中输入的内容也不会消失. 这就是 keep-alive 的作用,能够保存当前组件的状态.

组件不会被销毁,而是一直会缓存这.

2.3 activated和deactivated

简单介绍:

  1. activated:被 keep-alive 缓存的组件激活时调用。该钩子在服务器端渲染期间不被调用。
  2. deactivated:被 keep-alive 缓存的组件停用时调用。该钩子在服务器端渲染期间不被调用。

通过案例来看:

let Home= ({
            template:`
            <div>
                    <h2>Home组件</h2>
                    <input type="text">
            </div> `,
             activated(){
                // 当前组件处于活跃状态 ,
                console.log('activate')
            },
            deactivated(){
                // 当前组件不处于活跃状态, 冻结
                console.log("deactivate")
            }
        })

        let MyCom = {
            template:`
                <h2>Article组件</h2>
            `,
        }

当我们在 home 页面的时候回打印 activated,如果我们从 home 页面切换到 content 页面时会打印 deactivated.
即当我们在 home 页面时 home 组件处于活跃状态,当我们切换到其他页面的时候, home 组件处于不活跃状态,即冻结状态.

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值