-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathnode简单实现一个更改头像功能.html
1 lines (1 loc) · 37.7 KB
/
node简单实现一个更改头像功能.html
1
<!doctype html><html class="theme-next mist"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><meta name="google-site-verification" content="PBwskePkFkRAnqisXEBN7FyYihV0DkOHyvEC2eDt6Gg"><meta name="referrer" content="never"><script src="/lib/pace/pace.min.js?v=1.0.2"></script><link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="baidu-site-verification" content="haLEFmuOYV"><script>!function(e,t,o,c,i,a,n){e.DaoVoiceObject=i,e[i]=e[i]||function(){(e[i].q=e[i].q||[]).push(arguments)},e[i].l=1*new Date,a=t.createElement(o),n=t.getElementsByTagName(o)[0],a.async=1,a.src=c,a.charset="utf-8",n.parentNode.insertBefore(a,n)}(window,document,"script",("https:"==document.location.protocol?"https:":"http:")+"//widget.daovoice.io/widget/0f81ff2f.js","daovoice"),daovoice("init",{app_id:"0f81ff2f"}),daovoice("update")</script><link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/css/main.css?v=5.0.2" rel="stylesheet" type="text/css"><meta name="keywords" content="图片上传,更改头像"><link rel="alternate" href="/atom.xml" title="Moorez" type="application/atom+xml"><link rel="shortcut icon" type="image/x-icon" href="/images/favicon.ico?v=5.0.2"><meta name="description" content="前言一直想写这篇文章,无奈由于要考试的原因,一直在复习,拖延到现在才写🤣,之前用 node 的 express 框架写了个小项目,里面有个上传图片的功能,这里记录一下如何实现(我使用的是 ejs)📝"><meta name="keywords" content="图片上传,更改头像"><meta property="og:type" content="article"><meta property="og:title" content="node简单实现一个更改头像功能"><meta property="og:url" content="http://www.shenzekun.cn/node简单实现一个更改头像功能.html"><meta property="og:site_name" content="Moorez"><meta property="og:description" content="前言一直想写这篇文章,无奈由于要考试的原因,一直在复习,拖延到现在才写🤣,之前用 node 的 express 框架写了个小项目,里面有个上传图片的功能,这里记录一下如何实现(我使用的是 ejs)📝"><meta property="og:image" content="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/15144357069018.jpg"><meta property="og:image" content="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/2017-12-28-user-upload.gif"><meta property="og:updated_time" content="2018-10-22T02:44:10.652Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="node简单实现一个更改头像功能"><meta name="twitter:description" content="前言一直想写这篇文章,无奈由于要考试的原因,一直在复习,拖延到现在才写🤣,之前用 node 的 express 框架写了个小项目,里面有个上传图片的功能,这里记录一下如何实现(我使用的是 ejs)📝"><meta name="twitter:image" content="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/15144357069018.jpg"><script type="text/javascript" id="hexo.configuration">var NexT=window.NexT||{},CONFIG={scheme:"Mist",sidebar:{position:"left",display:"post"},fancybox:!0,motion:!1,duoshuo:{userId:"0",author:"Author"}}</script><link rel="canonical" href="http://www.shenzekun.cn/node简单实现一个更改头像功能.html"><title>node简单实现一个更改头像功能 | Moorez</title></head><body itemscope itemtype="//schema.org/WebPage" lang="zh-Hans"><div class="container one-collumn sidebar-position-left page-post-detail"><div class="headband"></div><a href="https://github.com/shenzekun" class="github-corner" aria-label="View source on Github"><svg width="92" height="92" viewBox="0 0 250 250" style="fill:#151513;color:#fff;position:absolute;top:0;border:0;right:0" aria-hidden="true"><path d="M0 0 115 115 130 115 142 142 250 250 250 0Z"></path><path d="M128.3 109C113.8 99.7 119 89.6 119 89.6 122 82.7 120.5 78.6 120.5 78.6 119.2 72 123.4 76.3 123.4 76.3 127.3 80.9 125.5 87.3 125.5 87.3 122.9 97.6 130.6 101.9 134.4 103.2" fill="currentColor" style="transform-origin:130px 106px" class="octo-arm"></path><path d="M115 115C114.9 115.1 118.7 116.5 119.8 115.4L133.7 101.6C136.9 99.2 139.9 98.4 142.2 98.6 133.8 88 127.5 74.4 143.8 58 148.5 53.4 154 51.2 159.7 51 160.3 49.4 163.2 43.6 171.4 40.1 171.4 40.1 176.1 42.5 178.8 56.2 183.1 58.6 187.2 61.8 190.9 65.4 194.5 69 197.7 73.2 200.1 77.6 213.8 80.2 216.3 84.9 216.3 84.9 212.7 93.1 206.9 96 205.4 96.6 205.1 102.4 203 107.8 198.3 112.5 181.9 128.9 168.3 122.5 157.7 114.1 157.9 116.9 156.7 120.9 152.7 124.9L141 136.5C139.8 137.7 141.6 141.9 141.8 141.8Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style><header id="header" class="header" itemscope itemtype="//schema.org/WPHeader"><div class="header-inner"><div class="site-meta"><div class="custom-logo-site-title"><a href="/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">Moorez</span><span class="logo-line-after"><i></i></span></a></div><p class="site-subtitle"></p></div><div class="site-nav-toggle"><button><span class="btn-bar"></span><span class="btn-bar"></span><span class="btn-bar"></span></button></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i><br>首页</a></li><li class="menu-item menu-item-categories"><a href="/categories" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br>分类</a></li><li class="menu-item menu-item-about"><a href="/about" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i><br>关于</a></li><li class="menu-item menu-item-archives"><a href="/archives" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br>归档</a></li><li class="menu-item menu-item-tags"><a href="/tags" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br>标签</a></li><li class="menu-item menu-item-search"><a href="javascript:;" class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br>搜索</a></li></ul><div class="site-search"><div class="popup"><span class="search-icon fa fa-search"></span> <input type="text" id="local-search-input"><div id="local-search-result"></div><span class="popup-btn-close">close</span></div></div></nav></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><div id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><link itemprop="mainEntityOfPage" href="http://www.shenzekun.cn/node简单实现一个更改头像功能.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="shenzekun"><meta itemprop="description" content=""><meta itemprop="image" content="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/avatar1.jpg"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Moorez"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">node简单实现一个更改头像功能</h1><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time itemprop="dateCreated" datetime="2017-12-28T10:23:05+08:00" content="2017-12-28">2017-12-28</time></span> <span class="post-category"> | <span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="https://schema.org/Thing"><a href="/categories/前端/" itemprop="url" rel="index"><span itemprop="name">前端</span></a></span></span> <span id="/node简单实现一个更改头像功能.html" class="leancloud_visitors" data-flag-title="node简单实现一个更改头像功能"> | <span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">热度</span><span class="leancloud-visitors-count"></span> <span>℃</span></span><div class="post-wordcount"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-file-word-o"></i></span> <span class="post-meta-item-text">字数统计</span> <span title="字数统计">638 字</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-clock-o"></i></span> <span class="post-meta-item-text">阅读时长</span> <span title="阅读时长">3 分钟</span></div></div></header><div class="post-body" itemprop="articleBody"><hr><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote><p>一直想写这篇文章,无奈由于要考试的原因,一直在复习,拖延到现在才写🤣,之前用 node 的 express 框架写了个小项目,里面有个上传图片的功能,这里记录一下如何实现(我使用的是 <strong>ejs</strong>)📝</p></blockquote><a id="more"></a><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><ol><li><p><strong>首先</strong>,当用户点击上传头像,更新头像的时候,将头像上传到项目的一个文件夹里面(<em>我是存放在项目的<code>public/images/img</code>里面</em>),并且将图像名重命名(<em>可以以时间戳来命名</em>)。<img src="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/15144357069018.jpg" alt=""></p></li><li><p><strong>同时</strong>图片在项目的路径插入到用户表的当前用户的 <code>userpicturepath</code> 里面</p></li><li>然后更新用户的 session,将图片里面的路径赋值给 session 的里面的<code>picture</code>属性里面</li><li><code><img></code> 的 <code>src</code> 获取到当前用户的session里面的 <code>picture</code> 的值,最后动态刷新页面头像就换成了用户上传的头像了</li></ol><h2 id="实现效果"><a href="#实现效果" class="headerlink" title="实现效果"></a>实现效果</h2><p><img src="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/2017-12-28-user-upload.gif" alt=""></p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><p>ejs部分</p><figure class="highlight vbscript-html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="xml"><span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">"nav-user-photo"</span> <span class="attr">src</span>=<span class="string">"</span></span></span><span class="vbscript"><%= user.picture.<span class="built_in">replace</span>(/<span class="keyword">public</span>(\/.*)/, <span class="string">"$1"</span>) %></span><span class="xml"><span class="tag"><span class="string">"</span> <span class="attr">alt</span>=<span class="string">"Photo"</span> <span class="attr">style</span>=<span class="string">"height: 40px;"</span>/></span></span></div><div class="line"></div><div class="line"><span class="tag"><<span class="name">form</span> <span class="attr">enctype</span>=<span class="string">"multipart/form-data"</span> <span class="attr">method</span>=<span class="string">"post"</span> <span class="attr">name</span>=<span class="string">"fileInfo"</span>></span></div><div class="line"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"file"</span> <span class="attr">accept</span>=<span class="string">"image/png,image/jpg"</span> <span class="attr">id</span>=<span class="string">"picUpload"</span> <span class="attr">name</span>=<span class="string">"file"</span>></span></div><div class="line"><span class="tag"></<span class="name">form</span>></span></div><div class="line"></div><div class="line"><span class="tag"><<span class="name">button</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">class</span>=<span class="string">"btn btn-primary"</span> <span class="attr">id</span>=<span class="string">"modifyPicV"</span>></span>确定<span class="tag"></<span class="name">button</span>></span></div></pre></td></tr></table></figure><p>js部分</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">document</span>.querySelector(<span class="string">'#modifyPicV'</span>).addEventListener(<span class="string">'click'</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">let</span> formData = <span class="keyword">new</span> FormData();</div><div class="line"> formData.append(<span class="string">"file"</span>,$(<span class="string">"input[name='file']"</span>)[<span class="number">0</span>].files[<span class="number">0</span>]);<span class="comment">//把文件对象插到formData对象上</span></div><div class="line"> <span class="built_in">console</span>.log(formData.get(<span class="string">'file'</span>));</div><div class="line"> $.ajax({</div><div class="line"> <span class="attr">url</span>:<span class="string">'/modifyPic'</span>,</div><div class="line"> <span class="attr">type</span>:<span class="string">'post'</span>,</div><div class="line"> <span class="attr">data</span>: formData,</div><div class="line"> <span class="attr">processData</span>: <span class="literal">false</span>, <span class="comment">// 不处理数据</span></div><div class="line"> contentType: <span class="literal">false</span>, <span class="comment">// 不设置内容类型</span></div><div class="line"> success:<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> alert(<span class="string">'success'</span>);</div><div class="line"> location.reload();</div><div class="line"> },</div><div class="line"> })</div><div class="line">});</div></pre></td></tr></table></figure><p>路由部分,使用<code>formidable</code>,这是一个Node.js模块,用于解析表单数据,尤其是文件上传</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> express = <span class="built_in">require</span>(<span class="string">'express'</span>);</div><div class="line"><span class="keyword">let</span> router = express.Router();</div><div class="line"><span class="keyword">let</span> fs = <span class="built_in">require</span>(<span class="string">'fs'</span>);</div><div class="line"><span class="keyword">let</span> {User} = <span class="built_in">require</span>(<span class="string">'../data/db'</span>);</div><div class="line"><span class="keyword">let</span> formidable = <span class="built_in">require</span>(<span class="string">'formidable'</span>);</div><div class="line"><span class="keyword">let</span> cacheFolder = <span class="string">'public/images/'</span>;<span class="comment">//放置路径</span></div><div class="line">router.post(<span class="string">'/modifyPic'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">req, res, next</span>) </span>{</div><div class="line"> <span class="keyword">let</span> userDirPath = cacheFolder + <span class="string">"Img"</span>;</div><div class="line"> <span class="keyword">if</span> (!fs.existsSync(userDirPath)) {</div><div class="line"> fs.mkdirSync(userDirPath);<span class="comment">//创建目录</span></div><div class="line"> }</div><div class="line"> <span class="keyword">let</span> form = <span class="keyword">new</span> formidable.IncomingForm(); <span class="comment">//创建上传表单</span></div><div class="line"> form.encoding = <span class="string">'utf-8'</span>; <span class="comment">//设置编码</span></div><div class="line"> form.uploadDir = userDirPath; <span class="comment">//设置上传目录</span></div><div class="line"> form.keepExtensions = <span class="literal">true</span>; <span class="comment">//保留后缀</span></div><div class="line"> form.maxFieldsSize = <span class="number">2</span> * <span class="number">1024</span> * <span class="number">1024</span>; <span class="comment">//文件大小</span></div><div class="line"> form.type = <span class="literal">true</span>;</div><div class="line"> form.parse(req, <span class="function"><span class="keyword">function</span> (<span class="params">err, fields, files</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (err) {</div><div class="line"> <span class="keyword">return</span> res.json(err);</div><div class="line"> }</div><div class="line"> <span class="keyword">let</span> extName = <span class="string">''</span>; <span class="comment">//后缀名</span></div><div class="line"> <span class="keyword">switch</span> (files.file.type) {</div><div class="line"> <span class="keyword">case</span> <span class="string">'image/pjpeg'</span>:</div><div class="line"> extName = <span class="string">'jpg'</span>;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> <span class="string">'image/jpeg'</span>:</div><div class="line"> extName = <span class="string">'jpg'</span>;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> <span class="string">'image/png'</span>:</div><div class="line"> extName = <span class="string">'png'</span>;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> <span class="string">'image/x-png'</span>:</div><div class="line"> extName = <span class="string">'png'</span>;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (extName.length === <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span> res.json({</div><div class="line"> <span class="attr">msg</span>: <span class="string">'只支持png和jpg格式图片'</span></div><div class="line"> });</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">let</span> avatarName = <span class="string">'/'</span> + <span class="built_in">Date</span>.now() + <span class="string">'.'</span> + extName;</div><div class="line"> <span class="keyword">let</span> newPath = form.uploadDir + avatarName;</div><div class="line"> fs.renameSync(files.file.path, newPath); <span class="comment">//重命名</span></div><div class="line"> <span class="built_in">console</span>.log(newPath)</div><div class="line"> <span class="comment">//更新表</span></div><div class="line"> User.update({</div><div class="line"> <span class="attr">picture</span>: newPath</div><div class="line"> }, {</div><div class="line"> <span class="attr">where</span>: {</div><div class="line"> <span class="attr">username</span>: req.session.user.username</div><div class="line"> }</div><div class="line"> }).then(<span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (data[<span class="number">0</span>] !== <span class="literal">undefined</span>) {</div><div class="line"> User.findAll({</div><div class="line"> <span class="attr">where</span>: {</div><div class="line"> <span class="attr">username</span>: req.session.user.username</div><div class="line"> }</div><div class="line"> }).then(<span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (data[<span class="number">0</span>] !== <span class="literal">undefined</span>) {</div><div class="line"> req.session.user.picture = data[<span class="number">0</span>].dataValues.picture;</div><div class="line"> res.send(<span class="literal">true</span>);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> res.send(<span class="literal">false</span>);</div><div class="line"> }</div><div class="line"> })</div><div class="line"> }</div><div class="line"> }).catch(<span class="function"><span class="keyword">function</span> (<span class="params">err</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(err);</div><div class="line"> });</div><div class="line"> }</div><div class="line"> });</div><div class="line">});</div></pre></td></tr></table></figure></div><div><div><div style="text-align:center;color:#ccc;font-size:14px">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div></div></div><div><div class="my_post_copyright"><script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script><script src="https://cdn.bootcss.com/jquery/2.0.0/jquery.min.js"></script><script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script><p><span>本文标题:</span><a href="/node简单实现一个更改头像功能.html">node简单实现一个更改头像功能</a></p><p><span>文章作者:</span><a href="/" title="访问 shenzekun 的个人博客">shenzekun</a></p><p><span>发布时间:</span>2017年12月28日 - 10:23</p><p><span>最后更新:</span>2018年10月22日 - 10:44</p><p><span>原始链接:</span><a href="/node简单实现一个更改头像功能.html" title="node简单实现一个更改头像功能">http://www.shenzekun.cn/node简单实现一个更改头像功能.html</a><span class="copy-path" title="点击复制文章链接"><i class="fa fa-clipboard" data-clipboard-text="http://www.shenzekun.cn/node简单实现一个更改头像功能.html" aria-label="复制成功!"></i></span></p><p><span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p></div><script>var clipboard=new Clipboard(".fa-clipboard");$(".fa-clipboard").click(function(){clipboard.on("success",function(){swal({title:"",text:"复制成功",icon:"success",showConfirmButton:!0})})})</script></div><div></div><div><div style="padding:10px 0;margin:20px auto;width:90%;text-align:center"><div>您的支持将鼓励我继续创作!</div><button id="rewardButton" disable="enable" onclick='var qr=document.getElementById("QR");"none"===qr.style.display?qr.style.display="block":qr.style.display="none"'><span>赏</span></button><div id="QR" style="display:none"><div id="wechat" style="display:inline-block"><img id="wechat_qr" src="/image/wechat-reward-image.png" alt="shenzekun WeChat Pay"><p>微信打赏</p></div></div></div></div><footer class="post-footer"><div class="post-tags"><a href="/tags/node/" rel="tag"><i class="fa fa-tag"></i>node</a></div><div class="post-nav"><div class="post-nav-next post-nav-item"><a href="/解决-webstrom-上的-babel-编译问题.html" rel="next" title="解决 webstrom 上的 babel 编译问题"><i class="fa fa-chevron-left"></i> 解决 webstrom 上的 babel 编译问题</a></div><div class="post-nav-prev post-nav-item"><a href="/vue全家桶与typescript使用总结.html" rel="prev" title="vue全家桶与typescript使用总结">vue全家桶与typescript使用总结<i class="fa fa-chevron-right"></i></a></div></div></footer></article><div class="post-spread"></div></div></div><div class="comments" id="comments"><div id="lv-container" data-id="city" data-uid="MTAyMC8yODgyMi81Mzky"></div></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span><span class="sidebar-toggle-line sidebar-toggle-line-middle"></span><span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">文章目录</li><li class="sidebar-nav-overview" data-target="site-overview">站点概览</li></ul><section class="site-overview sidebar-panel"><div class="site-author motion-element" itemprop="author" itemscope itemtype="//schema.org/Person"><img class="site-author-image" itemprop="image" src="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/avatar1.jpg" alt="shenzekun"><p class="site-author-name" itemprop="name">shenzekun</p><p class="site-description motion-element" itemprop="description">Road endless its long and far, I will seek up and down!</p></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"><a href="/archives"><span class="site-state-item-count">39</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"><a href="/categories"><span class="site-state-item-count">6</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"><a href="/tags"><span class="site-state-item-count">19</span> <span class="site-state-item-name">标签</span></a></div></nav><div class="feed-link motion-element"><a href="/atom.xml" rel="alternate"><i class="fa fa-rss"></i> RSS</a></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://github.com/shenzekun" target="_blank" rel="external nofollow" title="GitHub"><i class="fa fa-fw fa-github"></i> GitHub</a></span><span class="links-of-author-item"><a href="http://www.jianshu.com/u/b473784d730c" target="_blank" rel="external nofollow" title="简书"><i class="fa fa-fw fa-heartbeat"></i> 简书</a></span><span class="links-of-author-item"><a href="https://twitter.com/shenzekun" target="_blank" rel="external nofollow" title="Twitter"><i class="fa fa-fw fa-twitter"></i> Twitter</a></span><span class="links-of-author-item"><a href="https://segmentfault.com/u/juli_590dd17068b9e" target="_blank" rel="external nofollow" title="SegmentFault"><i class="fa fa-fw fa-meh-o"></i> SegmentFault</a></span><span class="links-of-author-item"><a href="http://blog.csdn.net/qq_33699981?viewmode=list" target="_blank" rel="external nofollow" title="csdn"><i class="fa fa-fw fa-crosshairs"></i> csdn</a></span><span class="links-of-author-item"><a href="https://juejin.im/user/5866ed77ac502e00612f1949" target="_blank" rel="external nofollow" title="掘金"><i class="fa fa-fw fa-spinner"></i> 掘金</a></span></div><div class="links-of-blogroll motion-element links-of-blogroll-inline"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-globe"></i> 推荐阅读</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"><a href="http://www.uisdc.com/" title="优设" target="_blank">优设</a></li><li class="links-of-blogroll-item"><a href="http://www.zhangxinxu.com/" title="张鑫旭" target="_blank">张鑫旭</a></li><li class="links-of-blogroll-item"><a href="http://www.alloyteam.com/nav/" title="Web前端导航" target="_blank">Web前端导航</a></li><li class="links-of-blogroll-item"><a href="http://www.36zhen.com/t?id=3448" title="前端书籍资料" target="_blank">前端书籍资料</a></li><li class="links-of-blogroll-item"><a href="http://ife.baidu.com/" title="百度前端技术学院" target="_blank">百度前端技术学院</a></li><li class="links-of-blogroll-item"><a href="http://wf.uisdc.com/cn/" title="google前端开发基础" target="_blank">google前端开发基础</a></li></ul></div></section><section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active"><div class="post-toc"><div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#前言"><span class="nav-number">1.</span> <span class="nav-text">前言</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#思路"><span class="nav-number">2.</span> <span class="nav-text">思路</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#实现效果"><span class="nav-number">3.</span> <span class="nav-text">实现效果</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#代码"><span class="nav-number">4.</span> <span class="nav-text">代码</span></a></li></ol></div></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright">© <span itemprop="copyrightYear">2020</span><span class="with-love"><i class="fa fa-heart"></i></span> <span class="author" itemprop="copyrightHolder">shenzekun</span></div><div class="theme-info"><i class="fa fa-pencil"></i> <span class="post-count">博客全站共 40.7k 字</span></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/js/src/utils.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/motion.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/scrollspy.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/post-details.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/bootstrap.js?v=5.0.2"></script><script type="text/javascript">!function(e,t){var n,c=e.getElementsByTagName(t)[0];"function"!=typeof LivereTower&&((n=e.createElement(t)).src="https://cdn-city.livere.com/js/embed.dist.js",n.async=!0,c.parentNode.insertBefore(n,c))}(document,"script")</script><script type="text/javascript">function proceedsearch(){$("body").append('<div class="popoverlay">').css("overflow","hidden"),$(".popup").toggle()}var isfetched=!1,search_path="search.xml";0==search_path.length&&(search_path="search.xml");var path="/"+search_path,searchFunc=function(e,t,a){"use strict";$.ajax({url:e,dataType:"xml",async:!0,success:function(e){isfetched=!0,$(".popup").detach().appendTo(".header-inner");var r=$("entry",e).map(function(){return{title:$("title",this).text(),content:$("content",this).text(),url:$("url",this).text()}}).get(),c=document.getElementById(t),n=document.getElementById(a);c.addEventListener("input",function(){var e=0,t='<ul class="search-result-list">',a=this.value.trim().toLowerCase().split(/[\s\-]+/);n.innerHTML="",this.value.trim().length>1&&r.forEach(function(r){var c=!1,n=r.title.trim().toLowerCase(),s=r.content.trim().replace(/<[^>]+>/g,"").toLowerCase(),o=decodeURIComponent(r.url),i=-1,l=-1,p=-1;if(""!=n&&a.forEach(function(e,t){i=n.indexOf(e),l=s.indexOf(e),(i>=0||l>=0)&&(c=!0,0==t&&(p=l))}),c){e+=1,t+="<li><a href='"+o+"' class='search-result-title'>"+n+"</a>";var h=r.content.trim().replace(/<[^>]+>/g,"");if(p>=0){var u=p-20,d=p+80;u<0&&(u=0),0==u&&(d=50),d>h.length&&(d=h.length);var f=h.substring(u,d);a.forEach(function(e){var t=new RegExp(e,"gi");f=f.replace(t,'<b class="search-keyword">'+e+"</b>")}),t+='<p class="search-result">'+f+"...</p>"}t+="</li>"}}),t+="</ul>",0==e&&(t='<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'),""==a&&(t='<div id="no-result"><i class="fa fa-search fa-5x" /></div>'),n.innerHTML=t}),proceedsearch()}})};$(".popup-trigger").click(function(e){e.stopPropagation(),0==isfetched?searchFunc(path,"local-search-input","local-search-result"):proceedsearch()}),$(".popup-btn-close").click(function(e){$(".popup").hide(),$(".popoverlay").remove(),$("body").css("overflow","")}),$(".popup").click(function(e){e.stopPropagation()})</script><script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script><script>AV.initialize("Cc9hxvKgB63w6aMIIBCV2Bfz-gzGzoHsz","mBmolCuukl1GN11A7m8VQj9f")</script><script>function showTime(e){var t=new AV.Query(e),n=[],o=$(".leancloud_visitors");o.each(function(){n.push($(this).attr("id").trim())}),t.containedIn("url",n),t.find().done(function(e){if(0!==e.length){for(c=0;c<e.length;c++){var t=e[c],i=t.get("url"),s=t.get("time"),l=document.getElementById(i);$(l).find(".leancloud-visitors-count").text(s)}for(var c=0;c<n.length;c++){var i=n[c],l=document.getElementById(i),r=$(l).find(".leancloud-visitors-count");""==r.text()&&r.text(0)}}else o.find(".leancloud-visitors-count").text(0)}).fail(function(e,t){console.log("Error: "+t.code+" "+t.message)})}function addCount(e){var t=$(".leancloud_visitors"),n=t.attr("id").trim(),o=t.attr("data-flag-title").trim(),i=new AV.Query(e);i.equalTo("url",n),i.find({success:function(t){if(t.length>0){var i=t[0];i.fetchWhenSave(!0),i.increment("time"),i.save(null,{success:function(e){$(document.getElementById(n)).find(".leancloud-visitors-count").text(e.get("time"))},error:function(e,t){console.log("Failed to save Visitor num, with error message: "+t.message)}})}else{var s=new e,l=new AV.ACL;l.setPublicReadAccess(!0),l.setPublicWriteAccess(!0),s.setACL(l),s.set("title",o),s.set("url",n),s.set("time",1),s.save(null,{success:function(e){$(document.getElementById(n)).find(".leancloud-visitors-count").text(e.get("time"))},error:function(e,t){console.log("Failed to create")}})}},error:function(e){console.log("Error:"+e.code+" "+e.message)}})}$(function(){var e=AV.Object.extend("Counter");1==$(".leancloud_visitors").length?addCount(e):$(".post-title-link").length>1&&showTime(e)})</script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script></body></html>