-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: 重构app-icon组件,优化逻辑,切换到srcipt-setup
- Loading branch information
Showing
7 changed files
with
140 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,65 @@ | ||
<template> | ||
<i v-bind="$attrs" style="display: inline-flex"> | ||
<el-icon v-if="iconType === 'ElIcon'" v-bind="iconProp"> | ||
<component :is="iconName" /> | ||
<i v-bind="$attrs" class="app-icon" :class="{ text }"> | ||
<el-icon v-if="isElIcon" :color="color" :size="parseInt(size)"> | ||
<component :is="icon" /> | ||
</el-icon> | ||
<svg v-else v-bind="iconProp"> | ||
<use :xlink:href.attr="iconName" /> | ||
</svg> | ||
<span v-if="text">{{ text }}</span> | ||
</i> | ||
</template> | ||
|
||
<script> | ||
<script setup> | ||
import { ElIcon } from 'element-plus' | ||
/** | ||
* <app-icon icon="el-icon-right" /> el-开头将渲染成 <i/> el图标支持小驼峰和中划线分割命名 | ||
* <app-icon icon="github" size="32" /> 其他则渲染成 <svg> | ||
* @example <app-icon icon="el-icon-right" /> el-开头将渲染成 <i/> el图标支持小驼峰和中划线分割命名 | ||
* <app-icon icon="github" size="32" /> 其他则渲染成 <svg> | ||
* | ||
* 附: 动态组件 <component :is="xxx" />模板编译的结果:_resolveDynamicComponent(xxx) | ||
* 该函数被定义在 runtime-core/src/helpers/resolveAssets.ts,内部调用app.context获取对应已注册的组件 | ||
* component 内置组件除了支持 is 绑定之外,也支持其他属性绑定和事件绑定 | ||
* | ||
* 如果svg标签的path标签已设置fill="color" 则该path的颜色也不会被更改 | ||
*/ | ||
import { ElIcon } from 'element-plus' | ||
const props = defineProps({ | ||
icon: { type: String, required: true }, | ||
size: { default: 16 }, | ||
color: { default: 'inherit' }, | ||
text: { type: [String, Number] }, | ||
}) | ||
export default { | ||
name: 'AppIcon', | ||
components: { ElIcon }, | ||
props: { | ||
icon: { type: String, required: true }, | ||
// 如果svg标签的path标签已设置fill="color" 则该path的颜色也不会被更改 | ||
color: { type: String }, | ||
size: { default: 16 }, | ||
}, | ||
setup(props) { | ||
const { icon, color, size } = props | ||
let iconType, iconName, iconProp | ||
if (icon.startsWith('el-icon-') || icon.startsWith('elIcon')) { | ||
iconType = 'ElIcon' | ||
iconName = icon | ||
iconProp = { color, size: Number(size) } | ||
} else { | ||
// 根据名字生成id使用svg>symbol里的svg标签(已提前注入到index.html中body下的svg标签) | ||
iconType = 'Custom' | ||
iconName = '#icon-' + icon | ||
const sizePx = size + 'px' | ||
const style = { width: sizePx, height: sizePx } | ||
if (color) { | ||
style.color = color | ||
style.fill = 'currentColor' | ||
} | ||
iconProp = { style } | ||
} | ||
return { iconType, iconName, iconProp } | ||
}, | ||
const isElIcon = /^el-?/i.test(props.icon) | ||
let iconName, iconProp | ||
// 如果不是el-icon,则使用svg sprites图标,以 #icon- 为id前缀进行引用 | ||
if (!isElIcon) { | ||
iconName = '#icon-' + props.icon | ||
const size = isNaN(props.size) ? props.size : props.size + 'px' | ||
const style = { width: size, height: size } | ||
if (props.color) { | ||
style.color = props.color | ||
style.fill = 'currentColor' | ||
} | ||
iconProp = { style } | ||
} | ||
</script> | ||
|
||
<style lang="scss"> | ||
@import '/src/styles/variables'; | ||
.app-icon { | ||
display: inline-flex; | ||
} | ||
.app-icon.text { | ||
align-items: center; | ||
cursor: pointer; | ||
} | ||
.app-icon.text:hover { | ||
color: #1d7dfa; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import defaultAvatar from '/src/assets/images/dio.jpg' | ||
import defaultBackground from '/src/assets/images/cute.jpg' | ||
import { getStrColor } from '../utils/process' | ||
|
||
/** | ||
* 项目难点标记:检测图片存在,如果不存在则用用户的昵称的首字符作为头像,绘制svg | ||
* 检测图片是否存在 | ||
* @param url | ||
*/ | ||
const imageIsExist = function (url) { | ||
return new Promise((resolve) => { | ||
let img = new Image() | ||
img.src = url | ||
img.onload = () => { | ||
if (img.complete === true) { | ||
resolve(true) | ||
img = null | ||
} | ||
} | ||
img.onerror = () => { | ||
resolve(false) | ||
img = null | ||
} | ||
}) | ||
} | ||
|
||
function genSvgImg(text, color, size = 36) { | ||
text = text.substring(0, 1) | ||
color = encodeURIComponent(color) | ||
return `data:image/svg+xml;utf8, | ||
<svg viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg"> | ||
<rect width="100%" height="100%" fill="${color}"/> | ||
<text x="50%" y="53%" text-anchor="middle" dominant-baseline="middle" fill='%23f1f1f1'>${text}</text> | ||
</svg>` | ||
} | ||
|
||
/** | ||
* 当图片加载失败时,显示默认图片 | ||
* 参数可选:'avatar' | 'background' | string | ||
* <img :src="xxxx" v-default-img.avatar /> | ||
*/ | ||
export default async function defaultImg(el, binding) { | ||
// 需要显示默认图片(当图片原本的src属性有错时)的类型 | ||
const { value, modifiers } = binding | ||
// 图片原本的src | ||
const realURL = el.src | ||
// 当原本图片不存在时,根据参数返回不同的图片url | ||
const exist = await imageIsExist(realURL) | ||
if (exist) return // 图片可正常加载,不做任何处理 | ||
if (value) { | ||
el.setAttribute('src', genSvgImg(value, getStrColor(value))) | ||
} else if (modifiers.avatar) { | ||
el.setAttribute('src', defaultAvatar) | ||
} else if (modifiers.background) { | ||
el.setAttribute('src', defaultBackground) | ||
} else { | ||
el.remove() // 什么都不加 v-default-img 时 移除图片 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
$sidebar-logo-height: 42px; | ||
$navbar-height: 42px; | ||
$tabBar-height: 30px; | ||
$sm-width: 768px; | ||
|
||
:export { | ||
smWidth: $sm-width; | ||
navbarHeight: $navbar-height; | ||
tabBarHeight: $tabBar-height; | ||
sidebarLogoHeight: $sidebar-logo-height; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters