vue内置组件component

component是vue的一个内置组件,作用是:配合is动态渲染组件。

<component :is='组件'></component>

 

不同组件之间进行动态的切换

//两个子组件
var son1 = {
    template: `
      <div>
        <h1>子组件-1</h1>
        <slot>子组件-1的默认内容</slot>
      </div>
            `
}
var son2 = {
     template: `
       <div>
         <h1>子组件-2</h1>
         <slot>子组件-2的默认内容</slot>
       </div>
            `
}
<!-- 父组件 -->
<div id="app">
  <button @click="change1">son1</button>
  <button @click="change2">son2</button>
  <component :is='state'></component>
</div>

<script>
 var vm = new Vue({
    el: "#app",
    data() {
        return {
            state: 'son1'
        }
    },
    methods: {
        change1() {
            this.state = 'son1'
        },
        change2() {
            this.state = 'son2'
        }
    },
    components: {
        son1,
        son2
    }
 })
</script>

上边代码,我们实现了两个子组件动态切换。

补充:

在vue-cli中,component经常用到的地方为tabs标签页中:

<template>
  <div class="home">
    <hr>
      <div style="display: flex;justify-content: center;">
        <button 
          v-for="(comp, i) in componentsList" 
          :key="i" 
          :style="[activingIndex === i ? {background: 'red', color: '#fff'} : {background: '#fff', color: '#000'}]"
          @click="test(i)"
        >{{i+1}}</button>
      </div>
      <component :is="proxy"></component>
  </div>
</template>
<script>
<!--以下是三个组件,动态来切换不同的组件-->
import com from './com';
import comOne from './com_1';
import comTwo from './com_2';
export default {
  name: 'Home',
  components: {
    com,
    comOne,comTwo
  },
  data() {
    return {
      componentsList: ['com', 'comOne', 'comTwo'],
      proxy: 'com',
      activingIndex: 0
    }
  },
  methods: {
    test(i) {
      this.activingIndex = i
      switch(i) {
        case 0:
          this.proxy = 'com'
          break;
        case 1:
          this.proxy = 'comOne'
          break;
        case 2:
          this.proxy = 'comTwo'
          break;    
      }
    }
  }
}
</script>

 

下边来看一个问题,两个组件进行切换时,一个组件显示,另一个是组件隐藏还是销毁呢?

//两个子组件
var son1 = {
    template: `
      <div>
        <h1>子组件-1</h1>
        <slot>子组件-1的默认内容</slot>
      </div>
            `,
    beforeDestroy(){
       alert('销毁子组件son1')
    }
}
var son2 = {
     template: `
       <div>
         <h1>子组件-2</h1>
         <slot>子组件-2的默认内容</slot>
       </div>
            `,
    beforeDestroy(){
       alert('销毁子组件son2')
    }
}

上边代码,当切换son2时,显示son1组件被销毁,所以,当两个组件进行动态切换时,组件的状态是:不断的创建与销毁的过程

如果你想把组件的缓存下来,可以在动态组件上使用vue另一个内置组件keep-alive

<keep-alive>
    <component :is='state'></component>
</keep-alive>

这样,当切换组件时,组件会被缓存下来,不会执行created 、mounted、beforeDestroy钩子函数。

 

父子组件执行顺序的问题:

我们在父组件和子组件son中分别定义个生命周期钩子mounted,页面加载到完成,父组件先渲染完成还是子组件先渲染完成呢?

var son = {
    template: `
    <div>
      <h1>子组件-1</h1>
      <slot>子组件-1的默认内容</slot>
    </div>
    `,
    mounted(){
        console.log('son')
    }
}
var vm = new Vue({
    el: "#app",
    mounted(){
        console.log('父组件')
    },
    components: {
        son
    }
})

输出结果:

上边代码,结果是父组件挂载完成前提:需等到子组件挂载完成后。

 

子组件异步渲染

上边代码,我们看到,子组件先挂载完成,父组件才能挂载完成,下边代码我们在父组件中获取子组件的dom元素,看下问题所在:

<div id="app">
  <son ref='son'></son>
</div>

<script>
//子组件
 var son = {
    template: `
       <div>
        <h1>{{name}}</h1>
       </div>
    `,
    data(){
      return{
          name:'lxc'
      }
    },
    mounted(){
      this.name = '呆呆君'
    },
 }

//父组件(根实例)
 var vm = new Vue({
    el: "#app",
    mounted(){
      console.log(this.$refs.son.$el.innerText)
    },
    components: {
      son
    }
 })
</script>

上边代码,在子组件的mounted中我们修改了原来data对象中的数据,页面渲染完全没问题,但是在父组件mouted中输出子组件dom元素的内容时,不是新数据 " 呆呆君 ",而是原来的数据 "lxc" !

结论,子组件生命周期钩子mounted和父组件的mounted都是同步执行的,但是子组件渲染dom元素却是异步渲染的,所以在父组件的mounted中获取dom元素是原来的子组件数据!!!

解决上边bug,通常会在vm.$nextTick中去获取dom元素:

<div id="app">
  <son ref='son'></son>
</div>

<script>
//子组件
 
··· ··· ···

//父组件(根实例)
 var vm = new Vue({
    el: "#app",
    mounted(){
      this.$nextTick(function(){
            console.log(this.$refs.son.$el.innerText)
        })
    },
    components: {
      son
    }
 })
</script>

输出结果:

关于vm.$nextTick(callback)我在之前的文章中有详细讲到:

https://blog.csdn.net/qq_42778001/article/details/96117236

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值