
在考虑了将矢量图标从图标字体迁移到内联 SVG 的 原因 之后,我在 Vue.js 中找到了一个用 SVG 替换图标字体的解决方案,同时仍能保持使用图标字体的灵活性和易用性——能够使用 CSS 轻松改变图标的大小、颜色以及其它属性。
一种流行的方法是使用 v-html 指令和 npm 模块 html-loader 来将 SVG 导入到我们的 Vue 模板中,并在 Vue 的生命周期函数 mounted() 中修改渲染的 <svg> 元素。CSS 样式可以直接应用到 <svg> 元素或者是其父元素上,并且这些能够组成一个可复用的组件。
创建 Svg-icon 组件
让我们创建 Svg-icon.vue 组件文件,并在里面接收三个 prop 变量。
icon 是一个字符串类型的 prop 变量用来传递 .svg 文件名的导入
hasFill 是一个布尔类型的 prop 变量来告诉组件 fill 属性是否用于更改 <svg> 元素的颜色,默认值为 false 即不使用 fill 属性
growByHeight 是一个布尔类型的 prop 变量来决定 height 或 width 是否相对于 font-size 进行缩放,默认值为 true 即使用 height
<script>
function recursivelyRemoveFill(el) {
if (!el) {
return;
}
el.removeAttribute('fill');
[].forEach.call(el.children, child => {
recursivelyRemoveFill(child);
});
}
export default {
name: 'svg-icon',
props: {
icon: {
type: String,
default: null
},
hasFill: {
type: Boolean,
default: false
},
growByHeight: {
type: Boolean,
default: true
},
},
mounted() {
if (this.$el.firstElementChild.nodeName === 'svg') {
const svgElement = this.$el.firstElementChild;
const widthToHeight = (svgElement.clientWidth / svgElement.clientHeight).toFixed(2);
if (this.hasFill) {
// recursively remove all fill attribute of element and its nested children
recursivelyRemoveFill(svgElement);
}
// set width and height relative to font size
// if growByHeight is true, height set to 1em else width set to 1em and remaining is calculated based on widthToHeight ratio
if (this.growByHeight) {
svgElement.setAttribute('height', '1em');
svgElement.setAttribute('width', `${widthToHeight}em`);
} else {
svgElement.setAttribute('width', '1em');
svgElement.setAttribute('height', `${1 / widthToHeight}em`);
}
svgElement.classList.add('svg-class');
}
}
}
</script><template>
<div v-html="require(`html-loader!../assets/svg/${icon}.svg`)" class="svg-container"></div>
</template>
<style lang="scss" scoped>
.svg-container {
display: inline-flex;
}
.svg-class {










