Alert组件
提前准备好字体文件
@font-face {font-family: "iconfont";
src: url('//at.alicdn.com/t/font_1699077_nnhvr47tsmd.eot?t=1584947660650'); /* IE9 */
src: url('//at.alicdn.com/t/font_1699077_nnhvr47tsmd.eot?t=1584947660650#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAT8AAsAAAAACmwAAAStAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDdAqHBIYDATYCJAMgCxIABCAFhG0HehsPCVGUSU5C9gW2DXtSIhtMEA7jhgEAhwCir0AVZAMTLAAACJ6vtfL97p7hA0R1tSrEpLKnAggy7JJVAdQE6K5q/ndNf4doKc8XyQ1QoT/4SdODXGDAqsJvQuPzrOYmgYVbrTCn4J/n0Lh8glUDGY16XyegLSnKId1C28Gx1M8Ey7O3d8nsRfFoPKDRMKKxQqQARxPlqagzUkdgFwiu4cUQwKeYOLFu86sb0INBthJA5nFmQU/GgmlgCq7erjjQINuwcNV6FWBr8PPylaz0gMLSyI6fGDQjWoPo9MH7FNPLomWM8xBIp3MBhzVBA42AYXpppWcDOso0ovFvpYYJQKr+Rg0fvA9ZH1Y+DP4w92PFp2IUFUahkUFD+BcPHCwUGoONgNgI0YTETss68MFzJIk2CyYsaPvChIJ2MExoaOeCDwMfK/iw4VNM9mI1rqdNJVHEugKhtCOl0ShFSsqERAqFdyQOU8PeDp5K6bl3b9j9+8MfPhz54MG4o5tDW7GNwfX8s3WwKUIeTM0W1g5X2fJAS1VPg6hZCOUI/MXoEaNgfZCbmzM8uBHj5+eOnM3x8vLHhjYB54wdrxxBsH5s9rT6elk5eRm5OZn5udl5Pbkj48urvLzHYeHK7NoFRnn5zyN2c3KG0TPJzx/jP29VPz9kVbeazRs9MLa2Yrzo/fp2ZM7eIyPjHM753Ldh9zePfBu1qeh76+iPKRvvzyw/vPMTtwoP3+68Ac3IzTSX6k4XMG1t5oIKPZE7lETOOjZrLVcBbLfI+tUKlOqGhPn1yyQghMhVJB3rB8U6KuPIZ5aYhrFaNXGdZyti8k+uqmdX8jr5uZksTPwfOPGXm2BP1ur0qqrL08hOLTnZVGzaNjx5EpI9vfAWyqj7GlTT3uM98kPGlgRL10RDH355SnCRvyagyUxi9EGM9D6zn/Uyqg8mKd1UVqQHavyNQf8VWGlhbmeF09y7wFMXyrf3mW3ou9m3ePRHumjx+qFrk7fxr8+ntxxwdEZbAyKa+JnnV6q+x9DntoJ3UMdwovydYslD9e5E8e9vcvLX915SPhFplAl7ERTJClrCKQBET1qX7wQQvepTWlYW7Aq6QV1EERhR3QCMD3X4H3s1PiV74nD9vxsYAJ4slJF4LhsZnnVR0Fn6/3QZiCyHkbscVtdcx3NEXWXDs7j0ZraUAnwNQMRAOn9TGrK+VpUcdVkJKByKQONSiTTYRrAIaAEbl47g08DC4QEZKNoR4wH1tAwIqdyAIplLoEnlBWmwv2CRzT/YpEo7+IyQ8RMGVAvvm1FoGXSJvU+4I0Jq201fWL+GbNu3VFoesLZQaR4nmWQ6n1/AENUUu+gdljWGEqpEQObN5dD3BYmUaKJjkg1jomoqRaseKOmIAProigKxMCAuBJt9CBwHQQj1Fjb0Fb5/DYSxjY+FahjzJrgFotDwpRMyJEl3QC5owk5jbqVVswMji2GKQqCHWkEAYZ4uxNeMgBBVr9cEcTAkaQxIRVRJcS7aVZNcXhe804sAH7mVK0q0GLHEFkdc8XDilgp5yDr4S3ixTlRKqG697TiodafjC41jkaX1rlBuYjvc4ZrbPo7kZQczAAAAAA==') format('woff2'),
url('//at.alicdn.com/t/font_1699077_nnhvr47tsmd.woff?t=1584947660650') format('woff'),
url('//at.alicdn.com/t/font_1699077_nnhvr47tsmd.ttf?t=1584947660650') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('//at.alicdn.com/t/font_1699077_nnhvr47tsmd.svg?t=1584947660650#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-warning:before {
content: "\e836";
}
.icon-info:before {
content: "\e64b";
}
.icon-error:before {
content: "\e651";
}
.icon-success:before {
content: "\e66b";
}
.icon-close:before {
content: "\e615";
}
.icon-password-unvisible:before {
content: "\e723";
}
.icon-password-visible:before {
content: "\e609";
}
目标及说明
页面中一个简短的提示信息。
参数
属性:
参数 | 说明 | 类型 | 可选值 | 默认值 |
type | 主题风格 | string | success/warning/info/error | info |
closable | 是否可以关闭 | boolean | - | true |
center | 文字是否居中 | boolean | - | false |
插槽:
插槽名 | 说明 |
default | 文本区域 |
需求:
- 点击右侧的关闭按钮,隐藏
- 如果不允许关闭,关闭按钮并不创建出来
- 如果没有通过插槽传入内容,显示
提示信息!
- 插槽有值,显示插槽的值
- 如果没有值显示
提示信息!
创建组件并导出
基本结构和样式
package/alert/alert.vue
下面给出了基本的结构和样式。
<template>
<div class="my-alert my-alert--success">
<!-- 内容 -->
<div class="my-alert__content">
<span class="my-alert__title">成功提示的文案</span>
<!-- 关闭按钮 -->
<i class="my-alert__closebtn iconfont icon-close"></i>
</div>
</div>
</template>
<script>
export default {}
</script>
<style lang="less">
.my-alert {
width: 100%;
padding: 8px 16px;
margin: 0;
box-sizing: border-box;
border-radius: 4px;
position: relative;
background-color: #fff;
overflow: hidden;
opacity: 1;
display: flex;
align-items: center;
transition: opacity 0.2s;
// 成功
&.my-alert--success {
background-color: #f0f9eb;
color: #67c23a;
}
// 信息
&.my-alert--info {
background-color: #f4f4f5;
color: #909399;
}
// 警告
&.my-alert--warning {
background-color: #fdf6ec;
color: #e6a23c;
}
// 错误
&.my-alert--error {
background-color: #fef0f0;
color: #f56c6c;
}
// 是否居中
&.is-center {
justify-content: center;
}
.my-alert__content {
display: table-cell;
padding: 0 8px;
}
.my-alert__title {
font-size: 13px;
line-height: 18px;
}
.my-alert__closebtn {
font-size: 12px;
opacity: 1;
position: absolute;
top: 12px;
right: 15px;
cursor: pointer;
&::before {
color: #c0c4cc;
}
}
}
</style>
组件创建及引用
与button组件的处理一样。
- 在package文件夹下创建alert/alert.vue
- 在package/index.js中引入并导出alert组件
// 导入在packages下创建的各个组件
import Button from './button/button.vue'
import Alert from './alert/alert.vue'
// 引入字体样式
import './font.less'
// vue插件格式
const ui = {
install: function (Vue) {
console.log('install ...... ')
Vue.component('MyButton', Button)
Vue.component('MyAlert', Alert)
}
}
// 导出
export default ui
- 在example中,使用组件。
为了方便测试,可以去修改组件名,app.vue中的路由导航及路由设置。 - 效果:
http://localhost:8080/#/test-alert
允许自定义内容
<slot>默认内容</slot>
测试代码examples/views/test-alert.vue
<template>
<div class="about">
<h1>用来测试alert组件</h1>
<MyAlert>你已经帅出了天际,请注意收敛!</MyAlert>
<br>
<MyAlert>我已经想了你一整天了~~~</MyAlert>
<br>
<MyAlert></MyAlert>
</div>
</template>
组件代码packages/alert/alert.vue
<template>
<div class="my-alert my-alert--success">
<!-- 内容 -->
<div class="my-alert__content">
<!-- slot: 表示插槽。它用来获取在使用组件时,传入的组件的内容
如果不传入,就使用默认内容
-->
<span class="my-alert__title"><slot>我是默认的插槽内容!</slot></span>
<!-- 关闭按钮 -->
<i class="my-alert__closebtn iconfont icon-close"></i>
</div>
</div>
</template>
注意:
- slot的作用是让外部传递结构
- 如果希望有默认值直接写在
slot
的内部
- 外部不传递直接使用默认值
- 叫做
插槽的后备内容
允许传入类型
父传子,在alert.vue中设置prop即可,并在视图中使用。
组件代码
props: {
type: {
type: String,
default: 'info'
}
}
<div class="my-alert" :class="'my-alert--'+type">
测试代码
<template>
<div class="about">
<h1>用来测试alert组件</h1>
<MyAlert type="error">你已经帅出了天际,请注意收敛!</MyAlert>
<br>
<MyAlert type="success">我已经想了你一整天了~~~</MyAlert>
<br>
<MyAlert type="warning"></MyAlert>
<br>
<MyAlert type="info">有了你,我的人生才**</MyAlert>
<br>
<MyAlert>有了你,我的人生才**</MyAlert>
</div>
</template>
效果
类型校验
对于传递进子组件中prop 类型校验 ,可以通过类型校验来判断,并给出提示帮助开发者传递正确的参数。
// alert的类型
props: {
type: {
type: String,
default: 'info',
validator: function (val) {
// 如果用户传入的type是下面4个之一:success,error,info,warning
const types = ['success', 'error', 'info', 'warning']
// 则通过验证 return true,否则,不通过 return false
if (types.includes(val)) {
return true
} else {
console.error(`你传入的类型${val},目前不支持`)
return false
}
}
}
}
注意:
- type可以实现类型校验,但是高级的校验无法实现
validator(value){}
可以实现自定义校验
- value就是传入的属性值
- 通过return
true
或者false
实现校验
- true通过
- false失败
- 判断逻辑根据需求来写即可
是否允许关闭
props: {
// 是否可以关闭
closable: {
type: Boolean,
default: true
}
}
模板
<template>
<div
+ v-show="isShow"
class="my-alert" :class="'my-alert--'+type">
<!-- 内容 -->
<div class="my-alert__content">
<!-- slot: 表示插槽。它用来获取在使用组件时,传入的组件的内容 -->
<span class="my-alert__title"><slot>我是默认的插槽内容!</slot></span>
<!-- 关闭按钮 -->
+ <i v-if="closable" @click="isShow=false" class="my-alert__closebtn iconfont icon-close"></i>
</div>
</div>
</template>
数据:
data () {
return {
// 是否可见
isShow: true
}
}
是否居中
注意如果只传入一个boolean值即可。
根据center
的布尔值来决定是否设置is-center
这个类名。
在父组件中
<my-alert center type="error">错误信息</my-alert>
添加prop
props: {
// ....
// 文字是否居中
center: {
type: Boolean,
default: false
}
}
视图:补充一个类
<div
v-show="isShow"
class="my-alert"
+ :class="['my-alert--'+type, {'is-center': center}]"
>
测试代码
<template>
<div class="about">
<h1>用来测试alert组件</h1>
<!-- 如果传入的prop是boolean类型,则可以直接写prop名,就等价于:center="true" -->
<MyAlert type="error" center>你已经帅出了天际,请注意收敛!</MyAlert>
<br>
<MyAlert type="success" :closable="false">我已经想了你一整天了~~~</MyAlert>
<br>
<MyAlert type="warning" :center="true"></MyAlert>
<br>
<MyAlert type="info" :center="true">有了你,我的人生才完整</MyAlert>
<br>
<MyAlert>有了你,我的人生才**</MyAlert>
</div>
</template>
小结
注意:
- 这里类名的绑定用到了
数组
和对象
,实现多种类名的绑定如果不熟悉建议看看:class="['my-alert--'+type, {'is-center': center}]"
结构
和样式
全部都实现准备好了,简化编码,但是大伙可能需要稍微看看- 布尔值的属性,传递是写属性名等同于设置为
true
,比如这里center
为true - 点击关闭的实现
- closable是外部传入的是否显示关闭按钮的标记
- 自己的显示切换通过
data
来定义
参考
<template>
<div
v-show="isShow"
class="my-alert"
:class="['my-alert--'+type, {'is-center': center}]"
>
<!-- 内容 -->
<!-- -->
<div class="my-alert__content">
<!-- slot: 表示插槽。它用来获取在使用组件时,传入的组件的内容 -->
<span class="my-alert__title"><slot>我是默认的插槽内容!</slot></span>
<!-- 关闭按钮 -->
<i v-if="closable" @click="isShow=false" class="my-alert__closebtn iconfont icon-close"></i>
</div>
</div>
</template>
<script>
export default {
name: 'MyAlert',
props: {
// 是否文本居中显示,默认是false
center: {
type: Boolean,
default: false
},
// 是否允许关闭,默认是true
closable: {
type: Boolean,
default: true
},
type: {
type: String,
default: 'info',
validator: function (val) {
// 如果用户传入的type是下面4个之一:success,error,info,warning
const types = ['success', 'error', 'info', 'warning']
// 则通过验证 return true,否则,不通过 return false
if (types.includes(val)) {
return true
} else {
console.error(`你传入的类型${val},目前不支持`)
return false
}
}
}
},
data () {
return {
// 是否可见
isShow: true
}
}
}
</script>
<style lang="less">
.my-alert {
width: 100%;
padding: 8px 16px;
margin: 0;
box-sizing: border-box;
border-radius: 4px;
position: relative;
background-color: #fff;
overflow: hidden;
opacity: 1;
display: flex;
align-items: center;
transition: opacity 0.2s;
// & : 表示它的上一级选择器 .my-alert
// 成功
&.my-alert--success {
background-color: #f0f9eb;
color: #67c23a;
}
// 信息
&.my-alert--info {
background-color: #f4f4f5;
color: #909399;
}
// 警告
&.my-alert--warning {
background-color: #fdf6ec;
color: #e6a23c;
}
// 错误
&.my-alert--error {
background-color: #fef0f0;
color: #f56c6c;
}
// 是否居中
&.is-center {
justify-content: center;
}
.my-alert__content {
display: table-cell;
padding: 0 8px;
}
.my-alert__title {
font-size: 13px;
line-height: 18px;
}
.my-alert__closebtn {
font-size: 12px;
opacity: 1;
position: absolute;
top: 12px;
right: 15px;
cursor: pointer;
&::before {
color: #c0c4cc;
}
}
}
</style>