前端学习案例-手动封装element-ui里面的button组件

简介: 前端学习案例-手动封装element-ui里面的button组件
首先我们知道vue里面包含有父子组件
但是你知道如果要进行一个element的手动组件封装
怎么封装吗
1首先第一步
首先我们建立一个组件
最好设置在一个文件目录下比如components
只是一个普通的组件
叫做OneButton.vue
        <template>
           <button class="one-button">
            按钮组件
           </button>
         </template>
         <script>
         export default {
           name: 'oneButton'
         }
     </script>
         <style lang="scss">
     </style>要想使用该组件
就需要进行全局注册
就是在main.js里面注册了
     import Vue from 'vue'
         import App from './App.vue'
         // 第一步:导入button组件
         import OneButton from './components/button.vue'
         Vue.config.productionTip = false
         // 第二步:注册组件,设置(组件名,组件)
         Vue.component(OneButton.name, OneButton)
         new Vue({
           render: h => h(App)
         }).$mount('#app')注册完成以后就可以进行使用了
    <template>
       <div id="app">
         <one-button>按钮</one-button>
       </div>
     </template>
     <script>
     export default {
       name: 'App',
       components: {}
     }
     </script>
     <style lang="scss">
     </style>到这里
我们可以看到 就会显示一个普通按钮了
但是吧 这样的封装过于简单
能不能实现更加复杂的操作呢
于是
我们需要封装一个有element-ui风格的组件
好 那我们继续实现
我们先让文字可以自由的输入
那就要利用插槽了
     <template>
           <button class="one-button">
            <span><slot></slot></span>
           </button>
         </template>我们的文件需要做以上处理
     <template>
           <div>
             <one-button>歌谣</one-button>
             <one-button>帅气</one-button>
             <one-button>关注我</one-button>
           </div>
         </template>加上基本样式
     <style lang="scss">
           .one-button{
             display: inline-block;
             line-height: 1;
             white-space: nowrap;
             cursor: pointer;
             background: #ffffff;
             border: 1px solid #dcdfe6;
             color: #606266;
             -webkit-appearance: none;
             text-align: center;
             box-sizing: border-box;
             outline: none;
             margin: 0;
             transition: 0.1s;
             font-weight: 500;
             //禁止元素的文字被选中
             -moz-user-select: none;
             -webkit-user-select: none;
             -moz-user-select: none;
             -ms-user-select: none;
             padding: 12px 20px;
             font-size: 14px;
             border-radius: 4px;
             &:hover,
             &:hover{
               color: #409eff;
               border-color: #c6e2ff;
               background-color: #ecf5ff;
             }
           }
         </style>这样文字的效果就实现了
到了这里 你又想element里面可以控制type属性控制按钮样式
怎么可以实现呢
父元素传递type值
        <template>
           <div id="app">
             <div class="row">
             <one-button>按钮</one-button>
             <one-button type="primary">primary按钮</one-button>
             <one-button type="success">success按钮</one-button>
             <one-button type="info">info按钮</one-button>
             <one-button type="danger">danger按钮</one-button>
             <one-button type="warning">warning按钮</one-button>
             </div>
           </div>
         </template>子元素接收当然props了
     export default {
           name: 'oneButton',
           // 此时对props进行校验,值接收string类型的type值
           props: {
             type:{
               type: String,
               // 设置默认值:如果不传值,那么使用default
               default: 'default'
             }
           },
           created () {
             console.log(this.type)//defalut primary success info danger warning
           }
         }做过处理以后根据type就可以实现数据的操作了
动态绑定样式
      <template>
           <button class="one-button" :class="`one-button-${type}`">
            <span><slot></slot></span>
           </button>
         </template>最后定义好样式
      .one-button-primary{
           color:#fff;
           background-color: #409eff;
           border-color: #409eff;
           &:hover,
           &:focus{
             background: #66b1ff;
             background-color: #66b1ff;
             color: #fff;
             }
           }
           .one-button-success{
           color:#fff;
           background-color: #67c23a;
           border-color: #67c23a;
           &:hover,
           &:focus{
             background: #85ce61;
             background-color: #85ce61;
             color: #fff;
             }
           }
           .one-button-info{
           color:#fff;
           background-color: #909399;
           border-color: #909399;
           &:hover,
           &:focus{
             background: #a6a9ad;
             background-color: #a6a9ad;
             color: #fff;
             }
           }
           .one-button-warning{
           color:#fff;
           background-color: #e6a23c;
           border-color: #e6a23c;
           &:hover,
           &:focus{
             background: #ebb563;
             background-color: #ebb563;
             color: #fff;
             }
           }
           .one-button-danger{
           color:#fff;
           background-color: #f56c6c;
           border-color: #f56c6c;
           &:hover,
           &:focus{
             background: #f78989;
             background-color: #f78989;
             color: #fff;
             }
           }运行
nice呀 有没有
这个时候你可能会想
如果设置plain属性怎么设置呢
和type类型相同,我们只要将样式先设置好,然后通过父组件传递过来的值进行判断,就可以设置plain属性了。
    和type类型相同,我们只要将样式先设置好,然后通过父组件传递过来的值进行判断,就可以设置plain属性了。
     第一步:父组件组件传递plain值
         <template>
           <div id="app">
             <div class="row">
             <one-button plain>按钮</one-button>
             <one-button plain type="primary">primary按钮</one-button>
             <one-button plain type="success">success按钮</one-button>
             <one-button plain type="info">info按钮</one-button>
             <one-button plain type="danger">danger按钮</one-button>
             <one-button plain type="warning">warning按钮</one-button>
             </div>
           </div>
         </template>
     第二步:子组件接收负组件传递的数据,同样进行props校验,并且设置默认值为false
           props: {
             plain: {
               type: Boolean,
               default: false
             }
           }
     第三步:通过绑定类名的方法动态控制样式,由于plain类型是布尔值,所以在类型中我们使用对象的形式来控制样式
         <template>
           <button class="one-button" :class="[`one-button-${type}`,{
             'is-plain':plain
           }]">
            <span><slot></slot></span>
           </button>
         </template>
     第四步:设置不同类型的样式,由于plain类型是以对象的形式在类中定义的,所以使用获取属性的方法定义样式
         // 朴素按钮样式
         .one-button.is-plain{
           &:hover,
           &:focus{
             background: #fff;
             border-color: #489eff;
             color: #409eff;
           }
         }
         .one-button-primary.is-plain{
           color: #409eff;
           background: #ecf5ff;
           &:hover,
           &:focus{
             background: #409eff;
             border-color: #409eff;
             color: #fff;
           }
         }
         .one-button-success.is-plain{
           color: #67c23a;
           background: #c2e7b0;
           &:hover,
           &:focus{
             background: #67c23a;
             border-color: #67c23a;
             color: #fff;
           }
         }
         .one-button-info.is-plain{
           color: #909399;
           background: #d3d4d6;
           &:hover,
           &:focus{
             background: #909399;
             border-color: #909399;
             color: #fff;
           }
         }
         .one-button-warning.is-plain{
           color: #e6a23c;
           background: #f5dab1;
           &:hover,
           &:focus{
             background: #e6a23c;
             border-color: #e6a23c;
             color: #fff;
           }
         }
         .one-button-danger.is-plain{
           color: #f56c6c;
           background: #fbc4c4;
           &:hover,
           &:focus{
             background: #f56c6c;
             border-color: #f56c6c;
             color: #fff;
           }
         }nice呀 有没有
round属性也是一样
    button组件的round属性
     设置round属性和之前的相似,只要在组件中定义好了样式,动态获取属性值即可。
     获取属性值:
             round: {
               type: Boolean,
               default: false
             }
     round样式:
         .one-button.is-round{
           border-radius: 20px;
           padding: 12px 23px;
         }看看效果
nice有没有
到这里
我们看看字体图标怎么实现
字体图标也是要引入的
    第一步:在main.js中引入字体图标
     import './assets/fonts/iconfont.css'
     第二步:将下载的字体图标css文件中的类名做修改,我将icon全部改为了one-icon,并且将初始的iconfont类改为了[class*='one-icon'],当类名中有one-icon时使用,如下
         [class*='one-icon'] {
           font-family: "iconfont" !important;
           font-size: 16px;
           font-style: normal;
           -webkit-font-smoothing: antialiased;
           -moz-osx-font-smoothing: grayscale;
         }
         .one-icon-bluetoothoff:before {
           content: "\e697";
         }
     第三步:父组件传递图标名,子组件接收并且放到图标中
     父组件传值:
             <div class="row">
               <one-button icon="bluetoothon"></one-button>
               <one-button type="primary" icon="camera">照相机</one-button>
               <one-button type="success" icon="course"></one-button>
               <one-button type="info" icon="bluetooth_link"></one-button>
               <one-button type="danger" icon="addto"></one-button>
               <one-button type="warning" icon="audio"></one-button>
             </div>
     子组件接收:
             icon: {
               type: String,
               default: ''
             }
     使用接收到的字体图标。在没有传入icon时隐藏<i>标签,在slot插槽没有传入值时,不显示<span>标签
         <template>
           <button class="one-button" :class="[`one-button-${type}`,{
             'is-plain':plain,
             'is-round':round,
             'is-circle':circle,
           }]">
           <i v-if="icon" :class="`one-icon-${icon}`"></i>
           <!-- 如果没传入文本插槽,则不显示span内容 -->
            <span v-if="$slots.default"><slot></slot></span>
           </button>
         </template>
     第四步:设置icon配套样式,使图标和文字之间有一定间隔
         .one-button [class*=one-icon-]+span{
           margin-left: 5px;
         }
      查看效果
nice有没有
到这里
我们想一想element里面还有点击事件怎么实现
    button组件中的点击事件
     我们在使用组件时,直接给组件定义事件是不会被触发的。我们需要在组件中定义一个点击事件,这个点击事件不进行其他操作,只出发父组件中的点击事件。
     组件中的定义点击事件:
         <template>
           <button class="one-button" :class="[`one-button-${type}`,{
             'is-plain':plain,
             'is-round':round,
             'is-circle':circle,
           }]"
           @click="handleClick"
           >
           <i v-if="icon" :class="`one-icon-${icon}`"></i>
           <!-- 如果没传入文本插槽,则不显示span内容 -->
            <span v-if="$slots.default"><slot></slot></span>
           </button>
         </template>
      定义一个点击事件,这个点击事件的作用是调用父组件中的点击事件,并且回调
           methods: {
             handleClick (e) {
               this.$emit('click', e)
             }
           }
     父组件在使用时定义自己的点击事件,其本质是子组件中的点击事件触发父组件中的点击事件。
         <div class="row">
           <one-button @click="getInfo">按钮</one-button>
         </div>
           methods: {
             getInfo () {
               console.log('获取信息!!')//获取信息!!
             }
           }就很nice
按钮中会设置是否禁用
我们可以通过父子传值
给子组件设置样式实现
    button组件中的disabled属性
     和之前相似,只要父子组件传值并且动态获取这个值并且赋给disabled属性,并且设置一个disabled样式即可。
         <div class="row">
           <one-button @click="getInfo" disabled>按钮</one-button>
         </div>
         <template>
           <button class="one-button" :class="[`one-button-${type}`,{
             'is-plain':plain,
             'is-round':round,
             'is-circle':circle,
             'is-disabled':disabled
           }]"
           @click="handleClick"
           :disabled="disabled"
           >
           <i v-if="icon" :class="`one-icon-${icon}`"></i>
            <span v-if="$slots.default"><slot></slot></span>
           </button>
         </template>
             disabled: {
               type: Boolean,
               default: false
             }
      disabled样式:
         .one-button.is-disabled{
            cursor: no-drop;
         }至此 element中的button组件就封装完成了 是不是很nice
下次有时间继续封转其他的
看看封装的总代码
    <template>
       <button class="one-button" :class="[`one-button-${type}`,{
         'is-plain':plain,
         'is-round':round,
         'is-circle':circle,
         'is-disabled':disabled
       }]"
       @click="handleClick"
       :disabled="disabled"
       >
       <i v-if="icon" :class="`one-icon-${icon}`"></i>
       <!-- 如果没传入文本插槽,则不显示span内容 -->
        <span v-if="$slots.default"><slot></slot></span>
       </button>
     </template>
     <script>
     export default {
       name: 'oneButton',
       // 此时对props进行校验,值接收string类型的type值
       props: {
         type: {
           type: String,
           // 设置默认值:如果不传值,那么使用default
           default: 'defalut'
         },
         plain: {
           type: Boolean,
           default: false
         },
         round: {
           type: Boolean,
           default: false
         },
         circle: {
           type: Boolean,
           default: false
         },
         icon: {
           type: String,
           default: ''
         },
         disabled: {
           type: Boolean,
           default: false
         }
       },
       created () {
         // 显示所有插槽
         // console.log(this.$slots)
       },
       methods: {
         // 定义一个点击事件,这个点击事件的作用是调用父组件中的点击事件,并且回调
         handleClick (e) {
           this.$emit('click', e)
         }
       }
     }
     </script>
     <style lang="scss" scoped>
       .one-button{
         display: inline-block;
         line-height: 1;
         white-space: nowrap;
         cursor: pointer;
         background: #ffffff;
         border: 1px solid #dcdfe6;
         color: #606266;
         -webkit-appearance: none;
         text-align: center;
         box-sizing: border-box;
         outline: none;
         margin: 0;
         transition: 0.1s;
         font-weight: 500;
         //禁止元素的文字被选中
         -moz-user-select: none;
         -webkit-user-select: none;
         -moz-user-select: none;
         -ms-user-select: none;
         padding: 12px 20px;
         font-size: 14px;
         border-radius: 4px;
         &:hover,
         &:focus{
           color: #409eff;
           border-color: #c6e2ff;
           background-color: #ecf5ff;
         }
       }
     .one-button-primary{
       color:#fff;
       background-color: #409eff;
       border-color: #409eff;
       &:hover,
       &:focus{
         background: #66b1ff;
         background-color: #66b1ff;
         color: #fff;
         }
       }
       .one-button-success{
       color:#fff;
       background-color: #67c23a;
       border-color: #67c23a;
       &:hover,
       &:focus{
         background: #85ce61;
         background-color: #85ce61;
         color: #fff;
         }
       }
       .one-button-info{
       color:#fff;
       background-color: #909399;
       border-color: #909399;
       &:hover,
       &:focus{
         background: #a6a9ad;
         background-color: #a6a9ad;
         color: #fff;
         }
       }
       .one-button-warning{
       color:#fff;
       background-color: #e6a23c;
       border-color: #e6a23c;
       &:hover,
       &:focus{
         background: #ebb563;
         background-color: #ebb563;
         color: #fff;
         }
       }
       .one-button-danger{
       color:#fff;
       background-color: #f56c6c;
       border-color: #f56c6c;
       &:hover,
       &:focus{
         background: #f78989;
         background-color: #f78989;
         color: #fff;
         }
       }
     // 朴素按钮样式
     .one-button.is-plain{
       &:hover,
       &:focus{
         background: #fff;
         border-color: #489eff;
         color: #409eff;
       }
     }
     .one-button-primary.is-plain{
       color: #409eff;
       background: #ecf5ff;
       &:hover,
       &:focus{
         background: #409eff;
         border-color: #409eff;
         color: #fff;
       }
     }
     .one-button-success.is-plain{
       color: #67c23a;
       background: #c2e7b0;
       &:hover,
       &:focus{
         background: #67c23a;
         border-color: #67c23a;
         color: #fff;
       }
     }
     .one-button-info.is-plain{
       color: #909399;
       background: #d3d4d6;
       &:hover,
       &:focus{
         background: #909399;
         border-color: #909399;
         color: #fff;
       }
     }
     .one-button-warning.is-plain{
       color: #e6a23c;
       background: #f5dab1;
       &:hover,
       &:focus{
         background: #e6a23c;
         border-color: #e6a23c;
         color: #fff;
       }
     }
     .one-button-danger.is-plain{
       color: #f56c6c;
       background: #fbc4c4;
       &:hover,
       &:focus{
         background: #f56c6c;
         border-color: #f56c6c;
         color: #fff;
       }
     }
     // round属性
     .one-button.is-round{
       border-radius: 20px;
       padding: 12px 23px;
     }
     // circle属性
     .one-button.is-circle{
       border-radius: 50%;
       padding: 12px;
     }
     // icon配套样式
     .one-button [class*=one-icon-]+span{
       margin-left: 5px;
     }
     // disabled属性
     .one-button.is-disabled{
        cursor: no-drop;
     }
     </style>
相关文章
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
上下文选择器(迭代选择器):基于祖先或同胞元素选择一个元素 ID和类选择器:基于id#和class的属性值进行选择元素。 属性选择器:基于属性的有无和特征进行选择。 ①上下文选择器: 上下文选择器的语法格式:标签1 标签2{属性:值;} //注意:组合选择器和上下文选择器的区别,组合选择器以逗号隔开, 上下文选择器以空格隔开 ②特殊的上下文选择器 子选择器> : 语法格式:标签1>标签2 解释说明:标签1和标签2
739 1
|
开发者 容器
44.[HarmonyOS NEXT RelativeContainer案例一] 掌握组件锚点布局:打造灵活精准的UI定位系统
在HarmonyOS NEXT的UI开发中,精确控制组件位置是构建复杂界面的关键。RelativeContainer作为一种强大的布局容器,通过锚点系统提供了精确定位能力,使开发者能够创建出灵活且精准的UI布局。本教程将详细讲解如何使用RelativeContainer的锚点布局功能,帮助你掌握这一核心技术。
477 4
|
前端开发 API 开发者
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
本文由黑臂麒麟(6年前端经验)撰写,介绍ArkTS开发中的常用基础组件与布局组件。基础组件包括Text、Image、Button等,支持样式设置如字体颜色、大小和加粗等,并可通过Resource资源引用统一管理样式。布局组件涵盖Column、Row、List、Grid和Tabs等,支持灵活的主轴与交叉轴对齐方式、分割线设置及滚动事件监听。同时,Tabs组件可实现自定义样式与页签切换功能。内容结合代码示例,适合初学者快速上手ArkTS开发。参考华为开发者联盟官网基础课程。
1670 75
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
1332 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
687 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
定位技术 容器
48.[HarmonyOS NEXT RelativeContainer案例五] 精确表单布局:辅助线定位技术打造专业级UI
在HarmonyOS NEXT的UI开发中,表单是常见且重要的界面元素。创建对齐精确、布局合理的表单需要精细的定位控制。RelativeContainer提供的辅助线(Guideline)功能,为表单布局提供了强大的支持。本教程将详细讲解如何使用RelativeContainer的辅助线功能实现精确的表单布局,帮助你掌握这一专业级UI技术。
391 7
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
706 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
开发框架 前端开发 JavaScript
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发一
本文介绍了方舟开发框架(ArkUI)及其两种开发范式:基于ArkTS的声明式开发范式和类Web开发范式。ArkUI是用于构建HarmonyOS应用界面的UI框架,提供极简UI语法和基础设施。声明式开发范式使用ArkTS语言,以组件、动画和状态管理为核心,适合复杂团队协作;类Web开发范式采用HML、CSS、JavaScript三段式开发,适用于简单界面应用,贴近Web开发者习惯。文中还概述了两者的架构和基础能力,帮助开发者选择合适的范式进行高效开发。
574 15
|
编解码 前端开发 Java
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发三
本文介绍了基于声明式UI范式的图形绘制与动画效果实现方法,涵盖绘制图形、添加动画效果及常见组件说明三部分内容。在绘制图形部分,详细讲解了如何通过Circle组件为食物成分表添加圆形标签,以及使用Path组件结合SVG命令绘制自定义图形(如应用Logo)。动画效果部分则展示了如何利用animateTo实现闪屏动画,包括渐出、放大效果,并设置页面跳转;同时介绍了页面间共享元素转场动画的实现方式。最后,文章列举了声明式开发范式中的各类组件及其功能,帮助开发者快速上手构建复杂交互页面。
557 11
|
存储 开发者 容器
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
本文介绍了ArkTS语言中的Class类、泛型、接口、模块化、自定义组件及状态管理等核心概念,并结合代码示例讲解了对象属性、构造方法、继承、静态成员、访问修饰符等内容,同时涵盖了路由管理、生命周期和Stage模型等应用开发关键知识点。
911 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例

热门文章

最新文章