自己在写这个组件的时候主要遇到的问题就是在动态传入背景图片或者背景色的时候没能立马顺利写出来,不过现在实现了这个简单组件就和大家分享一下
<template> <div class="card" :style="bg != undefined ? setBg() : {backgroundColor: '#fff'}"> <div class="cardTop"> <span class="left"> <span> <avatar class="leftImg" :src="cardImg" alt=""></avatar> </span> <span class="content"> <span class="cardName">{{cardName != undefined ? cardName : defaultCardName}}</span> <span class="cardType">{{cardType != undefined ? cardType : defaultCardType}}</span> </span> </span> <span class="right"> <avatar :src="QRCode" alt=""></avatar> </span> </div> <div class="cardBottom"> <span class="cardNum">卡号:{{cardNum != undefined ? cardNum : defaultCardNum}}</span> </div> </div> </template> <script> import Avatar from '@/components/avatar/Avatar.vue'; export default { components: { Avatar, }, props: { cardImg: {}, QRCode: {}, bg: {}, cardName: { type: String, }, cardType: { type: String, }, cardNum: { type: String, }, }, data() { return { backGround: '#fff', defaultCardName: '阿里云', defaultCardType: '会员卡', defaultCardNum: '8888 8888 8888' } }, computed: {}, methods: { setBg() { let cur = this.bg.lastIndexOf('.'); let img = this.bg.substr(cur + 1); if (/(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(img)) { return { backgroundImage: 'url(' + this.bg + ')' } } else { return { backgroundColor: this.bg } } } } } </script> <style scoped lang="less"> .card { height: 180px; max-width: 350px; display: flex; flex-direction: column; border-radius: 10px; padding: 10px; justify-content: space-between; border: 1px solid #ccc; .cardTop { display: flex; justify-content: space-between; .left { display: flex; flex-direction: row; .leftImg { height: 70px; width: 70px; } .content { margin-left: 10px; min-height: 70px; display: flex; flex-direction: column; justify-content: space-around; .cardName, .cardType { font-size: 18px; } } } .right { img { height: 50px; width: 50px; } } } .cardBottom { } } </style>
图片组件如下:
<template> <span :class="avatarCls"> <img :src="src" v-if="src"> <i v-else-if="icon" :class="['iconfont', `icon-${icon}`]"></i> <span v-else :class="`${prefixCls}-string`" :style="style" ref="children"> <slot></slot> </span> </span> </template> <script> export default { name: "Avatar", data() { return { prefixCls: "ei-avatar", scale: 1, isSlotShow: false, style: {} }; }, props: { size: { type: String, default: "large" }, src: String, shape: { type: String, default: "square" }, icon: String }, computed: { avatarCls() { const size = { large: "lg", small: "sm" }[this.size]; return [ this.prefixCls, `${this.prefixCls}-${this.shape}`, { [`${this.prefixCls}-${size}`]: !!size, [`${this.prefixCls}-icon`]: !!this.icon, [`${this.prefixCls}-image`]: !!this.src } ]; }, }, methods: { setScale() { this.isSlotShow = !this.src && !this.icon; if (this.$refs.children) { const childrenWidth = this.$refs.children.offsetWidth; const avatarWidth = this.$el.getBoundingClientRect().width; if (avatarWidth - 8 < childrenWidth) { this.scale = (avatarWidth - 8) / childrenWidth; } else { this.scale = 1; } } } }, mounted() { this.setScale(); }, updated() { this.setScale(); } }; </script> <style lang="stylus"> @import '../../assets/stylus/variable.styl'; @import '../../assets/stylus/mixin.styl'; .ei-avatar { display: inline-block; flex-center(start, center, center) text-align: center; background: $avatar-bg; color: $avatar-color; white-space: nowrap; position: relative; overflow: hidden; avatar-size($avatar-size-base, $avatar-font-size-base); &-lg { avatar-size($avatar-size-lg, $avatar-font-size-lg); } &-sm { avatar-size($avatar-size-sm, $avatar-font-size-sm); } &-square { border-radius: $avatar-border-radius; } & > img { width: 100%; height: 100%; display: block; } } </style>