自学内容网 自学内容网

【Vue】自定义指令、插槽

目录

自定义指令

是什么

作用

使用方法

定义

使用 

自定义指令配合绑定数据

语法

自定义指令的简写

语法

使用时机

插槽

什么是插槽

默认(匿名)插槽

​编辑插槽的默认值

具名插槽

使用方法

简写

使用示例 

作用域插槽


自定义指令

是什么

  • 内置指令:是vue3自带的,比如:v-model、v-for、v-if....我们可以直接使用。
  • 自定义指令:相对内置指令而言,我们自己编写的指令,当内置指令无法满足需求的时候,就可以自己编写的指令。

作用

封装一段公共的DOM操作的代码。

与ref属性操作DOM的区别:

  1. ref是作用在单个标签上的,代码无法复用
  2. 自定义指令可以把一段公共的DOM操作代码封装起来,进行复用

使用方法

定义

main.js -> app.directive('指令名',{

        mounted(el){

                //el就是指令所在的DOM元素

        }

})

示例:在main.js文件中

const app=createApp(App)

app.directive('jujiao',{
    mounted(el){
        el.focus()
    }
})

app.mount('#app')

使用 

<XXX v-指令名>

<template>
    <input type="text" v-jujiao/>
</template>

自定义指令配合绑定数据

语法

1、在绑定指令时,可以通过“等号”的形式为指令绑定具体的参数值

<template>
    <div v-color="colorStr">
        Hello World
    </div>
</template>

<script setup>
    import { ref } from 'vue'

    const colorStr = ref('blue')
</script>

2、通过binding.value可以拿到指令值,指令值修改会触发updated钩子

app.directive('color',{
     //mouted钩子只负责初次渲染,后续指令所在表达式的值变了,该函数不会执行,因此需要引入updated钩子
    mounted(el,binding){
        //el就是指令所在的DOM元素
        //binding:指令绑定的信息对象,通过binding.value获取表达式结果
        el.style.color=binding.value
    },
    updated(el,binding){
        el.style.color=binding.value
    }
})

自定义指令的简写

将上面提到指令的mounted()和updated()两个钩子进行合写,用一个函数来代替,并且这个函数会在mounted()和updated()时机都会执行。

语法

app.directive('color',(el,binding)=>{
    el.style.color=binding.value
})

使用时机

  1. 当自定义指令绑定数据,那么就可以简写(简写的本质=mounted()+updated())
  2. 当自定义指令没有绑定数据,那么就采用非简写的方式。

插槽

什么是插槽

        本质就是一个占位符,今后可以给这个占位符传入想要的组件结构,从而大大提高组件的灵活性和可复用性。

默认(匿名)插槽

作用

让组件内部的一些结构支持自定义

语法

  1. 在使用组件的时候,把组件写成双标签
  2. 在双标签之间传入想展示的结构,从而替换占位的slot组件

子组件

<script setup></script>
<template>
<div class="dialog">
<div class="dialog-header">
<h3>友情提示</h3>
<span class="close">✖️</span>
</div>
<div class="dialog-content">
<!-- 1. 在组件内标签不确定位置用 slot 组件 -->
<slot></slot>
</div>
<div class="dialog-footer">
<button>取消</button>
<button>确认</button>
</div>
</div>
</template>

<style scoped>
* {
margin: 0;
padding: 0;
}
.dialog {
width: 470px;
height: 230px;
padding: 0 25px;
background-color: #ffffff;
margin: 40px auto;
border-radius: 5px;
}
.dialog-header {
height: 70px;
line-height: 70px;
font-size: 20px;
border-bottom: 1px solid #ccc;
position: relative;
}
.dialog-header .close {
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
}
.dialog-content {
height: 80px;
font-size: 18px;
padding: 15px 0;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dialog-footer button {
width: 65px;
height: 35px;
background-color: #ffffff;
border: 1px solid #e1e3e9;
cursor: pointer;
outline: none;
margin-left: 10px;
border-radius: 3px;
}
.dialog-footer button:last-child {
background-color: #007acc;
color: #fff;
}
</style>

App.vue 

<template>
    <!-- 在使用组件的时候,给组件传入想展示的结构,从而替换掉组件内的slot组件 -->
    <MyDialog>
        <span>你确定要进行删除操作吗?</span>
    </MyDialog>
    <MyDialog>
        <span>你确定要退出本系统吗?</span>
    </MyDialog>
</template>

<script setup>
    import MyDialog from './components/MyDialog.vue';
</script>

插槽的默认值

如果未传入内容,则显示slot标签内的内容 

<slot> 我是默认内容 </slot>

默认值的生效规则:

  1. 如果没传,就显示默认值,防止页面空白
  2. 如果传入了,就会用传入的,替换掉占位的slot,从而展示实际传入的标签结构

具名插槽

一个组件内有多处结构,需要外部传入标签,进行定制,默认插槽只能定制一处内容。这是给插槽添加name属性,进行区分,添加name属性的插槽就是具名插槽。

使用方法

<slot name="插槽名"> 默认的内容</slot>

<template v-slot:插槽名> 要展示的内容</template> 

简写

<template #插槽名> 要展示的内容</template>

使用示例 

根组件

<template>
    <!-- 在使用组件的时候,给组件传入想展示的结构,从而替换掉组件内的slot组件 -->
    <MyDialog>
        <template v-slot:title>
            <span>删除确认</span>
        </template>
        <template v-slot:content>
            <span>你确定要进行删除操作吗?</span>
        </template>
    </MyDialog>
    
</template>

<script setup>
    import MyDialog from './components/MyDialog.vue';
</script>

子组件(插槽) 

<script setup></script>
<template>
<div class="dialog">
<div class="dialog-header">
<slot name="title"></slot>
<span class="close">✖️</span>
</div>
<div class="dialog-content">
<!-- 1. 在组件内标签不确定位置用 slot 组件 -->
<slot name="content"></slot>
</div>
<div class="dialog-footer">
<button>取消</button>
<button>确认</button>
</div>
</div>
</template>

<style scoped>
* {
margin: 0;
padding: 0;
}
.dialog {
width: 470px;
height: 230px;
padding: 0 25px;
background-color: #ffffff;
margin: 40px auto;
border-radius: 5px;
}
.dialog-header {
height: 70px;
line-height: 70px;
font-size: 20px;
border-bottom: 1px solid #ccc;
position: relative;
}
.dialog-header .close {
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
}
.dialog-content {
height: 80px;
font-size: 18px;
padding: 15px 0;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dialog-footer button {
width: 65px;
height: 35px;
background-color: #ffffff;
border: 1px solid #e1e3e9;
cursor: pointer;
outline: none;
margin-left: 10px;
border-radius: 3px;
}
.dialog-footer button:last-child {
background-color: #007acc;
color: #fff;
}
</style>

作用域插槽

带数据的插槽,用slot占位的同时,还可以给slot绑定数据,也就是说数据来源于插槽,但是怎么展示这些数据由自定义结构决定。

接收插槽数据

这里的obj就代表对应slot标签绑定的所有数据的对象

<template v-slot:content="obj">
    <span>obj.a={{ obj.a }}</span>
</template>

上面是使用一个对象进行接收,我们也可以对接收的数据进行解构,直接获取指定的数据,如下:

<template v-slot:content="{a}">
    <span> a={{ a }}</span>
</template>

slot绑定数据

<div class="dialog-content">
<slot name="content" a="123" b="456"></slot>
</div>


原文地址:https://blog.csdn.net/lzb_kkk/article/details/144154652

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!