Vue入门基础—— 动态组件&插槽&自定义指令

Posted 小hu同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue入门基础—— 动态组件&插槽&自定义指令相关的知识,希望对你有一定的参考价值。

本篇文章主要讲述的是 动态组件&插槽&自定义指令

一、动态组件

1、什么是动态组件

动态组件指的是动态切换组件的显示与隐藏

2、如何实现动态组件渲染

Vue提供了一个内置的组件,专门用来实现动态组件的渲染。示例代码如下

    data()
    //1、当前要渲染的组件名称
    
    retrn comName:'Left'
    
    
   <!--2. 通过is属性,动态指定要渲染的组件 -->
   <component :is='comName'></component>

<!-- 3. 点击按钮,动态切换组件的名称-->
  <button @click="Toleft">切换为Left</button>
  <button @click="Toright">切换为Right</button>

在App组件的中 导入两个组件(这个导入步骤省略)

//可使用component  is 来渲染组件
  <component :is="Left"></component>

总结:《component》 是一个占位符 ,要渲染谁就在is 后面添加对应的组件

2.1 动态组件-动态切换

我们刚刚这个component里面的is 后面是写死的,这个时候我们要让后面的值改为动态的
代码示例如下:


//动态绑定一个comname值
 <!-- 1、component标签是vue内置的 作用  组件的占位符 -->
 <!-- 2、is 属性的值 表示要渲染的组件的名字 -->
 <component :is="comname"></component>
 
 export default 
data() 
    return 
      // 表示默认展示的名字
      comname:'Left'
    
  ,
 

需求:当我们点击按钮上面的切换时,点击对应按钮就展示对应的组件

<button @click="Toleft">切换为Left</button>
<button @click="Toright">切换为Right</button>
 <component :is="comname"></component>
 
 export default 
  data() 
    return 
      // 表示默认展示的名字
      comname:'Left'
    
  ,

  methods: 
    Toleft()
       this.comname ='Left'
      
    ,
    Toright()
      this.comname  ='Right'
    
    
  ,
   
  //  注册组件
   components:
    //  如果在声明组件名称的时候 没有为组件声明name 名称 默认就是注册的名称
      Left,
      Right,
    

2.2 动态组件-keep-alive的使用

可以看下面这个案例,我在left 组件里面定义了一个自增加1,当我们加1后,切换到另外一个组件在切换回来,会发现我们的自增的数据没了这是为什么呢?
原因就是:当我们切换组件的时候,组件被销毁了,当我们切换回来的时候 ,组件又创建了


如果还不清楚 可以看下面这个。注意看右边的组件

我们在Left 组件中

创建一个 creatd生命周期函数,还记得created是什么意思么? 是组件完成数据的请求的阶段

 created() 
    console.log('left组件创建了')
  ,

然后再创建一个destroyed生命周期函数?组件销毁时触发阶段

destroyed()
    console.log('left组件销毁了');
  ,

看下图

当页面一进来的时候,会触发一次 created,切换到组件right的时候 会触发destroyed,当我们再次切换会left组件,可以看到我们组件 再次创建了

这个时候,我们就需要用到keep-alive了,官网的说法是,将失活的组件 [包裹起来](动态组件 & 异步组件 — Vue.js (vuejs.org))

用法:给我们在App.vue组件里面定义的component占位符外面包裹起来就可以了

  <!--keep-alive可以吧内部的组件  进行缓存 而不是销毁组件 -->
  
<keep-alive>
        <component :is='comname'></component>
 </keep-alive>


可以看到,我们的数据并没有销毁,而是保存下来了,注意看右边调试器,当我们切换组件的时候,left组件并没有被销毁,而是被缓存了

2.2.1 keep-alive对应的生命周期函数
  1. 当组件被缓存时,会自动触发组件的deactivated生命周期函数
 deactivated() 
    console.log('组件被缓存了');
  ,
  1. 当组件被激活的时候,会自动触发组件的activated生命
 activated() 
      console.log('组件被激活了');
  ,
2.2.2 keep-alive的include属性
 include 指定哪些组件需要缓存的 
  exinclude 指定哪些组件不需要缓存的 
     最好不要同时使用这两个属性
      <keep-alive include="MyLeft">
      <component :is='comname'></component>
      </keep-alive>

2.3 扩展-组件name名称

在声明组件的时候,没有为组件单独设置name名称时,这组件的名称就为注册时的名称,要是声明了name组件名称的名称,则组件的名称就为name名称

export default 
    name:'MyLeft'

二、插槽

1、什么是插槽

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

代码示例:

在app.vue中导入left组件

//在当前组件定义内容后,在页面上也是不会展示的,
因为需要到封装的组件中,预留一个插槽,来进行自定义内容的填充
<left>
<p> 这是默认插槽</p>
</left>

<!--默认情况下 在使用组件的时候
提供的内容会默认的被填充到名字为default的插槽中 -->

left.vue 组件

    <!-- 声明一个插槽区 -->
 <slot></slot>
 
 <!-- Vue 官方规定 每一个slot 都要有一个name 名称 -->
  <!-- 如果省略了 slot 的name 属性 则会有一个默认名称 -->
    <!--<slot name="default">默认插槽名称</slot>-->

2、v-slot 指令

v-slot 指名道姓的将某部分内容放到哪个插槽里面去

v-slot指令不能放在元素上,只能放在template组件

<left>
<p v-slot:default> 这是默认插槽</p>//错误写法,会报错
</left>
<left>
// 将p 元素放到 插槽name为default的里面
//<tempalte>标签 不会被渲染到页面结构里面
  <tempalte v-slot:default>
        <p> 这是默认插槽</p>
    </template>
</left>

总结

  1. 如果要吧内容填充到指定名称的插槽中 需要使用 v-slot:这个指令
  2. v-slot 这个指令后面要跟上插槽的名称
  3. v-slot:指令不能直接用在元素身上 必须用在template标签上
  4. template 这个标签 它是一个虚拟的标签 只起到包裹性质的作用 但是不会被渲染为任何实质性的html 元素
  5. v-slot 的简写是#
  6. 当在<slot></slot>插槽中填写了内容,又在组件中定义内容,会以自定义内容为准
    left.vue
//里面的内容为默认内容,当自定义内容为空时,会展示默认内容
<slot name="default">默认插槽</slot>

app.vue

<left>
//自定义内容,当自定义内容里面有数据时,会把默认内容给覆盖掉
<template #default>
           <p>这是我后来自定义内容</p>
        </template>
</left>

3、具名插槽

插槽拥有自己的名称,就是具名插槽
结合Vant 组件库看看

代码示例
right.vue组件

 <!-- 渲染文章的标题 -->
            <div class="header-box">
                <slot name="title" ></slot>
            </div>
            
            <!-- 渲染文章的内容 -->
            <div class="content-box">
            <!-- 在封装组件时 为预留的slot 提供属性对应的值 这种用法 叫做“作用域插槽” -->
        <!--ms 这里定义了一个值后,可以在组件调用时 使用-->    
            <slot name="content" ms="hello vue" :user="user"></slot>
            </div>


            <!-- 渲染文章的作者 -->
            <div class="footer-box">
                <slot name="footer"></slot>
            </div>
          
          
       //data里面定义1个 user对象 绑定到插槽上面,也作为数据传递过去   
 <script>
export default 
    data() 
        return 
            user:
                name:'张三',
                age:14
            
        
    ,
    name:'Art'

</script>
      

app.vue 根组件

<right>
      <template #title>
        <h3>锄禾</h3>
      </template>
      
      
        <!--  可以在这个插槽里面接收传递过来的数据,并且使用-->
        <!-- <template #content="ms">-->
        
        当有多个值需要接收时,可以写成
        <!--<template #content="ms,user">-->
      <template #content>
        <div>锄禾日当午,汗滴禾下土</div>
        <div>谁知盘中餐,粒粒皆辛苦</div>
         <div> ms </div>
        <div> user.name </div>
      </template>

      <template #footer>
        <div>白居易</div>
      </template>
    </right>

三、自定义指令

1、什么是自定义指令

vue官方提供了v-text、v-for、v-model、v-if等常用的指令。除此之外vue还允许开发者自定义指令

2、自定义指令的分类

vue中的自定义指令分为两类,分别是:

  • 私有自定义指令
  • 全局自定义指令

3、私有自定义指令

在每个vue 组件中,可以在directives节点下声明私有自定义指令。示例代码如下:

app.vue的业务逻辑

directives: 
    // 定义为color 的指令  指向一个配置对象
    color:
       // 当指令第一次被绑定到元素上的时候  会立即触发bind 函数
      // 形参中的el 表示当前指令所绑定的那个Dom 元素
          bind(el)
        el.style.color = 'red'
    ,
    

app.vue根页面结构

  <h4 v-color="'red'">测试</h4>

非写死

<h1 v-color="color">App 根组件</h1>
export default 
  data() 
    return 
      color: 'blue'
    
   ,
   
   directives: 
    // 定义为color 的指令  指向一个配置对象
    color:
       // 当指令第一次被绑定到元素上的时候  会立即触发bind 函数
      // 形参中的el 表示当前指令所绑定的那个Dom 元素
      //传递一个形参binding
          bind(el,binding)
          //私有binding.value 来获取到color的值
        el.style.color = binding.value
    ,
    
 
  • value 是真正的值
  • expression 外面有一层单引号(是一个表达式的意思)

3.1 update函数

 <button @click="color = 'red'">改变App的颜色</button>
 
 //当指令第一次被绑定到元素上的时候  会立即触发bind 函数。
 但我们点击时,数据修改了,页面的内容没有修改
 <script>
 export default 
  data() 
    return 
      color: 'blue'
    
   ,
   directives: 
    // 定义为color 的指令  指向一个配置对象
    color:
       // 当指令第一次被绑定到元素上的时候  会立即触发bind 函数
      // 形参中的el 表示当前指令所绑定的那个Dom 元素
      //传递一个形参binding
          bind(el,binding)
          //私有binding.value 来获取到color的值
        el.style.color = binding.value
    ,
    
   
   </script>

原因:bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发。 update 函数会在每次 DOM 更新时被调用。示例代码如下:

3.2 代码优化函数简写

如果 insert 和update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:
就是bind函数和update函数里面的业务逻辑是一样的就可以简写成以下的方式

 // 私有自定义指令的节点
  directives: 
    color(el, binding) 
      el.style.color = binding.value
            
    

4、全局自定义指令

全局共享的自定义指令需要通过“Vue.directive()”进行声明,示例代码如下:
main.js

//参数1:字符串,表示全局自定义指令的名字
//参数2:对象用来接收指令的参数值
Vue.directive('color',function(el,obj)
  el.style.color = obj.value
)

以上是关于Vue入门基础—— 动态组件&插槽&自定义指令的主要内容,如果未能解决你的问题,请参考以下文章

Vue动态组件 & 插槽 & 自定义指令

03vue2.x组件快速入门

15《Vue 入门教程》Vue 动态组件 &amp;amp; keep-alive

语法糖&具名插槽&作用域插槽&混入

Vue——自定义组件 & 自定义事件$emit & 插槽slot

Vue 开发之插槽(slot)的理解和使用