这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
一.Button
disabled属性:
只要父子组件传值并且动态获取这个值并且赋给disabled属性,并且设置一个disabled样式即可。
const props = defineProps({
type: {
type: String,
default: null
},
plain: {
type: Boolean,
default: false
},
round: {
type: Boolean,
default: false
},
circle: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
}
})
disabled样式:
.one-button.is-disabled{
cursor: no-drop;
}
补充:
cusor:no-drop cursor:not-allowed
no-drop:不掉落 指示不能在当前光标位置删除拖动的项。通常表现为一只手或一个有一条线穿过的小圆的指针。
not-allowed:不允许 指示将不执行请求的操作。常被描绘成一个有一条线穿过的圆。 公司自己封装的公共样式中
二.dialog(对话框)
前置知识:
- vue过渡动画
- sync修饰符
- 具名插槽与v-slot指令
参数支持:
| 参数名 | 参数描述 |
|---|---|
| title | 对话框标题 |
| width | 对话框标题 |
| top | 与顶部的距离 |
| visible | 是否显示dialog(支持sync修饰符) |
| 参数类型 | 默认值 |
|---|---|
| string | 提示 |
| string | 50% |
| string | 15vh |
| boolean | false |
事件支持:
| 事件名 | 事件描述 |
|---|---|
| opened | 模态框显示事件 |
| closed | 模态框关闭事件 |
插槽说明:
| 插槽名称 | 插槽描述 |
|---|---|
| default | dialog的内容 |
| title | dialog的标题 |
| footer | dialog的底部操作区 |
dialog组件的基本框架和样式
首先搭建起来dialog组件的框架,暂时不加入插槽,只构建出基本的框架和样式。
框架分为三个部分,头部(header)、内容(body)、底部(footer),基本框架如下:
<template>
<div class="one-dialog_wrapper">
<div class="one-dialog">
<div class="one-dialog_header">
<slot name="title">
<span class="one-dialog_title">{{ title }}</span>
</slot>
<button class="one-dialog_headerbtn">
<i class="one-icon-close"></i>
</button>
</div>
<div class="one-dialog_body">
<span>这是一段信息</span>
</div>
<div class="one-dialog_footer">
<my-button>取消</my-button>
<my-button type="primary">确定</my-button>
</div>
</div>
</div>
</template>
<script setup>
import myButton from './myButton.vue'
import { defineProps } from "vue"
defineProps({
title: {
type: String,
default: '提示'
}
})
</script>
<style lang="less" scoped>
.one-dialog_wrapper {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
margin: 0;
z-index: 2001;
background-color: rgba(0, 0, 0, 0.5);
.one-dialog {
position: relative;
margin: 15vh auto 50px;
background: #fff;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
width: 30%;
&_header {
padding: 20px 20px 10px;
.one-dialog_title {
line-height: 24px;
font-size: 18px;
color: #303133;
}
.one-dialog_headerbtn {
position: absolute;
top: 20px;
right: 20px;
padding: 0;
background: transparent;
border: none;
outline: none;
cursor: pointer;
font-size: 16px;
.one-icon-close {
color: 909399
}
}
}
&_body {
padding: 30px 20px;
color: #606266;
font-size: 14px;
word-break: break-all;
}
&_footer {
padding: 10px 20px 20px;
text-align: right;
box-sizing: border-box;
::v-deep .my-button:first-child {
margin-right: 20px;
}
}
}
}
</style>
补充:在标题放一个具名插槽,如果没有传入则显示默认title.
<slot name="title">
<span class="one-dialog_title">{{ title }}</span>
</slot>
插槽的使用
<div class="one-dialog_footer" v-if="$slots.footer">
<slot name="footer"></slot>
</div>
使用:
<my-dialog width="20%" top="200px">
<template v-slot:footer>
<my-button>取消</my-button>
<my-button type="primary">确定</my-button>
</template>
</my-dialog>
对话框显示与隐藏
利用组件通信即可
//myDialog
const emit = defineEmits(['handleClose'])
const handleClose = () => {
emit("close", false)
}
//App
<my-dialog width="20%" top="200px" :visible="visible" @close="close">
<template v-slot:footer>
<my-button @click="visible = false">取消</my-button>
<my-button type="primary" @click="visible = false">确定</my-button>
</template>
</my-dialog>
补充: .sync修饰符 (使用饿了么Ui时我们不用定义@close进行取消) 官方解释:我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。事实上就是组件不能直接修改 props 外部的数据,强行修改外部数据会引起报错,所以需要在子组件中改变 props 的属性值并更新到父组件中,就会使用到 .sync。本质上 .sync 就是一个语法糖。
v-model 与 .sync 的区别
都是用来实现父子组件之间的数据双向通信,但是 v-model 常用于表单元素,也就是输入类元素,input,单选多选框,select框,多行输入等,.sync 常用于子组件数据改变通过 props 传递更新到父组件中,所以,.sync 不限制标签。