仿Element-UI组件封装系列1-alert组件

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";
}

目标及说明

页面中一个简短的提示信息。

Element - Alert

参数

属性:

参数说明类型可选值默认值
type主题风格stringsuccess/warning/info/errorinfo
closable是否可以关闭boolean-true
center文字是否居中boolean-false

插槽:

插槽名说明
default文本区域

需求:

  1. 点击右侧的关闭按钮,隐藏
  2. 如果不允许关闭,关闭按钮并不创建出来
  3. 如果没有通过插槽传入内容,显示提示信息!
    • 插槽有值,显示插槽的值
    • 如果没有值显示提示信息!

创建组件并导出

在这里插入图片描述

基本结构和样式

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>

注意:

  1. slot的作用是让外部传递结构
  2. 如果希望有默认值直接写在slot的内部
    1. 外部不传递直接使用默认值
    2. 叫做插槽的后备内容

允许传入类型

父传子,在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
        }
      }
    }
  }

注意:

  1. type可以实现类型校验,但是高级的校验无法实现
  2. validator(value){}可以实现自定义校验
    1. value就是传入的属性值
    2. 通过returntrue或者false实现校验
      1. true通过
      2. false失败
    3. 判断逻辑根据需求来写即可

是否允许关闭

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>

小结

注意:

  1. 这里类名的绑定用到了数组对象,实现多种类名的绑定如果不熟悉建议看看

    :class="['my-alert--'+type, {'is-center': center}]"

  2. 结构样式全部都实现准备好了,简化编码,但是大伙可能需要稍微看看

  3. 布尔值的属性,传递是写属性名等同于设置为true,比如这里center为true

  4. 点击关闭的实现

    1. closable是外部传入的是否显示关闭按钮的标记
    2. 自己的显示切换通过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>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值