在 React、Vue项目中使用SVG的方法


Posted in Javascript onFebruary 09, 2018

在一些现代的扁平化设计网站,特别是移动端网站,经常会包含许多简单而清晰的小图标,例如网站图标、用户的默认头像、移动端网页首页底部固定的切换栏等,这些小图标一般都是由美工做好,可能会放到精灵图上,前端再进行裁切展示。

在 React、Vue项目中使用SVG的方法

而实际上,这些简单的小图标完全没必要让美工来做,前端完全可以通过 svg使用代码把这些简单的图标画出来,并且,因为这些图标是用代码描述出来的,所以如果想要修改这些图标,例如改变图标的颜色、图标的形状、大小等,都只是改几行代码的事情,非常简单,根本无需美工返工重做。

本文不是阐述如何利用 svg 来进行画图的,不了解 svg的可以前往 这里查看, 本文主要说一下如何在网站中使用 svg。

SVG在一般网页中的使用

svg使用 XML 格式定义图像,你也可以把它看做是一般的 HTML标签,镶嵌在网页中呈现出某种效果,在网页中使用svg的基本示例如下:

<body>
  <svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <rect width="100%" height="100%" style="fill:pink;stroke-width:1;stroke:rgb(0,0,0)"/>
  </svg></body>

效果如下:

在 React、Vue项目中使用SVG的方法

可以看到,普通网页中使用 svg是很简单的,只要你能把 svg图标画出来,在网页中的呈现完全不是问题。

在 Vue中使用 Svg

你完全可以像在 普通网页中使用 svg那样在Vue中使用,不过,既然已经是选择 vue来组件化开发项目了,那么在一堆组件中,穿插一大段的 svg毕竟有点不太好看。

一种解决方法是,利用 svg的 use标签,不直接在主页面中编写绘制svg图标的代码,而是把这一大段的代码放到另外的文件中,然后使用 use引用这段绘制图标的代码即可(好像饿了么移动端就是这么干的)。

例如,将所有绘制 svg的代码放到 svg-icon.vue文件中,所有图标的绘制代码使用 symbol标签分隔开并单独命名,避免错乱,然后将这个文件当做是一个组件导出,在主页面中引入此组件,接着,在需要 使用 svg图标的地方,通过 use标签将其引入。

svg-draw.vue代码示例如下:

<template>
 <svg
  xmlns="http://www.w3.org/2000/svg"
  xmlnsXlink="http://www.w3.org/1999/xlink"
  style={{position:'absolute',width:0,height:0}}>
  <defs>
   <symbol viewBox="0 0 26 31" id="location">
    <path xmlns="http://www.w3.org/2000/svg" d="M512.571517 65.907059c-204.736964 0-370.715183 165.979242-370.715183 370.724393 0 94.440929 35.320437 180.625824 93.462648 246.083651 1.572822 2.690272 3.50994 5.225001 5.817496 7.531534l240.297878 251.597225c1.279133 1.864464 2.736321 3.64297 4.393054 5.298679 2.111081 2.111081 4.418636 3.90596 6.856152 5.402033 14.458293 10.06524 34.491559 8.658194 47.393403-4.242627 3.26537-3.263323 5.78782-6.987135 7.582699-10.960633L783.610536 690.24766c1.867534-1.866511 3.489474-3.88447 4.876054-6.010901 58.951647-65.640999 94.819552-152.431691 94.819552-247.604284C883.305119 231.886301 717.325877 65.907059 512.571517 65.907059zM512.390391 588.611865c-82.734306 0-149.814074-67.087954-149.814074-149.842727 0-82.753749 67.079768-149.833517 149.814074-149.833517 82.772168 0 149.851936 67.079768 149.851936 149.833517C662.242328 521.523911 595.161536 588.611865 512.390391 588.611865z" fill="#d81e06"/>
   </symbol>
  </defs>
 </svg></template>

整个 vue组件导出一个大的 svg,此svg中包含了许多小的图标,类似于精灵图,每个图标使用 symbol分隔,并单独命名以方便引用。

使用示例如下:

// index.vue
...<svg class="location-icon">
 <use xlink:href="#location" rel="external nofollow" ></use></svg>...

然后,就可以看到网页中顺利出现对应的 svg图标了:

在 React、Vue项目中使用SVG的方法

不过,还有个问题,如果当前网站需要用到的 svg图标很多,势必就造成 svg-icon.vue这个文件体积逐渐变大,当前网页命名只需要用到其中一个 svg图标,结果你把几百个图标的 svg代码,全部加载了进来,明显不太友好,最好是能够按需加载,当前网页需要哪些图标就加载哪些,甚至一些可能出现可能不出现的图标,也在该出现时再加载,如果没有机会出现,那么永远不加载。

Github上有很多此类的插件,我介绍一个我觉得很好用的插件:vue-svg-icon,简单易用、快速上手。

首先,安装此插件,就不多说了,安装完成后,在项目的入口文件中注册此插件以方便全局调用:

import Icon from 'vue-svg-icon/Icon.vue'Vue.component('icon', Icon)

然后在根目录的 /src目录下新建一个 svg目录(目前这个路径只能是这样,不可配置为其他路径和目录),然后再这个目录中放入你想要使用的 svg图标的 svg文件即可。

例如一个微信图标的 svg如下:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1502683891821" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2885" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
<defs>
<style type="text/css"></style>
</defs>
<path d="M282.6 363.8c-23.7 0-47-15.7-47-38.9 0-23.7 23.3-38.9 46.5-38.9 23.7 0 38.9 15.2 38.9 38.9 0.5 23.2-15.1 38.9-38.4 38.9zM500.4 286c23.7 0 38.9 15.2 38.9 38.9 0 23.3-15.2 38.9-38.9 38.9-23.3 0-47-15.7-47-38.9 0-23.7 23.7-38.9 47-38.9z m167.7 84.5c9.8 0 19.7 0.5 30 1.8-27.3-125.6-161.4-218.7-314.4-218.7C212.4 153.6 72 270.3 72 418.3c0 85.9 46.5 155.6 124.8 210.2l-31.3 93.9 109.1-54.6c38.9 7.6 70.2 15.7 109.1 15.7 9.4 0 19.2-0.5 29.1-1.3-6.3-20.6-9.8-42.9-9.8-65.3-0.1-136 116.6-246.4 265.1-246.4z" p-id="2886"></path><path d="M772.7 573.9c-15.2 0-30.9-15.2-30.9-30.9 0.5-15.7 15.7-31.3 30.9-31.3 23.7 0 39.4 15.7 39.4 31.3-0.1 15.7-15.7 30.9-39.4 30.9z m-171.3 0c-15.2 0-30.9-15.2-30.9-30.9s15.7-31.3 30.9-31.3c23.7 0 38.9 15.7 38.9 31.3 0.5 15.7-15.2 30.9-38.9 30.9zM952 613.3C952 488.5 827.2 387 687.3 387c-148 0-264.7 101.5-264.7 226.3 0 124.8 116.7 225.8 264.7 225.8 31.3 0 62.6-8.1 93.5-15.7l85.9 47-23.7-77.8c62.5-47 109-109.1 109-179.3z" p-id="2887">
</path>
</svg>

将上述代码保存到一个 .svg的文件中,例如 wx.svg,放到 /src/svg目录中,这样就完成了准备工作。

接着,想要使用的话,很简单,直接在 vue组件中这么写:

<template>
  <icon class="wx-icon" name="wx"></icon></template>

在 React、Vue项目中使用SVG的方法

刷新页面时,打开控制台,可以看到页面中加载了这个 wx.svg文件,这样,就实现了 svg文件的按需引入。

在 React中使用 Svg

在 React中使用Svg和 vue一样,同样存在 3种方案,一种是直接在 react的 reader方法中写入 svg代码,第二种则是将所有 svg绘制代码放到一个文件中,然后将这个文件一次性载入,使用 use标签引用响应的 svg图案,第三种则是使用插件按需引入。

第一种直接在 渲染方法中写入 svg的方法就不多说了,第二种也很简单 ,和 vue一样,只不过写法上需要注意一下。

render() {
  return (
   <svg
    xmlns="http://www.w3.org/2000/svg"
    xmlnsXlink="http://www.w3.org/1999/xlink"
    style={{position:'absolute',width:0,height:0}}>
    <defs>
     <symbol viewBox="0 0 26 31" id="location">
      <path fill="#FFF" fillRule="evenodd" d="M22.116 22.601c-2.329 2.804-7.669 7.827-7.669 7.827-.799.762-2.094.763-2.897-.008 0 0-5.26-4.97-7.643-7.796C1.524 19.8 0 16.89 0 13.194 0 5.908 5.82 0 13 0s13 5.907 13 13.195c0 3.682-1.554 6.602-3.884 9.406zM18 13a5 5 0 1 0-10 0 5 5 0 0 0 10 0z"></path>
     </symbol>
     <symbol viewBox="0 0 14 8" id="arrow">
      <path fill="#FFF" fillRule="evenodd" d="M5.588 6.588c.78.78 2.04.784 2.824 0l5.176-5.176c.78-.78.517-1.412-.582-1.412H.994C-.107 0-.372.628.412 1.412l5.176 5.176z"></path>
     </symbol>
    </svg>
   )
}

主要是需要注意,因为 react使用 jsx语法,不允许出现 - 连字符,所以像 fill-rule这样的属性,就必须写成 fillRule,引用的时候同样如此。

// 引用的时候需要将 `xlink:href` 改写成 xlinkHref<svg className="arrow-left">
  <use xlinkhref="#arrow-left" rel="external nofollow" ></use>
 </svg>

第三种按需引入,只加载当前需要的 svg形状,同样是将每一个 svg图片作为一个单独的文件保存,然后再需要使用的地方进行引用。 Github上有个项目 react-svg,这个项目内部其实是对 SVGInjector的包装,

安装 react-svg之后,就可以像下面这样使用了:

import ReactSVG from 'react-svg'

ReactDOM.render(
 <ReactSVG
  path="atomic.svg"
  callback={svg => console.log(svg)}
  className="example"
 />,
 document.querySelector('.Root')
)

一般都只是在使用小图标的时候才考虑 svg,而这些小图标一般都比较简约,绘制起来也没什么难度,不过大部分情况下没有必要自己来画,很多网站都提供svg的图标下载,例如阿里的 iconfont,图标数量众多,基本可以满足绝大部分的需求,另外,类似的网站还有 easyicon 、 icomoon等。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在视频前插入广告
Nov 20 Javascript
JavaScript中几种排序算法的简单实现
Jul 29 Javascript
jQuery+html5+css3实现圆角无刷新表单带输入验证功能代码
Aug 21 Javascript
javascript运动框架用法实例分析(实现放大与缩小效果)
Jan 08 Javascript
js与applet相互调用的方法
Jun 22 Javascript
微信小程序 前端源码逻辑和工作流详解
Oct 08 Javascript
easyUI实现类似搜索框关键词自动提示功能示例代码
Dec 27 Javascript
原生JavaScript实现AJAX、JSONP
Feb 07 Javascript
Ionic项目中Native Camera的使用方法
Jun 07 Javascript
uni-app从安装到卸载的入门教程
May 15 Javascript
vue设置全局访问接口API地址操作
Aug 14 Javascript
JavaScript实现移动小精灵的案例代码
Dec 12 Javascript
JavaScript比较同一天的时间大小实例代码
Feb 09 #Javascript
vue2.0.js的多级联动选择器实现方法
Feb 09 #Javascript
使用mint-ui实现省市区三级联动效果的示例代码
Feb 09 #Javascript
vue二级路由设置方法
Feb 09 #Javascript
从零开始搭建一个react项目开发
Feb 09 #Javascript
Vue-Router2.X多种路由实现方式总结
Feb 09 #Javascript
浅谈react受控组件与非受控组件(小结)
Feb 09 #Javascript
You might like
根据ip调用新浪api获取城市名并转成拼音
2014/03/07 PHP
php的ZipArchive类用法实例
2014/10/20 PHP
实例简介PHP的一些高级面向对象编程的特性
2015/11/27 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
PHP+Mysql分布式事务与解决方案深入理解
2021/02/27 PHP
js cookies实现简单统计访问次数
2009/11/24 Javascript
文本框中禁止非数字字符输入比如手机号码、邮编
2013/08/19 Javascript
JS实现点击按钮自动增加一个单元格的方法
2015/03/09 Javascript
JS中dom0级事件和dom2级事件的区别介绍
2016/05/05 Javascript
基于jQuery倒计时插件实现团购秒杀效果
2016/05/13 Javascript
怎么引入(调用)一个JS文件
2016/05/26 Javascript
jQuery 操作input中radio的技巧
2016/07/18 Javascript
JavaScript实现的浏览器下载文件的方法
2017/08/09 Javascript
详解redux异步操作实践
2018/08/15 Javascript
微信小程序转发事件实现解析
2019/10/22 Javascript
js里面的变量范围分享
2020/07/18 Javascript
JavaScript的一些小技巧分享
2021/01/06 Javascript
Flask配置Cors跨域的实现
2019/07/12 Python
使用python远程操作linux过程解析
2019/12/04 Python
Python延迟绑定问题原理及解决方案
2020/08/04 Python
详解用 python-docx 创建浮动图片
2021/01/24 Python
联强国际笔试题面试题
2013/07/10 面试题
PPP协议组成及简述协议协商的基本过程
2015/05/28 面试题
这76道Java面试题及答案,祝你能成功通过面试
2016/04/16 面试题
计算机专业个人求职信范例
2013/09/23 职场文书
三项教育活动实施方案
2014/03/30 职场文书
模具专业自荐信
2014/05/29 职场文书
总账会计岗位职责
2015/04/02 职场文书
2015年办公室文员工作总结
2015/04/24 职场文书
2015年企业工作总结范文
2015/04/28 职场文书
漂亮妈妈观后感
2015/06/08 职场文书
经营场所证明范本
2015/06/19 职场文书
幼儿园毕业典礼园长致辞
2015/07/29 职场文书
小学运动会开幕词
2016/03/04 职场文书
微信小程序 WeUI扩展组件库的入门教程
2022/04/21 Javascript
超越Nginx的Web服务器caddy优雅用法
2022/06/21 Servers