首先我们知道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>