• 有问题请联系QQ:2374146085
  • 有问题请联系QQ:2374146085

Vue2 动态组件、插槽以及自定义指令

1年前 (2021-11-06) 1390次浏览 已收录 0个评论 扫描二维码

动态组件

动态组件指的是动态切换组件的显示与隐藏。vue提供了一个内置的<component>组件,专门用来实现动态组件的渲染。

is

is属性的值,表示要渲染组件的名字,可以通过修改data里的值来进行动态渲染。

在App组件中使用的例子:

<component :is="flag"></component>
...
data(){
      return{
//动态渲染left组件
        flag:'left'
      }
    },
隐藏(切换)的组件会被销毁,而显示的组件会被重新创建一个新的组件。

插槽

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

基本用法

使用组件者自定义内容并用v-slot指定填充到的插槽名称

在App中的例子

<template>
   <div>
     <left>
        <!-- template和上面的标签不一样,它不会被渲染成任何结构,只起包裹作用。v-slot只能用在template标签上,它可以简写成#,即#leftChaCao-->
       <template v-slot:leftChaCao>
         <p>目前我显示不了,因为我是使用组件者自定义的内容</p>
       </template>
     </left>
   <div>
<template>

在left组件某个地方中使用slot声明一个插槽区域,就会自动填充上面自定义的内容了。

<!-- 声明一个插槽区域 -->
<slot name="leftChaCao">
标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义,内容就会被显示)
</slot>

接着在App自定义的内容就会被填充到left中声明的这个插槽区域,就可以显示了。

具名插槽

<!-- 声明一个插槽区域 --> 
<slot name="leftChaCao">
标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义内容就会被显示)
</slot>

作用域插槽

在封装组件时,为预留的<slot>提供属性对应的数据,也可以理解成子传父,即把数据传给了外面使用它的组件。也就是通过插槽可以接收到插槽身上给我们传过来的数据。

<!-- 声明一个同时兼有具名和作用域的插槽区域 -->
<slot name="leftChaCao" mes="zzl">
标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义内容就会被显示)
</slot>

使用组件者自定义内容时可以接收到这个对象

<template>
   <div>
     <left>
        <!-- 指定插槽的名称,它和上面的标签不一样,它不会被渲染成任何结构,只起包裹作用,它只能用在template标签上,它可以简写成#,即#leftChaCao-->
       <template #leftChaCao="obj">
         <p>目前我显示不了,因为我是使用组件者自定义的内容</p>
         <p>{{obj.mes}}</p>
         <!-- 上面会显示zzl -->
       </template>
     </left>
   <div>
<template>

作用域插槽的解构赋值

在子组件中

<!-- 声明一个同时兼有具名和作用域的插槽区域 -->
<slot name="leftChaCao" mes="zzl" :user="info">
标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义内容就会被显示)
</slot>
...
<script>
  export default{
    data(){
      return{
         info:{
            name:'wxl',
            age:18
              }
            }
          }
     }
</script>

在父组件中

<template>
   <div>
     <left>
       <template #leftChaCao="{mes,info}">
         <p>目前我显示不了,因为我是使用组件者自定义的内容</p>
         <p>{{mes}}</p>
         <p>{{info.name}}</p>
       </template>
     </left>
   <div>
<template>

自定义指令

当需要对dom进行底层操作时,可以使用自定义指令。

私有自定义指令

在每一个vue组件中,可以在directives节点下声明私有自定义指令

<template>
<div class="rootbox">
  <h1 v-color>App根组件</h1>
</div>
</template>
...
directives:{
    //定义名为color的指令,指向一个配置对象,使用的时候是v-color,同下。
    color:{
      //vue3方法,当指令第一次被挂载到元素上的时候,会立即触发mounted函数
      mounted(el){
        console.log("v-color被这个页面挂载了")
        el.style.color='red'
      },
      //vue2方法,当指令第一次被绑定到元素上的时候,会立即触发bind函数
      //形参中的el表示当前指令所绑定的那个dom对象
      bind(el){
        console.log('触发了v-color的bind函数')
        el.style.color='red'
      }
    }
  },
    data(){
    }
vue2与vue3自定义指令还是有很大的差别的,具体可以参考vue官网,里面包含自定义指令的所有生命周期函数

binding.value获取指令绑定的值

<template>
<div class="rootbox">
  <h1 v-color="blue">App根组件</h1>
  <h1 v-color="'red'">App根组件2</h1>
</div>
</template>
...
directives:{
    //定义名为color的指令,指向一个配置对象
    color:{
      //当指令 【第一次】 被绑定到元素上的时候,会立即触发bind函数
      //形参中的el表示当前指令所绑定的那个dom对象
      bind(el,binding){
        console.log('触发了v-color的bind函数',binging)
        el.style.color=binging.value
      }
    }
  },
    data(){
       return{
             blue : 'blue'
         }
    }

update函数

bind函数的缺点是只调用1次:当指令第一次绑定到元素时会立即触发bind函数,但当dom更新时,bind函数不会再被触发了。

此时用update函数就可以在每次dom更新时都触发。

<template>
<div class="rootbox">
<button @click="color='green'">变App根组件1的颜色</button>
  <h1 v-color="color">App根组件1</h1>
  <h1 v-color="'red'">App根组件2</h1>
</div>
</template>
...
directives:{
    //定义名为color的指令,指向一个配置对象
    color:{
      //当指令 【第一次】 被绑定到元素上的时候,会立即触发bind函数
      //形参中的el表示当前指令所绑定的那个dom对象
      bind(el,binding){
        console.log('触发了v-color的bind函数',binging)
        el.style.color=binging.value
      },

  //当dom更新时,会触发update函数,此时就又可以实现上面的需求了
      update(el,binding){
         console.log('触发了v-color的update函数',binging)
         el.style.color=binding.value
                      }
    }
  },
    data(){
       return{
             color : 'blue'
         }
    }

自定义指令简写形式

bindupdate函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式,所以上面代码可以简写为下面部分:

<template>
<div class="rootbox">
<button @click="color='green'">变App根组件1的颜色</button>
  <h1 v-color="color">App根组件1</h1>
  <h1 v-color="'red'">App根组件2</h1>
</div>
</template>
...
directives:{
   color(el,binding){
       el.style.color=binding.value
}
  },
    data(){
       return{
          color : 'blue'
         }
    }

全局自定义指令

全局共享的自定义指令需要在main.js里通过Vue.directive()进行声明。

参数1:字符串,表示全局自定义指令的名字
参数2:对象,用来接收指令的参数值

//参数2简写形式
Vue.directive('color',function(el,binding){
     el.style.color=binding.value
})

//vue3写法
//const app = createApp(App)
//app.directive()

//不简写形式
Vue.directive('color',{
  bing(el,binding){
    el.style.color=binding.value
  },
  update(el,binding){
    el.style.color=binding.value
  }
})

渣渣龙, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Vue2 动态组件、插槽以及自定义指令
喜欢 (7)

您必须 登录 才能发表评论!