<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Yangfan&#39;s blog</title>
  <icon>https://www.gravatar.com/avatar/88c64d51c5489326f348c25c5da39c78</icon>
  <subtitle>The site of the Yangfan2016</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://yangfan.site/"/>
  <updated>2019-04-25T08:24:11.877Z</updated>
  <id>http://yangfan.site/</id>
  
  <author>
    <name>yangfan</name>
    <email>zhangh201601@gmail.com</email>
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>一次 bug 的寻找之旅</title>
    <link href="http://yangfan.site/2019/04/17/%E4%B8%80%E6%AC%A1-bug-%E7%9A%84%E5%AF%BB%E6%89%BE%E4%B9%8B%E6%97%85/"/>
    <id>http://yangfan.site/2019/04/17/一次-bug-的寻找之旅/</id>
    <published>2019-04-17T06:17:36.000Z</published>
    <updated>2019-04-25T08:24:11.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="一次-bug-的寻找之旅"><a href="#一次-bug-的寻找之旅" class="headerlink" title="一次 bug 的寻找之旅"></a>一次 bug 的寻找之旅</h2><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>在最近的一个项目中，用到了 ant-design 的 轮播图组件 <code>Carousel</code>，发现无法按照预期给每个 slide 加样式（内联样式），后来发现是 ant-design 的轮播图组件引用的三方库 <code>react-slick</code>，通过源码查找，终于发现是代码把内联样式重写了</p><h3 id="情景再现"><a href="#情景再现" class="headerlink" title="情景再现"></a>情景再现</h3><p>按照 ant-design 的官方示例，把demo拷贝过来</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; Carousel &#125; <span class="keyword">from</span> <span class="string">'antd'</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">onChange</span>(<span class="params">a, b, c</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(a, b, c);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Carousel afterChange=&#123;onChange&#125;&gt;</span><br><span class="line">    &lt;div&gt;<span class="xml"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>1<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    &lt;div&gt;<span class="xml"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>2<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    &lt;div&gt;<span class="xml"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>3<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    &lt;div&gt;<span class="xml"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>4<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  &lt;<span class="regexp">/Carousel&gt;,</span></span><br><span class="line"><span class="regexp">  mountNode</span></span><br><span class="line"><span class="regexp">);</span></span><br></pre></td></tr></table></figure><p>一切正常。然后按业务改动代码，加入背景图</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> urlBg001  <span class="keyword">from</span> <span class="string">"./images/urlBg001.png"</span>;</span><br><span class="line"><span class="keyword">import</span> urlBg002 <span class="keyword">from</span> <span class="string">"./images/urlBg002.png"</span>;</span><br><span class="line"><span class="keyword">import</span> urlBg003 <span class="keyword">from</span> <span class="string">"./images/urlBg003.png"</span>;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Carousel afterChange=&#123;onChange&#125;&gt;</span><br><span class="line">    &lt;div style=&#123;&#123; <span class="attr">backgroundImage</span>: <span class="string">`url(<span class="subst">$&#123;urlBg001&#125;</span>)`</span> &#125;&#125;&gt;<span class="xml"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>1<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    &lt;div style=&#123;&#123; <span class="attr">backgroundImage</span>: <span class="string">`url(<span class="subst">$&#123;urlBg002&#125;</span>)`</span> &#125;&#125;&gt;<span class="xml"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>2<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    &lt;div style=&#123;&#123; <span class="attr">backgroundImage</span>: <span class="string">`url(<span class="subst">$&#123;urlBg003&#125;</span>)`</span> &#125;&#125;&gt;<span class="xml"><span class="tag">&lt;<span class="name">h3</span>&gt;</span>3<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  &lt;<span class="regexp">/Carousel&gt;,</span></span><br><span class="line"><span class="regexp">  mountNode</span></span><br><span class="line"><span class="regexp">);</span></span><br></pre></td></tr></table></figure><p>然而，没有任何效果（不显示背景图）</p><h3 id="思考问题所在"><a href="#思考问题所在" class="headerlink" title="思考问题所在"></a>思考问题所在</h3><p>为何会这样呢</p><p>首先，我以为是图片路径的问题，做了个验证，发现图片正常显示</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Carousel afterChange=&#123;onChange&#125;&gt;</span><br><span class="line">    &lt;div&gt;<span class="xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#123;urlBg001&#125;</span> /&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  &lt;<span class="regexp">/Carousel&gt;,</span></span><br><span class="line"><span class="regexp">  mountNode</span></span><br><span class="line"><span class="regexp">);</span></span><br></pre></td></tr></table></figure><p>然后，我就怀疑是不是 <code>Carousel</code> 这个组件对插槽做了限制，进行了进一步的验证</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Carousel afterChange=&#123;onChange&#125;&gt;</span><br><span class="line">    &lt;div id=<span class="string">"test-slide"</span> style=&#123;</span><br><span class="line">        &#123; </span><br><span class="line">            backgroundImage: <span class="string">`url(<span class="subst">$&#123;urlBg001&#125;</span>)`</span>,</span><br><span class="line">            color:<span class="string">"#f02"</span>,</span><br><span class="line">            width:<span class="string">"50px"</span>,</span><br><span class="line">        &#125;&#125;&gt;<span class="number">1</span>&lt;<span class="regexp">/div&gt;</span></span><br><span class="line"><span class="regexp">  &lt;/</span>Carousel&gt;,</span><br><span class="line">  mountNode</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>结果，没有任何效果，打开控制台，找到 id 是 <code>test-slide</code> 的那个元素，发现渲染的结果是下面这样：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"test-slide"</span> <span class="attr">tabindex</span>=<span class="string">"-1"</span> <span class="attr">style</span>=<span class="string">"width: 100%; display: inline-block;"</span>&gt;</span>1<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p><code>style</code> 属性被重写了，我自己加的 <code>style</code> 不见了，更加确信了是 <code>Carousel</code> 组件内部搞的鬼</p><p>打开 <code>github</code> 扒 ant-design 源码，没有发现对 <code>style</code> 属性做任何更改，然后在头部找到该组件其实是引入一个 <code>react-slick</code>，然后包装了下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">// https://github.com/ant-design/ant-design/blob/master/components/carousel/index.tsx#L23</span><br><span class="line"></span><br><span class="line">const SlickCarousel = require(&quot;react-slick&quot;).default;</span><br><span class="line"></span><br><span class="line">export default class Carousel extends React.Component&lt;CarouselProps, &#123;&#125;&gt; &#123;</span><br><span class="line">  // 部分代码省略 ...</span><br><span class="line">  renderCarousel = (&#123; getPrefixCls &#125;: ConfigConsumerProps) =&gt; &#123;</span><br><span class="line">    // 部分代码省略 ...</span><br><span class="line">    return (</span><br><span class="line">      &lt;div className=&#123;className&#125;&gt;</span><br><span class="line">        &lt;SlickCarousel ref=&#123;this.saveSlick&#125; &#123;...props&#125; /&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    );</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    return &lt;ConfigConsumer&gt;&#123;this.renderCarousel&#125;&lt;/ConfigConsumer&gt;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>真相慢慢的付出了水面，再次扒 <code>react-slick</code> 的源码，终于功夫不负有心人，在这个文件里发现了问题的源头</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// https://github.com/akiran/react-slick/blob/master/src/slider.js#L184</span></span><br><span class="line"></span><br><span class="line">React.cloneElement(children[k], &#123;</span><br><span class="line">  key: <span class="number">100</span> * i + <span class="number">10</span> * j + k,</span><br><span class="line">  tabIndex: <span class="number">-1</span>,</span><br><span class="line">  style: &#123;</span><br><span class="line">    width: <span class="string">`<span class="subst">$&#123;<span class="number">100</span> <span class="regexp">/ settings.slidesPerRow&#125;%`,</span></span></span></span><br><span class="line"><span class="string"><span class="subst"><span class="regexp">    display: "inline-block"</span></span></span></span><br><span class="line"><span class="string"><span class="subst"><span class="regexp">  &#125;</span></span></span></span><br><span class="line"><span class="string"><span class="subst"><span class="regexp">&#125;)</span></span></span></span><br></pre></td></tr></table></figure><p>直接将子元素<code>children</code> 的 <code>style</code> 属性覆盖了</p><p>最后在 <code>react-slick</code> 找到了相关 <a href="https://github.com/akiran/react-slick/issues/1244" target="_blank" rel="noopener">issue</a>，然额这个 issue 仍然是 open 状态</p><p>在 PR 中找到 <a href="https://github.com/akiran/react-slick/pull/1372" target="_blank" rel="noopener">pull#1372</a>，有人尝试修复过，但是 PR 又关了，不知道什么原因</p><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><p>由于不知道源码作者为何要这么设置，我只能先找其他方法解决</p><ul><li>方法一<br>多嵌套一层，只要不是在第一层元素上操作就行</li></ul><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Carousel&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">      &lt;div style=&#123;&#123; <span class="attr">backgroundImage</span>: <span class="string">`url(<span class="subst">$&#123;logo&#125;</span>)`</span> &#125;&#125;&gt;<span class="number">1</span>&lt;<span class="regexp">/div&gt;</span></span><br><span class="line"><span class="regexp">    &lt;/</span>div&gt;</span><br><span class="line">  &lt;<span class="regexp">/Carousel&gt;,</span></span><br><span class="line"><span class="regexp">  mountNode</span></span><br><span class="line"><span class="regexp">);</span></span><br></pre></td></tr></table></figure><ul><li>方法二</li></ul><p>用其他方式达成目的</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Carousel&gt;</span><br><span class="line">    &lt;img src=&#123;logo&#125; alt=<span class="string">"001"</span>/&gt;</span><br><span class="line">  &lt;<span class="regexp">/Carousel&gt;,</span></span><br><span class="line"><span class="regexp">  mountNode</span></span><br><span class="line"><span class="regexp">);</span></span><br></pre></td></tr></table></figure><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul><li>找这个 bug 还是挺费时间的，不过，通过这次 bug 之旅，学到一定要用科学的方法，精准定位问题来源，多做空白试验参照，进行对比，这样才能更快的解决问题</li><li>一定要多看源码，可以学到很多技巧</li></ul><h3 id="备注"><a href="#备注" class="headerlink" title="备注"></a>备注</h3><p>可以点击下面的链接查看 “情景重现” 和组件源码</p><ul><li>“情景重现”<br>demo <a href="https://codesandbox.io/s/92n1x0w1my" target="_blank" rel="noopener">https://codesandbox.io/s/92n1x0w1my</a>  </li><li>源码<br>ant-design <a href="https://github.com/ant-design/ant-design/blob/master/components/carousel/index.tsx#L23" target="_blank" rel="noopener">https://github.com/ant-design/ant-design/blob/master/components/carousel/index.tsx#L23</a><br>react-slick <a href="https://github.com/akiran/react-slick/blob/master/src/slider.js#L185" target="_blank" rel="noopener">https://github.com/akiran/react-slick/blob/master/src/slider.js#L185</a>  </li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;一次-bug-的寻找之旅&quot;&gt;&lt;a href=&quot;#一次-bug-的寻找之旅&quot; class=&quot;headerlink&quot; title=&quot;一次 bug 的寻找之旅&quot;&gt;&lt;/a&gt;一次 bug 的寻找之旅&lt;/h2&gt;&lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>【译】React 函数式组件和 React 类有何不同</title>
    <link href="http://yangfan.site/2019/04/07/%E3%80%90%E8%AF%91%E3%80%91React-%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6%E5%92%8C-React-%E7%B1%BB%E6%9C%89%E4%BD%95%E4%B8%8D%E5%90%8C/"/>
    <id>http://yangfan.site/2019/04/07/【译】React-函数式组件和-React-类有何不同/</id>
    <published>2019-04-07T06:16:44.000Z</published>
    <updated>2019-04-25T08:24:11.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="React-函数式组件和-React-类有何不同？"><a href="#React-函数式组件和-React-类有何不同？" class="headerlink" title="React 函数式组件和 React 类有何不同？"></a>React 函数式组件和 React 类有何不同？</h2><blockquote><ul><li>原文地址：<a href="https://overreacted.io/how-are-function-components-different-from-classes/" target="_blank" rel="noopener">https://overreacted.io/how-are-function-components-different-from-classes/</a></li><li>原文作者：<a href="https://github.com/gaearon" target="_blank" rel="noopener">Dan Abramov</a></li><li>Markdown 地址：<a href="https://github.com/gaearon/overreacted.io/edit/master/src/pages/how-are-function-components-different-from-classes/index.md" target="_blank" rel="noopener">https://github.com/gaearon/overreacted.io/edit/master/src/pages/how-are-function-components-different-from-classes/index.md</a></li><li>译者：<a href="https://github.com/Yangfan2016" target="_blank" rel="noopener">Yangfan2016</a></li><li>英文版权所有：<a href="https://github.com/gaearon/overreacted.io/blob/master/LICENSE-posts" target="_blank" rel="noopener">Dan Abramov</a></li></ul></blockquote><p>一段时间内，权威的答案是 “类” 可以提供更多的特性的访问（比如，<code>state</code>）。而 <a href="https://reactjs.org/docs/hooks-intro.html" target="_blank" rel="noopener">Hooks</a> 就不一样了</p><p>或许你已了解到一种最佳实践。哪一种内？大多数基准测试都<a href="https://medium.com/@dan_abramov/this-benchmark-is-indeed-flawed-c3d6b5b6f97f?source=your_stories_page---------------------------" target="_blank" rel="noopener">不完美</a>，因此我得小心谨慎从它们中得出结论。性能本质上取决于代码做了什么而不是你选择函数还是类。我们观察到，它们的性能差别微不足道，尽管优化策略有些<a href="https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render" target="_blank" rel="noopener">不同</a></p><p>无论哪种情况下，我们都<a href="https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both" target="_blank" rel="noopener">不推荐</a>重写你已存在的组件，除非你有其他原因，和不介意做第一个 “吃螃蟹” 的人。<code>Hooks</code> 仍然是新概念（就像 2014 年的 React），并且那些 “最佳实践” 至今都没有在教程里找到</p><p>那么给我们留下了什么内？React 函数和类有本质的区别吗？当然，它们有（在心智模型层面上）。<strong>这篇文章，我将找到它们之间的最大的不同。</strong> 它自从 2015 的函数式组件被<a href="https://reactjs.org/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components" target="_blank" rel="noopener">引入</a>就存在了，但是它经常被忽视：</p><blockquote><p><strong>函数式组件捕获已渲染的值</strong></p></blockquote><p>让我们拆开这个概念来理解</p><hr><p><strong>注意：这篇文章并不做类或函数的价值评判。我只是描述下这两种编程模式在 React 中的不同。更多采用函数式的问题，请查阅 <a href="https://reactjs.org/docs/hooks-faq.html#adoption-strategy" target="_blank" rel="noopener">Hooks FAQ</a></strong></p><hr><p>仔细看看这个组件：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ProfilePage</span>(<span class="params">props</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> showMessage = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    alert(<span class="string">'Followed '</span> + props.user);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> handleClick = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    setTimeout(showMessage, <span class="number">3000</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    &lt;button onClick=&#123;handleClick&#125;&gt;Follow&lt;<span class="regexp">/button&gt;</span></span><br><span class="line"><span class="regexp">  );</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br></pre></td></tr></table></figure><p>它会显示一个用 <code>setTimeout</code> 模拟网络请求的按钮，并且之后会显示一个确认框。例如，如果 <code>props.user</code> 的值是 <code>&#39;Dan&#39;</code>，那么在 3 秒之后会显示 <code>&#39;Followed Dan&#39;</code>。足够简单</p><p><em>（注意，在这个例子中，不论我使用箭头函数还是声明式函数都没有关系。<code>function handleClick()</code> 都会以相同的方式正确执行）</em></p><p>我们如何用 “类” 重写内？原生翻译看起来可能是这样的：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ProfilePage</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line">  showMessage = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    alert(<span class="string">'Followed '</span> + <span class="keyword">this</span>.props.user);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  handleClick = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    setTimeout(<span class="keyword">this</span>.showMessage, <span class="number">3000</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.handleClick&#125;</span>&gt;</span>Follow<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>通常认为这两个代码片段是等价的。人们总是在这些模式进行自由的重构，而从来没有注意到它们的意义：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://overreacted.io/wtf-1d3c7a341ee3fcadc79df00e7d872e4b.gif" alt="找出两个版本的不同" title>                </div>                <div class="image-caption">找出两个版本的不同</div>            </figure><p><strong>然而，这两个代码片段只有细微的差别。</strong> 仔细看看它们，你发现不同了吗？就我个人而言，我花了一些时间才找到</p><p><strong>前方剧透，如果你要自己弄明白的话，请看这个<a href="https://codesandbox.io/s/pjqnl16lm7" target="_blank" rel="noopener">在线 demo</a></strong> ，文章的剩下的部分都在解释它们的差别和为何它如此重要</p><hr><p>在继续之前，我想强调下这篇文章描述的区别和 React Hooks 半毛钱关系都没有。甚至上面的例子里都没有提及 Hooks！</p><p>文章都是关于 React 中所有函数和 “类” 的差异。如果你计划在 React app 中更频繁的使用函数，你可能更想理解它</p><hr><p><strong>我们将用一个 React 应用中常见的 “类” bug 来图解这个区别</strong></p><p>打来这个 <strong><a href="https://codesandbox.io/s/pjqnl16lm7" target="_blank" rel="noopener">sandbox 例子</a></strong>，有一个简介选择器和两个 <code>信息页面</code>（每个都有一个关注按钮） </p><p>试着按下面的顺序触发这两个按钮：</p><ol><li><strong>单击</strong> 其中一个关注按钮  </li><li>在 3 秒过去之前 <strong>改变</strong> 已选的简介  </li><li><strong>读取</strong> 警告框的内容  </li></ol><p>你会发现一个奇怪的差异：</p><ul><li><p>使用上面的 <strong>function</strong> <code>信息页面</code> ，点击关注 Dan 的简介后，然后导航到 Sophie 的简介依然弹框显示 <code>&#39;Followed Dan&#39;</code></p></li><li><p>使用上面的 <strong>class</strong> <code>信息页面</code> ，它会弹框显示 <code>&#39;Followed Sophie&#39;</code>：</p></li></ul><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://overreacted.io/bug-386a449110202d5140d67336a0ade5a0.gif" alt="步骤示范" title>                </div>                <div class="image-caption">步骤示范</div>            </figure><hr><p>在这个例子中，第一个行为是正确的。<strong>如果我关注了一个人，然后导航到另一个人的简介页面，我的组件不应该困惑我到底关注了谁。</strong> 这个  “类” 实现明显是个 bug </p><p><em>（虽然你完全可以这样关注 <a href="https://mobile.twitter.com/sophiebits" target="_blank" rel="noopener">Sophie</a>）</em></p><hr><p>那么为何我们的 “类” 例子会如此表现内？</p><p>让我们仔细看看我们 “类” 方法 <code>showMessage</code>：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">class ProfilePage extends React.Component &#123;</span><br><span class="line">  showMessage = () =&gt; &#123;</span><br><span class="line">    alert(&apos;Followed &apos; + this.props.user);</span><br><span class="line">  &#125;;</span><br></pre></td></tr></table></figure><p>这个 “类” 方法从 <code>this.props.user</code> 读取。Props 在 React 里是不可变的，因此它们永远也不会改变。<strong>然而，<code>this</code> <em>是</em>，总是多变的</strong> </p><p>事实上，这就是 “类” 里 <code>this</code> 的全部目的。React 自己会随着时间改变，以至于你可以在 <code>render</code> 和生命周期方法获取到最新的版本</p><p>因此如果我们在请求期间重新渲染我们的组件，<code>this.props</code> 会改变。<code>showMessage</code> 方法获取到 <code>user</code> 将是 “更新的” <code>props</code></p><p>这个例子揭露出一个关于用户界面本质的有趣的观察。如果我们说 UI 概念上是当前应用状态的函数，<strong>那么事件处理器就是渲染结果的一部分（就像可视化输出一样）</strong>。我们事件处理器 “属于” 一个拥有特定 props 和 state 的特定渲染</p><p>然而，这些回调读取 <code>this.props</code> 超时会断开这个联系。我们的 <code>showMessage</code> 回调不能 “绑” 到任何特定的渲染，那么它就会 “丢失” 正确的 props。读取 <code>this</code> 的链接就会被切断  </p><hr><p><strong>我们假设函数式组件不存在。</strong> 我们该如何解决这个问题内？</p><p>我们想以某种方式 “修复” 带着正确的 props 的 <code>render</code> 和 <code>showMessage</code> 回调读取它们的联系。在某个地方，<code>props</code> 可能会丢失</p><p>一种方式是在事件处理更早读取 <code>this.props</code>，并且显示通过超时完成处理器传递进去：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">class ProfilePage extends React.Component &#123;</span><br><span class="line">  showMessage = (user) =&gt; &#123;</span><br><span class="line">    alert(&apos;Followed &apos; + user);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  handleClick = () =&gt; &#123;</span><br><span class="line">    const &#123;user&#125; = this.props;</span><br><span class="line">    setTimeout(() =&gt; this.showMessage(user), 3000);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    return &lt;button onClick=&#123;this.handleClick&#125;&gt;Follow&lt;/button&gt;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>起<a href="https://codesandbox.io/s/3q737pw8lq" target="_blank" rel="noopener">作用</a>了。然而，这种方式随着时间变化显著造成代码更冗余和容易出错。如果我们需要不止一个 prop？如果我们也需要访问这个 state？<strong>如果 <code>showMessage</code> 调用其他方法，而且这个方法也需要读取 <code>this.props.something</code> 或 <code>this.state.something</code>，我们又遇到了同样的问题。</strong> 因此我们把 <code>this.props</code> 和 <code>this.state</code> 作为参数从 <code>showMessage</code> 传递给每个它调用的方法</p><p>这么做会破坏 “类” 正常提供的工程学。它也难以记住和执行，这就是为何人们常常满足于 bug 的原因</p><p>同样，在 <code>handleClick</code> 里内嵌 <code>alert</code> 代码并不能解决更大的问题。我们想用一种方式结构化代码允许被更多方法拆分，<em>但是</em> 还是要读取调用相应渲染的 props 和 state。<strong>这个问题甚至都不是 React 独有的（你可以把这个可变对象如 <code>this</code>，放到任何一个 UI 库里都可以重现）</strong></p><p>或许，我们可以在构造器中 <em>绑定</em> 这个方法？</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">class ProfilePage extends React.Component &#123;</span><br><span class="line">  constructor(props) &#123;</span><br><span class="line">    super(props);</span><br><span class="line">    this.showMessage = this.showMessage.bind(this);</span><br><span class="line">    this.handleClick = this.handleClick.bind(this);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  showMessage() &#123;</span><br><span class="line">    alert(&apos;Followed &apos; + this.props.user);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  handleClick() &#123;</span><br><span class="line">    setTimeout(this.showMessage, 3000);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    return &lt;button onClick=&#123;this.handleClick&#125;&gt;Follow&lt;/button&gt;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>不，它不会解决任何问题。记住，问题所在是我们读取 <code>this.props</code> 太迟了（不是我们使用的语法有错！）<strong>然而，如果我们完全依赖 JavaScript 闭包可以解决这个问题</strong> </p><p>闭包总是被回避，因为它<a href="https://wsvincent.com/javascript-closure-settimeout-for-loop/" target="_blank" rel="noopener">难</a>以理解，值会随着时间变化。但是在 React 中，props 和 state 是不可变的！（或者至少，它是强烈推荐）消除了<br>闭包的主要阻碍</p><p>这意味着如果你在一个特别的渲染遮蔽了 props 或 state，你总是可以指望它们完全相同：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">class ProfilePage extends React.Component &#123;</span><br><span class="line">  render() &#123;</span><br><span class="line">    // 捕获这个 props！</span><br><span class="line">    const props = this.props;</span><br><span class="line"></span><br><span class="line">    // 注意：我们在 *render 内部*。</span><br><span class="line">    // 这些不是类方法</span><br><span class="line">    const showMessage = () =&gt; &#123;</span><br><span class="line">      alert(&apos;Followed &apos; + props.user);</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    const handleClick = () =&gt; &#123;</span><br><span class="line">      setTimeout(showMessage, 3000);</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    return &lt;button onClick=&#123;handleClick&#125;&gt;Follow&lt;/button&gt;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>你已经捕获了渲染时的 props：</strong></p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://overreacted.io/pokemon-fa483dd5699aac1350c57591770a49be.gif" alt="捕捉口袋妖怪" title>                </div>                <div class="image-caption">捕捉口袋妖怪</div>            </figure><p>这种方法，任何代码内置在它里面（包含在 <code>showMessage</code> 里），保证看到特定渲染的 props。React 不再 “移动我们的奶酪”</p><p><strong>我们可以在里面添加我们想要的任何数量的辅助函数，并且它们都将使用捕获的 prop 和 state。</strong> 闭包营救了我们！</p><hr><p><a href="https://codesandbox.io/s/oqxy9m7om5" target="_blank" rel="noopener">上面这个例子</a>是对的，但是看起来有点怪，如果你在 <code>render</code> 里定义了函数而不是使用 “类” 方法，那么在 “类” 里这么做有什么意义内？</p><p>事实上，我们可以通过移除它周围的 “壳” 来简化代码：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ProfilePage</span>(<span class="params">props</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> showMessage = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    alert(<span class="string">'Followed '</span> + props.user);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> handleClick = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    setTimeout(showMessage, <span class="number">3000</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    &lt;button onClick=&#123;handleClick&#125;&gt;Follow&lt;<span class="regexp">/button&gt;</span></span><br><span class="line"><span class="regexp">  );</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br></pre></td></tr></table></figure><p>就像上面这样，<code>props</code> 依然可以被捕获（React 把它们作为参数传递进去）。<strong>不像 <code>this</code>，<code>props</code> 对象永远不可能因 React 而发生改变</strong></p><p>如果你把函数定义里的 <code>props</code> 解构的话，会更清晰：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">function ProfilePage(&#123; user &#125;) &#123;</span><br><span class="line">  const showMessage = () =&gt; &#123;</span><br><span class="line">    alert(&apos;Followed &apos; + user);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  const handleClick = () =&gt; &#123;</span><br><span class="line">    setTimeout(showMessage, 3000);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  return (</span><br><span class="line">    &lt;button onClick=&#123;handleClick&#125;&gt;Follow&lt;/button&gt;</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当父组件携带不同的 props 渲染 <code>ProfilePage</code> 时，React 会再次调用 <code>ProfilePage</code> 函数。但是我们已经点击 “属于” 前一次渲染它自己的 <code>user</code> 的值和读取 <code>showMessage</code> 回调的那个事件处理程序。它们都原封不动</p><p>这就是为何在这个版本的 <a href="https://codesandbox.io/s/pjqnl16lm7" target="_blank" rel="noopener">demo</a> 函数中，点击关注 Sophie 的简介和改变选项到 Sunil 依然弹出 <code>&#39;Followed Sophie&#39;</code>：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://overreacted.io/fix-84396c4b3982827bead96912a947904e.gif" alt="正确行为的 demo" title>                </div>                <div class="image-caption">正确行为的 demo</div>            </figure><p>这个行为是对的。<em>（尽管你可能也想关注 <a href="https://mobile.twitter.com/threepointone" target="_blank" rel="noopener">Sunil</a>）</em></p><hr><p>现在我们就理解了 React 中 “类” 和函数的最大差别：</p><blockquote><p><strong>函数式组件捕获已渲染的值</strong></p></blockquote><p><strong>对于 Hooks，同样的原则也适用于 state。</strong> 仔细看看下面这个例子：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">MessageThread</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> [message, setMessage] = useState(<span class="string">''</span>);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> showMessage = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    alert(<span class="string">'You said: '</span> + message);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> handleSendClick = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    setTimeout(showMessage, <span class="number">3000</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> handleMessageChange = <span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">    setMessage(e.target.value);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    &lt;&gt;</span><br><span class="line">      &lt;input value=&#123;message&#125; onChange=&#123;handleMessageChange&#125; /&gt;</span><br><span class="line">      &lt;button onClick=&#123;handleSendClick&#125;&gt;Send&lt;<span class="regexp">/button&gt;</span></span><br><span class="line"><span class="regexp">    &lt;/</span>&gt;</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>（这里有一个<a href="https://codesandbox.io/s/93m5mz9w24" target="_blank" rel="noopener">在线 demo</a>）</p><p>虽然这个消息 app UI 并不是很好，但它阐述了相同的原理：如果我发送了一个特别的消息，那么组件不应该困惑发送出去的消息实际是什么。这个函数组件的 <code>message</code> 捕获了 “属于” 返回浏览器调用的点击处理程序的渲染的 state。因此，<code>message</code> 被设置为我点击 “发送” 那一时刻的输入框的值</p><hr><p>因此我们了解到 React 的函数默认捕获 props 和 state。<strong>但是如果 <em>想</em> 读取到最新的不是属于这个特定渲染的 props 或 state？</strong> 假如我们想<a href="https://dev.to/scastiel/react-hooks-get-the-current-state-back-to-the-future-3op2" target="_blank" rel="noopener">从未来读取它们</a>？</p><p>在 “类” 中，你可以通过 <code>this.props</code> 或 <code>this.state</code> 读取到，因为 <code>this</code> 本身是可变的。React 改变了它。在函数式组件里，你也可以拥有一个可变值，该值由所有组件渲染器共享。它称为 “ref”：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">MyComponent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> ref = useRef(<span class="literal">null</span>);</span><br><span class="line">  <span class="comment">// 你可以读取或设置 `ref.current`</span></span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然而，你需要自己管理它</p><p>一个 ref 扮演者和一个实例字段<a href="https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables" target="_blank" rel="noopener">相同的角色</a>。它是进入可变命令式世界的转义口。你或许对 “DOM refs” 很熟悉，但是这个概念更宽泛。它就像你放东西的盒子一样</p><p>即使在视觉上，<code>this.something</code> 看起来像是 <code>something.current</code> 的镜像。它们代表相同的概念</p><p>默认情况下，React 不会为了在函数式组件的最新 props 或 state 创建 refs。大多数情况下你不需要它们，而且给它们赋值会浪费工作。然而，如果你喜欢的话，可以手动跟踪这个值：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">function MessageThread() &#123;</span><br><span class="line">  const [message, setMessage] = useState(&apos;&apos;);</span><br><span class="line">  const latestMessage = useRef(&apos;&apos;);</span><br><span class="line"></span><br><span class="line">  const showMessage = () =&gt; &#123;</span><br><span class="line">    alert(&apos;You said: &apos; + latestMessage.current);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  const handleSendClick = () =&gt; &#123;</span><br><span class="line">    setTimeout(showMessage, 3000);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  const handleMessageChange = (e) =&gt; &#123;</span><br><span class="line">    setMessage(e.target.value);</span><br><span class="line">    latestMessage.current = e.target.value;</span><br><span class="line">  &#125;;</span><br></pre></td></tr></table></figure><p>如果我们在 <code>showMessage</code> 读取 <code>message</code>，我们会看到我们按下发送按钮时的那个消息。但是当我们读取 <code>latestMessage.current</code> 时，我们得到了最新的值（即使我们在发送按钮按下之后，仍然在打字输入）</p><p>你可以比较这<a href="https://codesandbox.io/s/93m5mz9w24" target="_blank" rel="noopener">两个</a><a href="https://codesandbox.io/s/ox200vw8k9" target="_blank" rel="noopener">例子</a>的区别。ref 是一种渲染一致性的 “选择性退出” 方法，而且在某些情况下很方便</p><p>通常，你应该避免在渲染 <em>期间</em> 读取或设置 refs，因为它们是可变的。我们想要保持渲染的可预测性。<strong>然而，如果想要得到一个特别的 prop 或 state 的最新值，手动更新 ref 可能会非常恼火。</strong> 我们可以用这个效果实现自动化：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">function MessageThread() &#123;</span><br><span class="line">  const [message, setMessage] = useState(&apos;&apos;);</span><br><span class="line"></span><br><span class="line">  // 持续跟踪最新值</span><br><span class="line">  const latestMessage = useRef(&apos;&apos;);</span><br><span class="line">  useEffect(() =&gt; &#123;</span><br><span class="line">    latestMessage.current = message;</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  const showMessage = () =&gt; &#123;</span><br><span class="line">    alert(&apos;You said: &apos; + latestMessage.current);</span><br><span class="line">  &#125;;</span><br></pre></td></tr></table></figure><p>（这有一个<a href="https://codesandbox.io/s/yqmnz7xy8x" target="_blank" rel="noopener">demo</a>）</p><p>我们在这个效果 <em>内部</em> 进行赋值，以致于 ref 值只有在 DOM 更新之后改变。这就确保了我们的改变不会打破像 [Time Slicing and Suspense] (<a href="https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html)特性，它们依赖渲染中断" target="_blank" rel="noopener">https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html)特性，它们依赖渲染中断</a></p><p>这样使用 ref  并不是经常必须的。<strong>捕获 props 或 state 还是使用默认最好。</strong> 然而，它可以方便处理像时间间隔和订阅类<a href="/making-setinterval-declarative-with-react-hooks/">命令式 API</a>。记住你可以像 this 一样跟踪 <em>任何</em> 值（prop，state 变量，整个 props 对象，或甚至一个函数）</p><p>这个模式也方便优化（例如，当 <code>useCallback</code> id 改变太频繁）。然而，<a href="https://reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down" target="_blank" rel="noopener">使用 reducer</a>通常是一个<a href="https://github.com/ryardley/hooks-perf-issues/pull/3" target="_blank" rel="noopener">更好的解决方案</a>。（后面的文章会提及到这个主题！）</p><hr><p>在这篇文章中，我们已经看到了 “类” 的常见的破坏模式，而且闭包如何帮助我们修复它。然而，你可能注意到当你试图指定的依赖数组优化 Hooks 时，你可能遇到陈旧的闭包的 bug。这么说是闭包的 “锅” 喽？我不这么认为</p><p>正如我们上面看到的那样，闭包确实帮助我们 <em>修复</em> 了很难察觉的细微问题。同样，它们也使得在<a href="https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html" target="_blank" rel="noopener">并发模式</a>正常工作的代码更容易编写。它是有可能的，因为在组件内的逻辑遮蔽了已经渲染的正确的 props 和 state</p><p>在我目前所遇到的所有情况里，<strong>“陈旧的闭包” 的问题发生是由于假设 “函数不会发生改变” 或 ”props 总是相同的“</strong> 造成的。事实并非如此，我希望通过这篇文章有助于澄清这一点</p><p>函数遮蔽了它们的 props 和 state（而且因此它们的 id 是如此重要）。这不是 bug，而是函数式组件的一个特性。对于 <code>useEffect</code> 或 <code>useCallback</code> 函数不应该把 “依赖数组” 排除。（正确的修复是通常用 <code>useReducer</code> 或 <code>useRef</code> 来解决上面的问题 - 我们会尽快出如何在它们之间进行选择的文档）</p><p>当我们在 React 写大多数函数时，我们需要调整我们关于<a href="https://github.com/ryardley/hooks-perf-issues/pull/3" target="_blank" rel="noopener">优化代码</a> 和 <a href="https://github.com/facebook/react/issues/14920" target="_blank" rel="noopener">什么值会随着时间改变</a>的直觉</p><p>正如 <a href="https://mobile.twitter.com/EphemeralCircle/status/1099095063223812096" target="_blank" rel="noopener">Fredrik</a> 所说：</p><blockquote><p>我目前在 hooks 发现的最好的心理规律就是 “代码就像任何值，任何时候都可能改变”</p></blockquote><p>函数也不例外。它需要花费一定的时间来了解 React 学习材料的常识。它需要从 “类” 中调整一些心态。但是我希望这篇文章可以帮助你刷新你的眼光</p><p>React 函数总是会捕获它们的值（现在我们知道原因了）</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://overreacted.io/pikachu-fc3bddf6d4ca14bc77917ac0cfad3608.gif" alt="微笑的皮卡丘" title>                </div>                <div class="image-caption">微笑的皮卡丘</div>            </figure><p>它们是完全不同的口袋妖怪</p><blockquote><ul><li>本文仅代表原作者个人观点，译者不发表任何观点</li><li>版权由原作者所有<br>Copyright (c) Dan Abramov and the contributors.<br>All rights reserved.</li></ul></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;React-函数式组件和-React-类有何不同？&quot;&gt;&lt;a href=&quot;#React-函数式组件和-React-类有何不同？&quot; class=&quot;headerlink&quot; title=&quot;React 函数式组件和 React 类有何不同？&quot;&gt;&lt;/a&gt;React 函数式组件
      
    
    </summary>
    
    
      <category term="翻译计划" scheme="http://yangfan.site/tags/%E7%BF%BB%E8%AF%91%E8%AE%A1%E5%88%92/"/>
    
  </entry>
  
  <entry>
    <title>Element-UI  组件 el-scrollbar 的文档</title>
    <link href="http://yangfan.site/2019/03/05/Element-UI-%E7%BB%84%E4%BB%B6-el-scrollbar-%E7%9A%84%E6%96%87%E6%A1%A3/"/>
    <id>http://yangfan.site/2019/03/05/Element-UI-组件-el-scrollbar-的文档/</id>
    <published>2019-03-05T09:09:53.000Z</published>
    <updated>2019-04-25T08:59:38.253Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Element-UI-组件-el-scrollbar-的文档"><a href="#Element-UI-组件-el-scrollbar-的文档" class="headerlink" title="Element-UI  组件 el-scrollbar 的文档"></a>Element-UI  组件 el-scrollbar 的文档</h2><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>我们在 Element-UI 的其他组件里发现，有使用这个组件，并且还不错，由于 Element-UI 官方文档并没有写到关于 <code>el-scrollbar</code> 的文档，所以稳定性上可能是有些问题，这里只是爬了源码，翻译了一些属性的使用，仅供参考</p><h3 id="快速使用"><a href="#快速使用" class="headerlink" title="快速使用"></a>快速使用</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">el-scrollbar</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"user in userList"</span> <span class="attr">:key</span>=<span class="string">"user.id"</span>&gt;</span>&#123;&#123;user.name&#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">el-scrollbar</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="具体实例"><a href="#具体实例" class="headerlink" title="具体实例"></a>具体实例</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">el-scrollbar</span></span></span><br><span class="line"><span class="tag">    <span class="attr">wrapClass</span>=<span class="string">"yf-container"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">viewClass</span>=<span class="string">"yf-content"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">wrapStyle</span>=<span class="string">"color:'#fff';fontSize:'16px';"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">viewStyle</span>=<span class="string">"color:'#fff';fontSize:'16px';"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">:native</span>=<span class="string">"false"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">:noresize</span>=<span class="string">"true"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">tag</span>=<span class="string">"ul"</span></span></span><br><span class="line"><span class="tag">&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"user in userList"</span> <span class="attr">:key</span>=<span class="string">"user.id"</span>&gt;</span>&#123;&#123;user.name&#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">el-scrollbar</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="结构构成"><a href="#结构构成" class="headerlink" title="结构构成"></a>结构构成</h3><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://user-gold-cdn.xitu.io/2019/1/21/1686f8b54408c5e2?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt="constructor" title>                </div>                <div class="image-caption">constructor</div>            </figure><h3 id="文档"><a href="#文档" class="headerlink" title="文档"></a>文档</h3><p>Attribute</p><table><thead><tr><th style="text-align:center">参数</th><th style="text-align:center">说明</th><th style="text-align:center">类型</th><th style="text-align:center">可选值</th><th style="text-align:center">默认值</th></tr></thead><tbody><tr><td style="text-align:center">wrapClass</td><td style="text-align:center">可选参数，容器的样式名</td><td style="text-align:center">string</td><td style="text-align:center">-</td><td style="text-align:center">-</td></tr><tr><td style="text-align:center">viewClass</td><td style="text-align:center">可选参数，展示视图的样式名</td><td style="text-align:center">string</td><td style="text-align:center">-</td><td style="text-align:center">-</td></tr><tr><td style="text-align:center">wrapStyle</td><td style="text-align:center">可选参数，容器的样式</td><td style="text-align:center">string</td><td style="text-align:center">-</td><td style="text-align:center">-</td></tr><tr><td style="text-align:center">viewStyle</td><td style="text-align:center">可选参数，展示视图的样式</td><td style="text-align:center">string</td><td style="text-align:center">-</td><td style="text-align:center">-</td></tr><tr><td style="text-align:center">native</td><td style="text-align:center">可选参数，是否使用原生滚动</td><td style="text-align:center">boolean</td><td style="text-align:center">-</td><td style="text-align:center">false</td></tr><tr><td style="text-align:center">noresize</td><td style="text-align:center">可选参数，容器大小是否是不可变的</td><td style="text-align:center">boolean</td><td style="text-align:center">-</td><td style="text-align:center">false</td></tr><tr><td style="text-align:center">tag</td><td style="text-align:center">可选参数，渲染容器的标签</td><td style="text-align:center">string</td><td style="text-align:center">-</td><td style="text-align:center">div</td></tr></tbody></table><h3 id="备注"><a href="#备注" class="headerlink" title="备注"></a>备注</h3><p>源码 <a href="https://github.com/ElemeFE/element/blob/dev/packages/scrollbar/src/main.js" target="_blank" rel="noopener">https://github.com/ElemeFE/element/blob/dev/packages/scrollbar/src/main.js</a>  </p><p>文章 <a href="https://juejin.im/post/5c4583eee51d4526e57d8a5a" target="_blank" rel="noopener">element ScrollBar滚动组件源码深入分析</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;Element-UI-组件-el-scrollbar-的文档&quot;&gt;&lt;a href=&quot;#Element-UI-组件-el-scrollbar-的文档&quot; class=&quot;headerlink&quot; title=&quot;Element-UI  组件 el-scrollbar 的文档&quot;
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>你所不知道的 Chrome 控制台</title>
    <link href="http://yangfan.site/2019/02/19/%E4%BD%A0%E6%89%80%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84-chrome-%E6%8E%A7%E5%88%B6%E5%8F%B0/"/>
    <id>http://yangfan.site/2019/02/19/你所不知道的-chrome-控制台/</id>
    <published>2019-02-19T07:21:25.000Z</published>
    <updated>2019-04-25T08:24:11.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="你所不知道的-Chrome-控制台调试技巧"><a href="#你所不知道的-Chrome-控制台调试技巧" class="headerlink" title="你所不知道的 Chrome 控制台调试技巧"></a>你所不知道的 Chrome 控制台调试技巧</h2><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>收集了一些工作中常用到的 Chrome 调试技巧，其他大部分 Chrome 调试功能工具介绍已经在其他的很多文章中介绍到了，这里就不 DRY 了</p><h3 id="Request-blocking-阻塞请求"><a href="#Request-blocking-阻塞请求" class="headerlink" title="Request blocking 阻塞请求"></a>Request blocking 阻塞请求</h3><p>使用这个功能可以拦截请求  </p><p>大部分情况是页面执行完某个操作后，页面就重定向了（比如登录），这时就不方便调试了，下面这个工具很好的解决了这个问题</p><p>比如你想了解在页面重定向之前，发去的登录请求都做了什么，使用操作如下图所示：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/console-reqblock-001.png" alt="console-reqblock-001" title>                </div>                <div class="image-caption">console-reqblock-001</div>            </figure><h3 id="Coverage-代码覆盖率"><a href="#Coverage-代码覆盖率" class="headerlink" title="Coverage 代码覆盖率"></a>Coverage 代码覆盖率</h3><p>可以观察到代码覆盖率，哪些是没用的，去除无用代码，较少代码体积  </p><p>你需要点击下图的记录按钮进行记录，然后你需要在页面上进行一些交互操作（如点击、鼠标移入等）</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/console-coverage-001.png" alt="console-coverage-001" title>                </div>                <div class="image-caption">console-coverage-001</div>            </figure><p>然后你会得到下图，红色的部分是没有用到的代码占比，绿色部分是用到的代码占比，你可以点击占比进度条，到达指定源代码区进行细致查看</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/console-coverage-002.png" alt="console-coverage-002" title>                </div>                <div class="image-caption">console-coverage-002</div>            </figure><h3 id="Changes-变化"><a href="#Changes-变化" class="headerlink" title="Changes 变化"></a>Changes 变化</h3><p>显示更改代码的比较，你可以通过这个工具观察，你用控制台修改过的代码，就和 git 的 diff 功能类似，红色代表删除、绿色代码新增</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/console-changes-001.png" alt="console-changes-001" title>                </div>                <div class="image-caption">console-changes-001</div>            </figure><p>你如果点击代码里的某一行，它会打开源代码面板，你可以在这里进行修改、调试操作</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/console-changes-002.png" alt="console-changes-002" title>                </div>                <div class="image-caption">console-changes-002</div>            </figure><h3 id="Snippets-代码片段"><a href="#Snippets-代码片段" class="headerlink" title="Snippets 代码片段"></a>Snippets 代码片段</h3><p>一般在 console 里可以临时运行代码，但是书写格式不太友好，而且一换行就执行了（当然你可以 shift+enter 换行），这时，你又懒癌发作，不想打开代码编辑器，你可以使用 Snippets 这个工具，如下图所示：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/console-snippets-001.png" alt="console-snippets-001" title>                </div>                <div class="image-caption">console-snippets-001</div>            </figure><p>可以像代码编辑器一样书写，可以格式化代码、可以断点调试、也可以单独导出文件</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;你所不知道的-Chrome-控制台调试技巧&quot;&gt;&lt;a href=&quot;#你所不知道的-Chrome-控制台调试技巧&quot; class=&quot;headerlink&quot; title=&quot;你所不知道的 Chrome 控制台调试技巧&quot;&gt;&lt;/a&gt;你所不知道的 Chrome 控制台调试技巧&lt;/
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>下载 Github 仓库的指定文件夹</title>
    <link href="http://yangfan.site/2019/01/23/%E4%B8%8B%E8%BD%BD-Github-%E4%BB%93%E5%BA%93%E7%9A%84%E6%8C%87%E5%AE%9A%E6%96%87%E4%BB%B6%E5%A4%B9/"/>
    <id>http://yangfan.site/2019/01/23/下载-Github-仓库的指定文件夹/</id>
    <published>2019-01-23T06:44:47.000Z</published>
    <updated>2019-04-25T08:24:11.877Z</updated>
    
    <content type="html"><![CDATA[<h3 id="下载整个仓库"><a href="#下载整个仓库" class="headerlink" title="下载整个仓库"></a>下载整个仓库</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git <span class="built_in">clone</span> https://github.com/Yangfan2016/PersonalWorks.git</span><br></pre></td></tr></table></figure><h3 id="下载仓库内的指定文件"><a href="#下载仓库内的指定文件" class="headerlink" title="下载仓库内的指定文件"></a>下载仓库内的指定文件</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">$ git init</span><br><span class="line">$ git config core.sparseCheckout <span class="literal">true</span> <span class="comment"># 配置</span></span><br><span class="line">$ git remote add -f origin https://github.com/Yangfan2016/PersonalWorks.git</span><br><span class="line">$ <span class="built_in">echo</span> <span class="string">"static-page/"</span> &gt;&gt; .git/info/sparse-checkout <span class="comment"># 写入要下载的文件目录</span></span><br><span class="line">$ <span class="built_in">echo</span> <span class="string">"web-app/"</span> &gt;&gt; .git/info/sparse-checkout</span><br><span class="line">$ git pull origin master</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;下载整个仓库&quot;&gt;&lt;a href=&quot;#下载整个仓库&quot; class=&quot;headerlink&quot; title=&quot;下载整个仓库&quot;&gt;&lt;/a&gt;下载整个仓库&lt;/h3&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutt
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>【译】深入理解 ES2015，第一趴：块作用域 let 和 const</title>
    <link href="http://yangfan.site/2019/01/15/%E3%80%90%E8%AF%91%E3%80%91%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3-ES2015%EF%BC%8C%E7%AC%AC%E4%B8%80%E8%B6%B4%EF%BC%9A%E5%9D%97%E4%BD%9C%E7%94%A8%E5%9F%9F-let-%E5%92%8C-const/"/>
    <id>http://yangfan.site/2019/01/15/【译】深入理解-ES2015，第一趴：块作用域-let-和-const/</id>
    <published>2019-01-15T09:23:17.000Z</published>
    <updated>2019-04-25T08:24:11.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="【译】深入理解-ES2015，第一趴：块作用域-let-和-const"><a href="#【译】深入理解-ES2015，第一趴：块作用域-let-和-const" class="headerlink" title="【译】深入理解 ES2015，第一趴：块作用域 let 和 const"></a>【译】深入理解 ES2015，第一趴：块作用域 let 和 const</h2><blockquote><ul><li>原文地址：<a href="http://javascriptissexy.com/understanding-es2015-in-depth-part-1-block-scope-with-let-and-const/" target="_blank" rel="noopener">http://javascriptissexy.com/understanding-es2015-in-depth-part-1-block-scope-with-let-and-const/</a></li><li>原文作者：<a href="http://javascriptissexy.com/author/dan_wellman/" target="_blank" rel="noopener">Dan Wellman</a></li><li>Markdown 地址：<a href="https://github.com/Yangfan2016/learn-translate/blob/master/2-Understanding-ES2015-In-Depth-Part-1.md" target="_blank" rel="noopener">https://github.com/Yangfan2016/learn-translate/blob/master/2-Understanding-ES2015-In-Depth-Part-1.md</a></li><li>译者：<a href="https://github.com/Yangfan2016" target="_blank" rel="noopener">Yangfan2016</a></li></ul></blockquote><hr><p>ES2015 最大的特性之一就是有了一个全新的作用域。在这个章节里，我们将开始学习什么是作用域。我们将继续学习如何创建新的作用域类型，以及给我们代码带来的好处</p><h3 id="快速了解作用域"><a href="#快速了解作用域" class="headerlink" title="快速了解作用域"></a>快速了解作用域</h3><p>作用域描述为一个变量，函数，标识符可以被访问的区域。JavaScript 传统上有两种作用域类型：全局作用域和函数作用域，你定义变量的位置会影响其他代码是否可以访问。让我们来看一个简单的例子来阐述作用域的概念。想象一下，你的 JavaScript 文件只包含以下代码：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> globalVariable = <span class="string">'This is global'</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">globalFunction1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> innerVariable1 = <span class="string">'Non-global variable 1'</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">globalFunction2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> innerVariable2 = <span class="string">'Non-global variable 2'</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在上面的代码中，我们首先声明了一个变量 <code>globalVariable</code>。这个语句不在函数内部，所以会自动存到全局作用域中。浏览器用 <code>window</code> 对象创建了一个全局作用域，除了可以用 <code>globalVariable</code> 访问，我们还可以通过挂在 <code>window</code> 对象上的 <code>window.globalVariable</code> 访问。我们可以在文件的任何地方访问这个变量，这两个函数的之前或之后，甚至是在函数的内部（这就是为什么我们说全局变量是 “隐藏的”，我们可以在任何地方正确的访问他们），甚至是在附在同一页面的其他 JavaScript 文件</p><p>在全局作用域里，我们定义了两个函数，<code>globalFunction1</code> 和 <code>globalFunction2</code>，就像全局变量一样，他们是 “可见的” 并且可以在这个文件的任何地方调用，也可以被同一页面的其他 JavaScript 文件调用。然而，当 JavaScript 引擎解析这些函数时，会分别创建他们自己的作用域。因吹斯听，这两个新的函数作用域被嵌套在全局作用域下，成为子作用域。这也就意味着函数内的代码可以访问全局变量，就像是和在函数 “内部的” 定义变量一样</p><p>当我们试图访问 JavaScript 里的标识符时，浏览器会首先在当前作用域中查找。如果没有找到，浏览器会在当前作用域的父作用域中查找，并且继续向上查找，直到找到这个变量，或者到达全局作用域为止。如果这个变量在全局作用域里依旧没有找到的话，那么浏览器会抛出一个 <code>ReferenceError</code> 错误。这种嵌套的作用域被称作作用域链，而这个检查当前作用域和父作用域的过程被称作变量查找。这种查找只会向上查找作用域链，它永远不会在它的子作用域里查找 </p><p>在上面的作用域链查找方向我们得知，例子中的 <code>innerVariable1</code> 变量只能在 <code>globalFunction1</code> 函数内部被访问，<code>innerVariable2</code> 变量只能在 <code>globalFunction2</code> 函数内部被访问。<code>innerVariable1</code> 变量不能在 <code>globalFunction2</code> 函数内部或全局作用域内被访问，<code>innerVariable2</code> 变量也不能在 <code>globalFunction1</code> 函数内部或全局作用域内被访问</p><p>下面的图片是上面代码中作用域的抽象表示：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://user-gold-cdn.xitu.io/2019/1/14/1684c6ca914e0347?w=780&h=505&f=png&s=32363" alt="js-scopes" title>                </div>                <div class="image-caption">js-scopes</div>            </figure><blockquote><h4 id="全局作用域包含了-globalVariable-以及两个内嵌的函数作用域。每个内嵌的函数作用域又包含自己的变量，但是这些变量不能被全局作用域访问。虚线表示的是作用域链的查找方向"><a href="#全局作用域包含了-globalVariable-以及两个内嵌的函数作用域。每个内嵌的函数作用域又包含自己的变量，但是这些变量不能被全局作用域访问。虚线表示的是作用域链的查找方向" class="headerlink" title="全局作用域包含了 globalVariable 以及两个内嵌的函数作用域。每个内嵌的函数作用域又包含自己的变量，但是这些变量不能被全局作用域访问。虚线表示的是作用域链的查找方向"></a>全局作用域包含了 <code>globalVariable</code> 以及两个内嵌的函数作用域。每个内嵌的函数作用域又包含自己的变量，但是这些变量不能被全局作用域访问。虚线表示的是作用域链的查找方向</h4></blockquote><p>让我们来看下另一个简短的代码示例，彻底的了解下到目前为止我们所介绍到的作用域概念。假设 JavaScript 文件只包含如下代码：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">outer</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> variable1;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">inner</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> variable2;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在这段代码里，我们在全局作用域里声明了一个叫 <code>outer</code> 的函数。因为它是一个函数，所以它创建了一个函数作用域，嵌套在全局作用域下。在这个作用域下，我们又声明了一个叫 <code>variable1</code> 的变量和 一个叫 <code>inner</code> 的函数。因为 <code>inner</code> 也是一个函数，所以一个新的作用域又被创建了，嵌套在 <code>outer</code> 函数的作用域下</p><p>在 <code>inner</code> 函数中，我们既可以访问 <code>variable2</code> 也可以访问 <code>variable1</code>。当我们在 <code>inner</code> 函数中访问 <code>variable1</code> 时，浏览器首先会在它的作用域里查找这个变量；当这个变量没有被找到时，会继续向上在父作用域里查找（也就是 <code>outer</code> 函数的作用域）。代码里作用域如下图所示：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://user-gold-cdn.xitu.io/2019/1/14/1684c6ca800aacd1?w=635&h=505&f=png&s=31601" alt="js-scopes2" title>                </div>                <div class="image-caption">js-scopes2</div>            </figure><blockquote><h4 id="函数作用域可以嵌套在其他的函数作用域里，但是作用域链查找规则是一样的，因此在-inner-作用域下可以访问到-variable1-和-variable2，但是在-outer-作用域下只能访问-variable1"><a href="#函数作用域可以嵌套在其他的函数作用域里，但是作用域链查找规则是一样的，因此在-inner-作用域下可以访问到-variable1-和-variable2，但是在-outer-作用域下只能访问-variable1" class="headerlink" title="函数作用域可以嵌套在其他的函数作用域里，但是作用域链查找规则是一样的，因此在 inner 作用域下可以访问到  variable1 和 variable2，但是在 outer 作用域下只能访问 variable1"></a>函数作用域可以嵌套在其他的函数作用域里，但是作用域链查找规则是一样的，因此在 <code>inner</code> 作用域下可以访问到  <code>variable1</code> 和 <code>variable2</code>，但是在 <code>outer</code> 作用域下只能访问 <code>variable1</code></h4></blockquote><p>这个示例中的作用域链比较长，从 <code>inner</code> 函数延伸到 <code>outer</code> 函数，直到全局对象 <code>window</code></p><h3 id="JavaScript-的新作用域"><a href="#JavaScript-的新作用域" class="headerlink" title="JavaScript 的新作用域"></a>JavaScript 的新作用域</h3><p>在 JavaScript 中，一个块是由一个或多个语句用大括号包裹起来的。诸如 <code>if</code>，<code>for</code>，<code>while</code> 的条件表达式，都是用块基于特定的条件来执行块语句</p><p>其他流行的常见的编程语言都有块作用域，JavaScript 作用域中，直到如今却只有全局作用域和函数作用域，因此使我们变得很困惑。ES2015 在 JavaScript 新增了块作用域，对于我们的代码来说有很大的影响，并且对于那些熟悉其他编程语言的开发者来说变得更直观</p><p>块作用域意味着一个块可以创建它自己的作用域，而不是简单的存在于它最近到父级函数作用域或全局作用域下。让我们在认识块作用域是如何工作的之前，先来了解下传统上块里的 JavaScript 是如何工作的：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> x = <span class="string">'function scope'</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> y = <span class="string">'not block scope'</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">innerFn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(x, y); <span class="comment">// function scope not block scope</span></span><br><span class="line">  &#125;</span><br><span class="line">  innerFn();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>var</code> 语句是不能够创建块作用域的，即使是在块里，因此 <code>console.log</code> 语句可以访问到 <code>x</code> 和 <code>y</code> 变量。 <code>fn</code> 函数创建了一个函数作用域而且 <code>x</code> 和 <code>y</code> 变量都是可以通过作用域内的作用域链访问到 </p><h3 id="声明提升"><a href="#声明提升" class="headerlink" title="声明提升"></a>声明提升</h3><p>理解提升的概念是理解 JavaScript 如何工作的基础。JavaScript 有两个阶段：解析阶段（JavaScript 引擎读取所有的代码）、执行阶段（执行已解析的代码）。大多数的事情都发生在第二阶段；例如，当你使用 <code>console.log</code> 语句时，实际的日志消息会在执行阶段打印到控制台</p><p>然而，一些重要的事情也会在解析阶段发生，包括变量的内存分配、作用域创建。提升这个术语指的是 JavaScript 引擎在遇到标识符，如变量、函数声明时所发生到事情；当发生声明提升时，它的行为就像是把它定义的字面量提升到当前作用域的顶部。鉴于此，上面到代码示例实际会变成如下情况：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> x;</span><br><span class="line">  <span class="keyword">var</span> y;</span><br><span class="line"></span><br><span class="line">  x = <span class="string">'function scope'</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">    y = <span class="string">'not block scope'</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">innerFn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(x, y); <span class="comment">// function scope not block scope</span></span><br><span class="line">  &#125;</span><br><span class="line">  innerFn();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>只有变量到声明会提升到它的作用域的顶部；在这个例子的 <code>if</code> 语句中，变量赋值依然发生在我们所赋值的地方。当然，我们到变量并不会移动，而是引擎行为表现如此，因此这样可以更好的帮助我们理解代码</p><p>除了变量，函数声明也会被提升。结果就是，从 JavaScript 引擎到角度来看，代码实际上看起来是这样的：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> x;</span><br><span class="line">  <span class="keyword">var</span> y;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">innerFn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(x, y); <span class="comment">// function scope not block scope</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  x = <span class="string">'function scope'</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">    y = <span class="string">'not block scope'</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  innerFn();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>innerFn</code> 的声明也被提升到了它的作用域的顶部。但是，记住它仅仅是函数声明被提升了，函数调用没有被提升。上面的代码并不会报任何错，因为 <code>innerFn</code> 在 <code>x</code> 和 <code>y</code> 赋值之前并没有被调用   </p><h3 id="使用-let"><a href="#使用-let" class="headerlink" title="使用 let"></a>使用 <code>let</code></h3><p>即使使用了 ES2015，<code>var</code> 声明也不会创建块作用域。为了创建块作用域，我们需要在块里使用 <code>let</code> 或 <code>const</code> 声明。我们一会再看 <code>const</code>，首先来看下 <code>let</code></p><p>表面上，<code>let</code> 和 <code>var</code>（我们用它来声明变量）的行为很相似：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> variable1;</span><br><span class="line">  <span class="keyword">let</span> variable2;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在这个简单的例子中，<code>var</code> 和 <code>let</code> 声明都做了相同的事情（在 <code>fn</code> 创建的作用域下初始化了一个新的变量）。为了创建一个新的块作用域，我们需要在块里使用 <code>let</code>：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> variable1 = <span class="string">'function scope'</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> variable2 = <span class="string">'block scope'</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="built_in">console</span>.log(variable1, variable2); <span class="comment">// Uncaught ReferenceError: variable2 is not defined</span></span><br><span class="line">&#125;</span><br><span class="line">fn();</span><br></pre></td></tr></table></figure><p>在这个代码示例中，抛出了一个引用错误（reference error）；让我们来探索下为什么会这样。<code>fn</code> 函数创建了一个新作用域，里面声明了变量 <code>variable1</code>。然后我们在 <code>if</code> 语句的块里，声明了变量 <code>variable2</code>。然而，因为我们在块里使用了 <code>let</code> 声明，因此一个新的块作用域在 <code>fn</code> 的作用域下被创建了</p><p>如果 <code>console.log</code> 语句也在 <code>if</code> 块中的话，那么它就和 <code>variable2</code> 在相同的作用域下了，也能够通过作用域链找到 <code>variable1</code>。但是因为 <code>console.log</code> 在外头，因此它不能访问 <code>variable2</code>，所以会抛出一个引用错误</p><p>块作用域和函数作用域的行为相同，但是他们是为块创建的，而不是函数</p><h3 id="暂时性死区"><a href="#暂时性死区" class="headerlink" title="暂时性死区"></a>暂时性死区</h3><p>当一个用 <code>var</code> 声明的常规变量被创建时，会被提升到它的作用域的顶部，然后并初始化一个 <code>undefined</code> 值，这样就允许我们能够在它赋值之前引用一个常规变量</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(x); <span class="comment">// undefined</span></span><br><span class="line"><span class="keyword">var</span> x = <span class="number">10</span>;</span><br></pre></td></tr></table></figure><p>记住，由于存在声明提升，代码实际看起来是这样的：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> x = <span class="literal">undefined</span>;</span><br><span class="line"><span class="built_in">console</span>.log(x); <span class="comment">// undefined</span></span><br><span class="line">x = <span class="number">10</span>;</span><br></pre></td></tr></table></figure><p>这个行为会阻止抛出引用错误 <code>ReferenceError</code></p><p>用 <code>let</code> 声明的变量也被提升了，但重要的是，他们并不会自动初始化值 <code>undefined</code>，因此意味着下面的代码会产生一个错误：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(x); <span class="comment">// Uncaught ReferenceError: x is not defined</span></span><br><span class="line"><span class="keyword">let</span> x = <span class="number">10</span>;</span><br></pre></td></tr></table></figure><p>这个错误是由暂时性死区（TDZ）引起的。TDZ 存在于作用域初始化到变量声明期间。为了修复这个错误（<code>ReferenceError</code>），我们需要在访问它前声明它：</p><blockquote><p>译者注：<a href="https://gist.github.com/rwaldron/ca35924d59ddc60a6aa165e1e4a3acda" target="_blank" rel="noopener">TDZ</a></p></blockquote><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> x;</span><br><span class="line"><span class="built_in">console</span>.log(x); <span class="comment">// undefined</span></span><br><span class="line">x = <span class="number">10</span>;</span><br></pre></td></tr></table></figure><p>TDZ 这样设计是为了使开发更容易（试图引用一个还没声明的变量通常视为一个错误，而不是故意为之），因此这个错误可以立即提醒我们</p><h3 id="使用-const"><a href="#使用-const" class="headerlink" title="使用 const"></a>使用 <code>const</code></h3><p>新的 <code>const</code> 被用来声明一个不可再次赋值的变量。它和 <code>let</code> 的在 TDZ 的行为非常相似，但是，<code>const</code> 变量必须初始化一个值</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> VAR1 = <span class="string">'constant'</span>;</span><br></pre></td></tr></table></figure><p>从现在开始， 变量 <code>VAR1</code> 的值将永远是 “constant” 这个字符串。如果我们试图再次对它赋值，我们会得到一个错误：</p><blockquote><p>TypeError: Assignment to <code>constant</code> variable</p></blockquote><p>如果我们试图创建一个没有初始化的 <code>const</code> 变量，我们将看到一个语法错误：</p><blockquote><p>SyntaxError: Missing initializer in <code>const</code> declaration</p></blockquote><p>相似地，一个 <code>const</code> 变量不能被再次声明。如果我们试图再次用 <code>const</code> 声明一个相同变量时，我们将得到一个不同类型的语法错误</p><blockquote><p>SyntaxError: Identifier ‘VAR1′ has already been declared</p></blockquote><p>和其他编程语言一样，常量是被用来保存我们的程序在生命周期里不希望改变的值</p><p>记住 <code>let</code> 和 <code>const</code> 都是 JavaScript 的保留词，因此在严格模式下，是不能被用作标识符名称的（变量名，函数名等）。随着 ES2015 越来越普遍，<code>let</code> 和 <code>const</code> 优于 <code>var</code> 已形成一个共识，因为变量创建的作用域更与其他现代编程语言看齐，并且代码的行为也更好预测。<br>因此，在大多数情况下尽可能的避免使用 <code>var</code></p><h3 id="不可变性"><a href="#不可变性" class="headerlink" title="不可变性"></a>不可变性</h3><p>用 <code>const</code> 声明的变量不能被再次赋值的，但是 <code>const</code> 声明的变量并不是完全不可变的。如果我们用对象或数组初始化了一个 <code>const</code> 变量，我们依然可以修改对象的属性和增加删除数组的元素 </p><h3 id="练习"><a href="#练习" class="headerlink" title="练习"></a>练习</h3><ol><li>在 <code>for</code> 循环里用 <code>let</code> 来初始化计数器变量  </li><li>修复下面 <code>const</code> 的错误：</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> VAR1 = <span class="string">'constant'</span>;</span><br><span class="line"><span class="keyword">const</span> VAR1 = <span class="string">'constant2'</span>;</span><br><span class="line"><span class="keyword">const</span> VAR2;</span><br><span class="line">VAR2 = <span class="string">'constant'</span>;</span><br></pre></td></tr></table></figure><blockquote><h4 id="成功是通过不断的练习和知识的积累，而非智力"><a href="#成功是通过不断的练习和知识的积累，而非智力" class="headerlink" title="成功是通过不断的练习和知识的积累，而非智力"></a>成功是通过不断的练习和知识的积累，而非智力</h4></blockquote><hr><blockquote><ul><li>本文仅代表原作者个人观点，译者不发表任何观点</li><li>Markdown 文件由译者手动整理，如有勘误，欢迎指正</li><li>译文和原文采用一样协议，侵删</li></ul></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;【译】深入理解-ES2015，第一趴：块作用域-let-和-const&quot;&gt;&lt;a href=&quot;#【译】深入理解-ES2015，第一趴：块作用域-let-和-const&quot; class=&quot;headerlink&quot; title=&quot;【译】深入理解 ES2015，第一趴：块作用
      
    
    </summary>
    
    
      <category term="翻译计划" scheme="http://yangfan.site/tags/%E7%BF%BB%E8%AF%91%E8%AE%A1%E5%88%92/"/>
    
  </entry>
  
  <entry>
    <title>快速构建一个 vue 插件</title>
    <link href="http://yangfan.site/2019/01/10/%E5%BF%AB%E9%80%9F%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA-vue-%E6%8F%92%E4%BB%B6/"/>
    <id>http://yangfan.site/2019/01/10/快速构建一个-vue-插件/</id>
    <published>2019-01-10T09:05:29.000Z</published>
    <updated>2019-04-25T08:24:11.877Z</updated>
    
    <content type="html"><![CDATA[<h3 id="碎碎念"><a href="#碎碎念" class="headerlink" title="碎碎念"></a>碎碎念</h3><p>上一篇<a href="https://juejin.im/post/5c2f248b51882525030dc50b" target="_blank" rel="noopener">文章</a>，我们介绍了如何构建一个 react 插件，今天我们说说如何构建 vue 插件</p><h3 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h3><p>由于与上一篇 react 插件文章使用的是相同的结构，代码测试、持续集成及发布 npm 包也都是一个套路，这里就不再敖述。<br>下面主要说下不同的地方，let’s start  😊</p><ol><li>开发依赖包</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">"devDependencies"</span>: &#123;</span><br><span class="line">        <span class="string">"@babel/core"</span>: <span class="string">"^7.0.0"</span>,</span><br><span class="line">        <span class="string">"@babel/preset-env"</span>: <span class="string">"^7.0.0"</span>,</span><br><span class="line">        <span class="string">"babel-loader"</span>: <span class="string">"^8.0.2"</span>,</span><br><span class="line">        <span class="string">"chai"</span>: <span class="string">"^4.2.0"</span>,</span><br><span class="line">        <span class="string">"coveralls"</span>: <span class="string">"^3.0.2"</span>,</span><br><span class="line">        <span class="string">"css-loader"</span>: <span class="string">"^1.0.0"</span>,</span><br><span class="line">        <span class="string">"jest"</span>: <span class="string">"^23.6.0"</span>,</span><br><span class="line">        <span class="string">"style-loader"</span>: <span class="string">"^0.23.1"</span>,</span><br><span class="line">        <span class="string">"vue"</span>: <span class="string">"^2.5.21"</span>,</span><br><span class="line">        <span class="string">"vue-loader"</span>: <span class="string">"^15.5.0"</span>, <span class="comment">// 解析 SFC 文件</span></span><br><span class="line">        <span class="string">"vue-style-loader"</span>: <span class="string">"^4.1.2"</span>,</span><br><span class="line">        <span class="string">"vue-template-compiler"</span>: <span class="string">"^2.5.21"</span>, <span class="comment">// vue-loader 的同步依赖 </span></span><br><span class="line">        <span class="string">"webpack"</span>: <span class="string">"^4.17.2"</span>,</span><br><span class="line">        <span class="string">"webpack-cli"</span>: <span class="string">"^3.1.0"</span></span><br><span class="line">    &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>webpack 配置</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"><span class="keyword">const</span> &#123; VueLoaderPlugin &#125; = <span class="built_in">require</span>(<span class="string">"vue-loader"</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    mode: <span class="string">"production"</span>, <span class="comment">// 生产模式</span></span><br><span class="line">    entry: &#123; <span class="comment">// 入口</span></span><br><span class="line">        <span class="string">"YanProgress"</span>: path.resolve(__dirname, <span class="string">'./src/index.js'</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    output: &#123; <span class="comment">// 出口</span></span><br><span class="line">        path: path.resolve(__dirname, <span class="string">'./dist'</span>),</span><br><span class="line">        filename: <span class="string">'[name].min.js'</span>,</span><br><span class="line">        publicPath: <span class="string">"./dist/"</span>,</span><br><span class="line">        libraryTarget: <span class="string">'umd'</span>, <span class="comment">// 按 UMD 模式打包</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="built_in">module</span>: &#123;</span><br><span class="line">        rules: [</span><br><span class="line">            &#123;</span><br><span class="line">                test: <span class="regexp">/\.vue$/</span>,</span><br><span class="line">                loader: <span class="string">'vue-loader'</span>,</span><br><span class="line">                options: &#123;</span><br><span class="line">                    <span class="comment">// 模板编译过程中，编译器可以将某些特性转换为 require 调用</span></span><br><span class="line">                    transformAssetUrls: &#123;</span><br><span class="line">                        video: [<span class="string">'src'</span>, <span class="string">'poster'</span>],</span><br><span class="line">                        source: <span class="string">'src'</span>,</span><br><span class="line">                        img: <span class="string">'src'</span>,</span><br><span class="line">                        image: <span class="string">'xlink:href'</span> <span class="comment">// SVG</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="comment">// 只命中src目录里的js文件，加快 Webpack 搜索速度</span></span><br><span class="line">                include: path.resolve(__dirname, <span class="string">"./src"</span>),</span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">                test: <span class="regexp">/\.js$/</span>,</span><br><span class="line">                use: [</span><br><span class="line">                    &#123;</span><br><span class="line">                        loader: <span class="string">'babel-loader'</span>,</span><br><span class="line">                        options: &#123;</span><br><span class="line">                            presets: [<span class="string">'@babel/preset-env'</span>]</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;,</span><br><span class="line">                ],</span><br><span class="line">                <span class="comment">// 只命中src目录里的js文件，加快 Webpack 搜索速度</span></span><br><span class="line">                include: path.resolve(__dirname, <span class="string">"./src/"</span>),</span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line"></span><br><span class="line">                test: <span class="regexp">/\.css$/</span>,</span><br><span class="line">                loader: <span class="string">"style-loader!css-loader"</span></span><br><span class="line">            &#125;</span><br><span class="line">        ]</span><br><span class="line">    &#125;,</span><br><span class="line">    plugins: [</span><br><span class="line">        <span class="comment">// vue-loader **这个插件是必须的！**它的职责是将你定义过的其它规则复制并应用到 .vue 文件里相应语言的块。</span></span><br><span class="line">        <span class="keyword">new</span> VueLoaderPlugin</span><br><span class="line">    ],</span><br><span class="line">    resolve: &#123; <span class="comment">// 省略文件后缀时，默认按下面的配置取</span></span><br><span class="line">        extensions: [<span class="string">'.js'</span>, <span class="string">'.vue'</span>],</span><br><span class="line">    &#125;,</span><br><span class="line">    externals: &#123; <span class="comment">// 不把 vue 打包进去</span></span><br><span class="line">        vue: <span class="string">'vue'</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h3 id="编写插件"><a href="#编写插件" class="headerlink" title="编写插件"></a>编写插件</h3><p>写 vue 插件稍微复杂一点 😢，根据<a href="https://cn.vuejs.org/v2/guide/plugins.html#%E5%BC%80%E5%8F%91%E6%8F%92%E4%BB%B6" target="_blank" rel="noopener">官网</a>的案例，我们需要提供一个包含 install 方法的对象或者一个函数（<a href="https://cn.vuejs.org/v2/api/#Vue-use" target="_blank" rel="noopener">传送门</a>），供 Vue.use 调用注册你的插件</p><ul><li>写法一</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Component <span class="keyword">from</span> <span class="string">'./YanProgress.vue'</span>; <span class="comment">// 这个就是你平时写的 SFC 组件</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这里要导出一个包含 install 方法的对象</span></span><br><span class="line"><span class="keyword">let</span> plugin = &#123; <span class="comment">// 这里要导出一个 install 方法</span></span><br><span class="line">    install(Vue,options) &#123; </span><br><span class="line">        <span class="comment">// 这里写你的代码，你可以全局注册组件，也可以写全局指令，也可以扩展 Vue 的方法</span></span><br><span class="line">        <span class="comment">// 1. 全局组件</span></span><br><span class="line">        Vue.component(<span class="string">'yan-progress'</span>,Component); </span><br><span class="line">        <span class="comment">// 2. 全局方法或属性</span></span><br><span class="line">        Vue.myGlobalMethod = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="comment">// 逻辑...</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 3. 全局指令</span></span><br><span class="line">        Vue.directive(<span class="string">'my-directive'</span>, &#123;</span><br><span class="line">            bind (el, binding, vnode, oldVnode) &#123;</span><br><span class="line">                <span class="comment">// 逻辑...</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">        <span class="comment">// 4. 注入组件</span></span><br><span class="line">        Vue.mixin(&#123;</span><br><span class="line">            created: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">                <span class="comment">// 逻辑...</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">        <span class="comment">// 5. 添加实例方法</span></span><br><span class="line">        Vue.prototype.$myMethod = <span class="function"><span class="keyword">function</span> (<span class="params">methodOptions</span>) </span>&#123;</span><br><span class="line">            <span class="comment">// 逻辑...</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">window</span> &amp;&amp; <span class="built_in">window</span>.Vue) &#123; <span class="comment">// 如果是渐进式开发（script 引入简单粗暴的开发方式），需要自动注册你的插件</span></span><br><span class="line">    <span class="built_in">window</span>.Vue.use(plugin);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> plugin;</span><br></pre></td></tr></table></figure><ul><li>写法二</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Component <span class="keyword">from</span> <span class="string">'./YanProgress.vue'</span>; <span class="comment">// 这个就是你平时写的 SFC 组件</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 或者这里也可以写成函数</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">plugin</span>(<span class="params">Vue,options</span>) </span>&#123; </span><br><span class="line">        <span class="comment">// 这里写你的代码，你可以全局注册组件，也可以写全局指令，也可以扩展 Vue 的方法</span></span><br><span class="line">        Vue.component(<span class="string">'yan-progress'</span>,Component); </span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">window</span> &amp;&amp; <span class="built_in">window</span>.Vue) &#123; <span class="comment">// 如果是渐进式开发（script 引入简单粗暴的开发方式），需要自动注册你的插件</span></span><br><span class="line">    <span class="built_in">window</span>.Vue.use(plugin);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> plugin;</span><br></pre></td></tr></table></figure><p>这样写的原因是，下面<a href="https://github.com/vuejs/vue/blob/dev/src/core/global-api/use.js" target="_blank" rel="noopener">源码</a>伺候😄</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">initUse</span> (<span class="params">Vue: GlobalAPI</span>) </span>&#123;</span><br><span class="line">  Vue.use = <span class="function"><span class="keyword">function</span> (<span class="params">plugin: <span class="built_in">Function</span> | <span class="built_in">Object</span></span>) </span>&#123; <span class="comment">// 在这里哦，可以传对象，也可以传函数</span></span><br><span class="line">    <span class="keyword">const</span> installedPlugins = (<span class="keyword">this</span>._installedPlugins || (<span class="keyword">this</span>._installedPlugins = []))</span><br><span class="line">    <span class="keyword">if</span> (installedPlugins.indexOf(plugin) &gt; <span class="number">-1</span>) &#123; <span class="comment">// 避免重复注册插件</span></span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">this</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// additional parameters</span></span><br><span class="line">    <span class="keyword">const</span> args = toArray(<span class="built_in">arguments</span>, <span class="number">1</span>)</span><br><span class="line">    args.unshift(<span class="keyword">this</span>)</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> plugin.install === <span class="string">'function'</span>) &#123; <span class="comment">// 如果是带有 install 方法的对象</span></span><br><span class="line">      plugin.install.apply(plugin, args) <span class="comment">// 不改变插件的 this（这里的 this 还是指向插件对象本身）</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> plugin === <span class="string">'function'</span>) &#123; <span class="comment">// 如果是函数</span></span><br><span class="line">      plugin.apply(<span class="literal">null</span>, args) <span class="comment">// 不改变插件的 this（这里应该是指向window，在浏览器非严格模式下）</span></span><br><span class="line">    &#125;</span><br><span class="line">    installedPlugins.push(plugin)</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="开源贡献"><a href="#开源贡献" class="headerlink" title="开源贡献"></a>开源贡献</h3><p>拥抱开源，这样才能让社区，乃至行业发展更有动力，哎，似曾相识的赶脚，😂</p><blockquote><p>注：例如，你的 star 是对我最大的鼓励，是支持我继续开源的动力，😄</p></blockquote><ul><li>awesome-vue 社区 <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li><li>其他社区，可以到 <code>Github</code> 探索</li></ul><h3 id="完结撒花🎉"><a href="#完结撒花🎉" class="headerlink" title="完结撒花🎉"></a>完结撒花🎉</h3><p>👏 再次欢迎大家一起和我搞 ji 由（<a href="https://github.com/Yangfan2016" target="_blank" rel="noopener">Github</a>）😊 </p><ul><li>项目地址 <a href="https://github.com/Yangfan2016/vue-yan-progress" target="_blank" rel="noopener">https://github.com/Yangfan2016/vue-yan-progress</a>   </li><li>博客原文 <a href="https://yangfan2016.github.io" target="_blank" rel="noopener">https://yangfan2016.github.io</a>  </li><li>react-yan-progress <a href="https://github.com/Yangfan2016/react-yan-progress" target="_blank" rel="noopener">https://github.com/Yangfan2016/react-yan-progress</a>  </li><li>vue-yan-progress <a href="https://github.com/Yangfan2016/vue-yan-progress" target="_blank" rel="noopener">https://github.com/Yangfan2016/vue-yan-progress</a>  </li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;碎碎念&quot;&gt;&lt;a href=&quot;#碎碎念&quot; class=&quot;headerlink&quot; title=&quot;碎碎念&quot;&gt;&lt;/a&gt;碎碎念&lt;/h3&gt;&lt;p&gt;上一篇&lt;a href=&quot;https://juejin.im/post/5c2f248b51882525030dc50b&quot; targe
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>快速构建一个 react 插件</title>
    <link href="http://yangfan.site/2019/01/04/%E5%BF%AB%E9%80%9F%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA-react-%E6%8F%92%E4%BB%B6/"/>
    <id>http://yangfan.site/2019/01/04/快速构建一个-react-插件/</id>
    <published>2019-01-04T07:21:36.000Z</published>
    <updated>2019-04-25T08:24:11.877Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>一般情况下，我们写 React 项目，用 create-react-app 脚手架开发比较方便，但是如果要写一个插件的话，用三方脚手架就显得有点臃肿了，我们可以自己配置一个符合我们开发的简单工具，本文教你如何一步一步开发一个<br>React 插件 ，let’s start  😊</p><h3 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h3><p>工欲善其事，必先利其器，我们来选型</p><ul><li>Typescript  </li></ul><p>为了方便开发，我们选用 Typescript 作为开发语言，可以即时类型检查，顺便还能装逼（巨硬大法好），</p><blockquote><p>注：<br>Typescript 可选的，你也可以选择 js 刀耕火种，不过最好还是用 Typescript 写吧，毕竟9102年了，骚年 😄</p></blockquote><ul><li>webpack + babel</li></ul><p>这里先用我们熟悉的 webpack 作为打包工具（之后会尝试改成 rollup 作为打包工具）</p><ul><li>jest + travis + coveralls</li></ul><p>jest 作为我们代码测试的工具,这里选用 travis ，一个在线持续集成的工具（帮助你打包、构建、运行scripts命令、代码测试等）<br>选用 coveralls 可以根据 travis 代码测试后生成的代码覆盖率生成 badge（Github 好多项目都有的）<br><img src="https://user-gold-cdn.xitu.io/2019/1/8/1682db589e80f715?w=90&amp;h=20&amp;f=svg&amp;s=724" alt="Build Status"></p><h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><p>下面我们来大体组织下目录结构<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">react-yan-progress</span><br><span class="line">├── build                                 // 打包目录</span><br><span class="line">│   └── YanProgress.min.js</span><br><span class="line">├── src                                   // 源码</span><br><span class="line">│   ├── index.css</span><br><span class="line">│   └── index.tsx</span><br><span class="line">├── test                                  // 测试文件</span><br><span class="line">│   └── YanProgress.test.js</span><br><span class="line">├── index.d.ts                            // 声明文件（ts）</span><br><span class="line">├── jest.config.js                        // jest 测试配置文件</span><br><span class="line">├── webpack.config.js                     // webpack 配置文件</span><br><span class="line">├── tsconfig.json                         // ts 配置文件</span><br><span class="line">├── package.json</span><br><span class="line">├── .travis.yml                           // travis 配置文件</span><br><span class="line">├── LICENSE </span><br><span class="line">└── README.md</span><br></pre></td></tr></table></figure></p><h3 id="开发者选项"><a href="#开发者选项" class="headerlink" title="开发者选项"></a>开发者选项</h3><p>所有的依赖的包如下</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">"devDependencies"</span>: &#123;</span><br><span class="line">        <span class="string">"@babel/core"</span>: <span class="string">"^7.1.6"</span>,</span><br><span class="line">        <span class="string">"@babel/preset-env"</span>: <span class="string">"^7.1.6"</span>, </span><br><span class="line">        <span class="string">"@babel/preset-react"</span>: <span class="string">"^7.0.0"</span>, <span class="comment">// for react</span></span><br><span class="line">        <span class="string">"@types/react"</span>: <span class="string">"^16.7.18"</span>, <span class="comment">// 声明文件</span></span><br><span class="line">        <span class="string">"@types/react-dom"</span>: <span class="string">"^16.0.11"</span>, <span class="comment">// 声明文件</span></span><br><span class="line">        <span class="string">"babel-loader"</span>: <span class="string">"^8.0.4"</span>,</span><br><span class="line">        <span class="string">"chai"</span>: <span class="string">"^4.2.0"</span>, <span class="comment">// 测试断言库</span></span><br><span class="line">        <span class="string">"coveralls"</span>: <span class="string">"^3.0.2"</span>, <span class="comment">// 代码覆盖率</span></span><br><span class="line">        <span class="string">"css-loader"</span>: <span class="string">"^1.0.1"</span>, </span><br><span class="line">        <span class="string">"jest"</span>: <span class="string">"^23.6.0"</span>, <span class="comment">// 测试工具</span></span><br><span class="line">        <span class="string">"react"</span>: <span class="string">"^16.7.0"</span>,</span><br><span class="line">        <span class="string">"react-dom"</span>: <span class="string">"^16.7.0"</span>,</span><br><span class="line">        <span class="string">"style-loader"</span>: <span class="string">"^0.23.1"</span>,</span><br><span class="line">        <span class="string">"ts-loader"</span>: <span class="string">"^5.3.2"</span>, <span class="comment">// 解析 ts </span></span><br><span class="line">        <span class="string">"typescript"</span>: <span class="string">"^3.2.2"</span>, <span class="comment">// 解析 ts</span></span><br><span class="line">        <span class="string">"webpack"</span>: <span class="string">"^4.25.1"</span>,</span><br><span class="line">        <span class="string">"webpack-cli"</span>: <span class="string">"^3.1.2"</span></span><br><span class="line">    &#125;      </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>命令配置如下，详情 <code>package.json</code><br><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"scripts"</span>: &#123;</span><br><span class="line">        <span class="attr">"build"</span>: <span class="string">"webpack --config webpack.config.js --progress --colors"</span>,</span><br><span class="line">        <span class="attr">"test"</span>: <span class="string">"jest ./test/YanProgress.test.js"</span>,</span><br><span class="line">        <span class="attr">"coveralls"</span>: <span class="string">"cat ./coverage/lcov.info | coveralls"</span></span><br><span class="line">    &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><h3 id="webpack-配置"><a href="#webpack-配置" class="headerlink" title="webpack 配置"></a>webpack 配置</h3><p>我们采用 webpack4 ,具体配置请看官网，<a href="https://webpack.js.org/concepts/" target="_blank" rel="noopener">传送门</a><br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">mode: <span class="string">"production"</span>, <span class="comment">// 生产模式</span></span><br><span class="line">entry: &#123; <span class="comment">// 入口</span></span><br><span class="line"><span class="string">"YanProgress"</span>: path.resolve(__dirname, <span class="string">'./src/index.tsx'</span>)</span><br><span class="line">&#125;,</span><br><span class="line">output: &#123; <span class="comment">// 出口</span></span><br><span class="line">path: path.resolve(__dirname, <span class="string">'./build'</span>),</span><br><span class="line">filename: <span class="string">'[name].min.js'</span>,</span><br><span class="line">publicPath: <span class="string">"./build/"</span>,</span><br><span class="line">libraryTarget: <span class="string">'commonjs2'</span>, <span class="comment">// 注意这里按 commonjs2 模块规范打包</span></span><br><span class="line">&#125;,</span><br><span class="line"><span class="built_in">module</span>: &#123;</span><br><span class="line">rules: [</span><br><span class="line">&#123;</span><br><span class="line">test: <span class="regexp">/\.tsx?$/</span>,</span><br><span class="line">use: [</span><br><span class="line">&#123;</span><br><span class="line">loader: <span class="string">'babel-loader'</span>,</span><br><span class="line">options: &#123;</span><br><span class="line">presets: [<span class="string">'@babel/preset-env'</span>, <span class="string">"@babel/preset-react"</span>]</span><br><span class="line">&#125;</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">loader: <span class="string">'ts-loader'</span>, <span class="comment">// 解析 ts</span></span><br><span class="line">&#125;</span><br><span class="line">],</span><br><span class="line">include: path.resolve(__dirname, <span class="string">"./src/"</span>), <span class="comment">// 只解析 src 目录下的文件</span></span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">test: <span class="regexp">/\.css$/</span>,</span><br><span class="line">loader: <span class="string">"style-loader!css-loader?modules&amp;localIdentName=[hash:8]"</span>, <span class="comment">// css_modules 配置详情  http://www.ruanyifeng.com/blog/2016/06/css_modules.html</span></span><br><span class="line">include: path.resolve(__dirname, <span class="string">"./src/"</span>),</span><br><span class="line">&#125;</span><br><span class="line">]</span><br><span class="line">&#125;,</span><br><span class="line">resolve: &#123; <span class="comment">// 省略文件后缀时，默认按下面的配置取</span></span><br><span class="line">extensions: [<span class="string">'.ts'</span>, <span class="string">'.tsx'</span>, <span class="string">'.js'</span>],</span><br><span class="line">&#125;,</span><br><span class="line">externals: &#123; <span class="comment">// 不把 react 打包进去</span></span><br><span class="line">react: <span class="string">'react'</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p><h3 id="【选读】Typescript-配置"><a href="#【选读】Typescript-配置" class="headerlink" title="【选读】Typescript 配置"></a>【选读】Typescript 配置</h3><p>由于我们要在 ts 文件中 引入 css 模块，但是 ts 不认识，所以我们需要进行如下配置</p><p>在项目的根目录下新建一个 <code>index.d.ts</code> ts 声明文件</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="keyword">module</span> '*.css';</span><br></pre></td></tr></table></figure><h3 id="开始编写插件"><a href="#开始编写插件" class="headerlink" title="开始编写插件"></a>开始编写插件</h3><p>这里就是与平常的开发组件一样，举个例子</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// jsx</span></span><br><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">YanProgress</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span></span>&#123;</span><br><span class="line">render() &#123;</span><br><span class="line"><span class="keyword">return</span> (</span><br><span class="line">&lt;div&gt;</span><br><span class="line">骚年，写代码快乐吗，看我干嘛 😄，赶快滚去写代码啊，别忘了点个 star 😂</span><br><span class="line">&lt;<span class="regexp">/div&gt;</span></span><br><span class="line"><span class="regexp">);</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">export default YanProgress; /</span><span class="regexp">/ 记得导出啊，骚年</span></span><br></pre></td></tr></table></figure><p>你可以直接看我写好的代码（然后 ctrl+c,ctrl+v），源码在这里，<a href="https://github.com/Yangfan2016/react-yan-progress/tree/master" target="_blank" rel="noopener">点我</a></p><h3 id="安装依赖及代码压缩打包"><a href="#安装依赖及代码压缩打包" class="headerlink" title="安装依赖及代码压缩打包"></a>安装依赖及代码压缩打包</h3><p>webpack4 默认会压缩代码，so 我们直接执行刚才 package.json 配置好的 scripts 的命令</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ yarn</span><br><span class="line">$ yarn run build</span><br></pre></td></tr></table></figure><h3 id="代码测试"><a href="#代码测试" class="headerlink" title="代码测试"></a>代码测试</h3><ul><li><p>单元测试<br>  可以在 <code>test</code> 目录下新建一个 <code>xxx.test.js</code> 的测试文件，写好测试用例（这里使用的是 chai 断言库的 expect 风格），执行如下命令</p>  <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ yarn run <span class="built_in">test</span></span><br></pre></td></tr></table></figure></li><li><p>包测试<br>  如果你也想以 npm 包的形式引入（<code>import YanProgress from &#39;react-yan-progress&#39;</code>），测试的话，可以执行如下命令  </p><p>  在你的项目根目录下，打开终端运行如下命令，建立链接</p>  <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ yarn link</span><br></pre></td></tr></table></figure><p>  在你要测试的 demo 项目根目录下，执行如下，然后你就可以这样使用了 <code>import YanProgress from &#39;react-yan-progress&#39;</code></p>  <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ yarn link react-yan-progress</span><br></pre></td></tr></table></figure></li></ul><h3 id="持续集成"><a href="#持续集成" class="headerlink" title="持续集成"></a>持续集成</h3><p>这里用到比较方便简单的 travis 在线测试工具，和测试代码覆盖率工具 coveralls，网址如下：<br>持续集成 <a href="https://travis-ci.org" target="_blank" rel="noopener">https://travis-ci.org</a><br>代码覆盖率  <a href="https://coveralls.io" target="_blank" rel="noopener">https://coveralls.io</a>  </p><p>注册使用过程就略过了，毕竟已经有很多教程了（面向谷歌编程 😂）</p><p>在项目根目录下新建一个 <code>.travis.yml</code> 文件，配置如下</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">language:</span> <span class="string">node_js</span> <span class="comment"># 运行环境</span></span><br><span class="line"><span class="attr">node_js:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">"10.6.0"</span> <span class="comment"># 版本</span></span><br><span class="line"><span class="attr">branches:</span></span><br><span class="line"><span class="attr">  only:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">master</span> <span class="comment"># 只有主支可以</span></span><br><span class="line"><span class="attr">before_install:</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">export</span> <span class="string">TZ='Asia/Shanghai'</span> <span class="comment"># 如果你的项目里涉及到时间处理，这里需要设置时区</span></span><br><span class="line"><span class="attr">install:</span> <span class="string">yarn</span> <span class="string">install</span> <span class="comment"># 安装 npm 包</span></span><br><span class="line"><span class="attr">script:</span> <span class="comment"># 执行命令</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">yarn</span> <span class="string">run</span> <span class="string">build</span> <span class="comment"># 打包</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">yarn</span> <span class="string">run</span> <span class="string">test</span> <span class="comment"># 测试</span></span><br><span class="line"><span class="attr">after_success:</span> <span class="comment"># 成功之后执行如下命令</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">yarn</span> <span class="string">run</span> <span class="string">coveralls</span> <span class="comment"># 测试代码覆盖率</span></span><br></pre></td></tr></table></figure><h3 id="发布-npm-包"><a href="#发布-npm-包" class="headerlink" title="发布 npm 包"></a>发布 npm 包</h3><p>注册 npm 账号，注册过程略  </p><blockquote><p>注意之前，先去 npm 官网找一下，你的包名有木有被抢先占用了</p></blockquote><p>执行如下命令进行发布<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm publish</span><br></pre></td></tr></table></figure></p><p>升级包<br>执行如下命令（x.x.x  -&gt; major.minor.patch）<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm version patch</span><br></pre></td></tr></table></figure></p><h3 id="开源贡献"><a href="#开源贡献" class="headerlink" title="开源贡献"></a>开源贡献</h3><p>拥抱开源，这样才能让社区，乃至行业发展更有动力</p><blockquote><p>注：例如，你的 star 是对我最大的鼓励，是支持我继续开源的动力</p></blockquote><ul><li>React-componets 社区 <a href="https://github.com/brillout/awesome-react-components" target="_blank" rel="noopener">awesome-react-components</a></li><li>其他社区，可以到 <code>Github</code> 探索</li></ul><h3 id="完结撒花🎉"><a href="#完结撒花🎉" class="headerlink" title="完结撒花🎉"></a>完结撒花🎉</h3><p>👏 欢迎大家一起和我搞 ji（<a href="https://github.com/Yangfan2016" target="_blank" rel="noopener">Github</a>）😊 </p><ul><li>项目地址 <a href="https://github.com/Yangfan2016/react-yan-progress#react-yan-progress" target="_blank" rel="noopener">https://github.com/Yangfan2016/react-yan-progress#react-yan-progress</a>  </li><li>博客原文 <a href="https://yangfan2016.github.io" target="_blank" rel="noopener">https://yangfan2016.github.io</a></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;一般情况下，我们写 React 项目，用 create-react-app 脚手架开发比较方便，但是如果要写一个插件的话，用三方脚手架就显得
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>You don&#39;t know cross-origin</title>
    <link href="http://yangfan.site/2018/11/19/You-don&#39;t-know-cross-origin/"/>
    <id>http://yangfan.site/2018/11/19/You-don&#39;t-know-cross-origin/</id>
    <published>2018-11-19T12:19:05.000Z</published>
    <updated>2019-04-25T08:30:47.712Z</updated>
    
    <content type="html"><![CDATA[<figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/cross-origin.png" alt="cross-origin" title>                </div>                <div class="image-caption">cross-origin</div>            </figure><h2 id="Why"><a href="#Why" class="headerlink" title="Why"></a>Why</h2><blockquote><p>为什么会存在跨域问题</p></blockquote><ul><li>同源策略<br>由于出于安全考虑，浏览器规定JavaScript不能操作其他域下的页面DOM，不能接受其他域下的xhr请求（不只是js，引用非同域下的字体文件，还有canvas引用非同域下的图片，也被同源策略所约束）<br>只要协议、域名、端口有一者不同，就被视为非同域。</li></ul><h2 id="How"><a href="#How" class="headerlink" title="How"></a>How</h2><blockquote><p>如何解决  </p></blockquote><p>要解决跨域问题，就要绕过浏览器对js的限制，另辟蹊径</p><ol><li>JSONP<br>这是最简单，也是最流行的跨域解决方案，它利用script标签不受同源策略的影响，解决跨域，需要后台配合，返回特殊格式的数据</li></ol><p>前端<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">JSONP</span>(<span class="params">link</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">let</span> script=<span class="built_in">document</span>.createElement(<span class="string">"script"</span>);</span></span><br><span class="line"><span class="undefined">        script.src=link;</span></span><br><span class="line"><span class="javascript">        <span class="built_in">document</span>.body.appendChild(script);</span></span><br><span class="line"><span class="undefined">    &#125;</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">getUser</span>(<span class="params">data</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(data);<span class="comment">// todo</span></span></span><br><span class="line"><span class="undefined">    &#125;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> API_URL_USER=<span class="string">'http://cache.video.iqiyi.com/jp/avlist/202861101/1/?callback=getUser'</span>; <span class="comment">// 这里以爱奇艺的接口为例（来源网络，侵删）</span></span></span><br><span class="line"><span class="undefined">    JSONP(API_URL_USER);</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></p><p>后端<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Express(Nodejs)</span></span><br><span class="line"><span class="comment">// mock data</span></span><br><span class="line"><span class="keyword">const</span> USERS=[</span><br><span class="line">    &#123;<span class="attr">name</span>:<span class="string">"Tom"</span>,<span class="attr">age</span>:<span class="number">23</span>&#125;,</span><br><span class="line">    &#123;<span class="attr">name</span>:<span class="string">"Jack"</span>,<span class="attr">age</span>:<span class="number">23</span>&#125;</span><br><span class="line">];</span><br><span class="line"></span><br><span class="line">app.get(<span class="string">"/user"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">req,res</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> cbName=req.query[<span class="string">"callback"</span>];</span><br><span class="line">    <span class="comment">// 这里做一个容错处理</span></span><br><span class="line">    res.send(<span class="string">`</span></span><br><span class="line"><span class="string">        try&#123;</span></span><br><span class="line"><span class="string">            <span class="subst">$&#123;cbName&#125;</span>(<span class="subst">$&#123;<span class="built_in">JSON</span>.stringify(USRES)&#125;</span>);</span></span><br><span class="line"><span class="string">        &#125;catch(ex) &#123;</span></span><br><span class="line"><span class="string">            console.error("The data is invalid");</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">    `</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p><ol start="2"><li>CORS (cross-origin resource sharing)<br>跨域资源共享，是W3C的一个标准，它允许浏览器发送跨域服务器的请求，CORS需要浏览器和服务器同时支持</li></ol><p>后端</p><p>简单请求和非简单请求详情，请阅读阮一峰老师的<a href="http://www.ruanyifeng.com/blog/2016/04/cors.html" target="_blank" rel="noopener">博文</a>，这里不再敖述<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="function"><span class="keyword">function</span> (<span class="params">req,res,next</span>)</span>&#123;</span><br><span class="line">    res.header(<span class="string">'Access-Control-Allow-Origin'</span>, <span class="string">'http://localhost:6666'</span>); <span class="comment">// 允许跨域的白名单，一般不建议使用 * 号</span></span><br><span class="line">    res.header(<span class="string">'Access-Control-Allow-Methods'</span>, <span class="string">'GET,PUT,POST,DELETE'</span>); <span class="comment">// 允许请求的方法，非简单请求，会进行预检</span></span><br><span class="line">    res.header(<span class="string">'Access-Control-Allow-Headers'</span>, <span class="string">'Content-Type'</span>); <span class="comment">// 允许请求携带的头信息，非简单请求，会进行预检</span></span><br><span class="line">    res.header(<span class="string">'Access-Control-Allow-Credentials'</span>,<span class="string">'true'</span>); <span class="comment">// 允许发送cookie，这里前端xhr也需要一起配置 `xhr.withCredentials=true`</span></span><br><span class="line">    next();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p><ol start="3"><li>代理<br>只要是在与你同域下的服务器，新建一个代理（服务端不存在同源策略），将你的跨域请求全部代理转发</li></ol><p>后端<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> proxy=<span class="built_in">require</span>(<span class="string">"http-proxy-middleware"</span>); <span class="comment">// 这里使用这个中间件完成代理</span></span><br><span class="line">app.use(<span class="string">'/api'</span>, proxy(<span class="string">"http://b.com"</span>)); <span class="comment">// http://a.com/api -&gt; http://b.com/api</span></span><br></pre></td></tr></table></figure></p><ol start="4"><li>window.name+iframe<br>MDN里解释道它是<code>获取/设置窗口的名称</code>，因为的它在不同页面甚至域名加载后值都不会改变，该属性也被用于作为 JSONP 的一个更安全的备选来提供跨域通信（cross-domain messaging）</li></ol><p>前端<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--http://a.com/page1.html--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">request</span>(<span class="params">url,callback</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">let</span> iframe=<span class="built_in">document</span>.createElement(<span class="string">"iframe"</span>);</span></span><br><span class="line"><span class="javascript">        <span class="keyword">let</span> isFirst=<span class="literal">true</span>;</span></span><br><span class="line"><span class="javascript">        iframe.style.display=<span class="string">"none"</span>;</span></span><br><span class="line"><span class="javascript">        iframe.addEventListener(<span class="string">"load"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">            <span class="keyword">if</span> (isFirst) &#123; </span></span><br><span class="line"><span class="javascript">                isFirst=<span class="literal">false</span>; <span class="comment">// 防止iframe循环加载</span></span></span><br><span class="line"><span class="javascript">                iframe.src=<span class="string">"http://a.com/page2.html"</span>;</span></span><br><span class="line"><span class="undefined">                callback &amp;&amp; callback(iframe.contentWindow.name);</span></span><br><span class="line"><span class="undefined">                iframe.remove();               </span></span><br><span class="line"><span class="undefined">            &#125;</span></span><br><span class="line"><span class="undefined">        &#125;);</span></span><br><span class="line"><span class="undefined">        iframe.src=url;</span></span><br><span class="line"><span class="undefined">    &#125;</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript">    requeset(<span class="string">"http://b.com/user"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(data); <span class="comment">// todo</span></span></span><br><span class="line"><span class="undefined">    &#125;);</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></p><p>后端<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Express(Nodejs)</span></span><br><span class="line"><span class="comment">// mock data</span></span><br><span class="line"><span class="keyword">const</span> USERS=[</span><br><span class="line">    &#123;<span class="attr">name</span>:<span class="string">"Tom"</span>,<span class="attr">age</span>:<span class="number">23</span>&#125;,</span><br><span class="line">    &#123;<span class="attr">name</span>:<span class="string">"Jack"</span>,<span class="attr">age</span>:<span class="number">23</span>&#125;</span><br><span class="line">];</span><br><span class="line"></span><br><span class="line">app.get(<span class="string">"/user"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">req,res</span>) </span>&#123;</span><br><span class="line">    res.send(<span class="string">`</span></span><br><span class="line"><span class="string">        &lt;script&gt;</span></span><br><span class="line"><span class="string">            ;window.name=<span class="subst">$&#123;<span class="built_in">JSON</span>.stringify(USERS)&#125;</span>;</span></span><br><span class="line"><span class="string">        &lt;/script&gt;</span></span><br><span class="line"><span class="string">    `</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p><ol start="5"><li><p>document.domian<br>这个使用情况有限，例如<br><a href="http://a.c.com" target="_blank" rel="noopener">http://a.c.com</a><br><a href="http://b.c.com" target="_blank" rel="noopener">http://b.c.com</a><br>主域相同时，分别设置他们页面的<code>document.domain=&quot;c.com&quot;;</code></p></li><li><p>locaction.hash+iframe<br>嵌套两层iframe，达到第一层与第三层同域，就可以互相通信了</p></li></ol><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--http://a.com/page1.html--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> iframe=<span class="built_in">document</span>.createElement(<span class="string">"iframe"</span>);</span></span><br><span class="line"><span class="javascript">    iframe.style.display=<span class="string">"none"</span>;</span></span><br><span class="line"><span class="javascript">    iframe.src=<span class="string">"http://b.com/user.html"</span>;</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="built_in">window</span>.addEventListener(<span class="string">"hashchange"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(location.hash.slice(<span class="number">1</span>)); <span class="comment">// todo</span></span></span><br><span class="line"><span class="undefined">    &#125;);</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--http://b.com/user.html--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> iframe=<span class="built_in">document</span>.createElement(<span class="string">"iframe"</span>);</span></span><br><span class="line"><span class="javascript">    iframe.style.display=<span class="string">"none"</span>;</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">getUserData</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        fetch(<span class="string">"http://b.com/user"</span>)</span></span><br><span class="line"><span class="javascript">            .then(<span class="function"><span class="params">res</span>=&gt;</span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="keyword">let</span> data=res.json();</span></span><br><span class="line"><span class="javascript">                iframe.src=<span class="string">`http://a.com/page2.html#<span class="subst">$&#123;data&#125;</span>`</span>;</span></span><br><span class="line"><span class="undefined">            &#125;);</span></span><br><span class="line"><span class="undefined">    &#125;</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined">    getUserData();</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="built_in">window</span>.addEventListener(<span class="string">"hashchange"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="undefined">        getUserData();</span></span><br><span class="line"><span class="undefined">    &#125;);</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">    top.location.hash=<span class="built_in">window</span>.location.hash;</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><ol start="7"><li>图片ping<br>这个只能发出去请求，无法获取到服务器的响应，常常用于网站流量统计</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> img=<span class="keyword">new</span> Image();</span><br><span class="line">img.addEventListener(<span class="string">"load"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"Send success"</span>); <span class="comment">// todo</span></span><br><span class="line">&#125;);</span><br><span class="line">img.src=<span class="string">"http://site.c.com/a.gif?count=666"</span>;</span><br></pre></td></tr></table></figure><ol start="8"><li>postMessage+iframe</li></ol><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- http://a.com --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">"sendBtn"</span>&gt;</span>从B接口获取用户数据<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">iframe</span> <span class="attr">src</span>=<span class="string">"http://b.com"</span> <span class="attr">id</span>=<span class="string">"ifr"</span>&gt;</span><span class="tag">&lt;/<span class="name">iframe</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript"><span class="built_in">window</span>.addEventListener(<span class="string">"message"</span>,<span class="function"><span class="keyword">function</span>(<span class="params">&#123;detail,origin&#125;</span>)</span>&#123;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">if</span> (origin===<span class="string">"http://b.com"</span>) &#123; <span class="comment">// 最好判断下消息来源</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">if</span> (detail.type===<span class="string">"set-user"</span>) &#123;</span></span><br><span class="line"><span class="javascript">            <span class="built_in">console</span>.log(detail.data); <span class="comment">// todo</span></span></span><br><span class="line"><span class="undefined">        &#125;</span></span><br><span class="line"><span class="undefined">    &#125;</span></span><br><span class="line"><span class="undefined">&#125;);</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript">sendBtn.addEventListener(<span class="string">"click"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="undefined">    ifr.contentWindow.postMessage(&#123;</span></span><br><span class="line"><span class="javascript">        type:<span class="string">"get-user"</span>,</span></span><br><span class="line"><span class="javascript">    &#125;,<span class="string">"http://b.com"</span>);</span></span><br><span class="line"><span class="undefined">&#125;);</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- http://b.com --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript"><span class="built_in">window</span>.addEventListener(<span class="string">"messagae"</span>,<span class="function"><span class="keyword">function</span>(<span class="params">&#123;detail,origin&#125;</span>)</span>&#123;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">if</span> (origin===<span class="string">"http://a.com"</span>) &#123; <span class="comment">// 最好判断下消息来源</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">if</span> (detail.type===<span class="string">"get-user"</span>) &#123;</span></span><br><span class="line"><span class="javascript">            fetch(<span class="string">"http://b.com/user"</span>)</span></span><br><span class="line"><span class="javascript">            .then(<span class="function"><span class="params">res</span>=&gt;</span>&#123;</span></span><br><span class="line"><span class="undefined">                top.contentWindow.postMessage(&#123;</span></span><br><span class="line"><span class="javascript">                    type:<span class="string">"set-user"</span>,</span></span><br><span class="line"><span class="javascript">                    data:res.json(), <span class="comment">// 假设接口返回的是json格式的数据</span></span></span><br><span class="line"><span class="javascript">                &#125;,<span class="string">"http://a.com"</span>);</span></span><br><span class="line"><span class="undefined">            &#125;)</span></span><br><span class="line"><span class="undefined">        &#125;</span></span><br><span class="line"><span class="undefined">    &#125;</span></span><br><span class="line"><span class="undefined">&#125;);</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><ol start="9"><li>postMessage+form+iframe  </li></ol><p>这个需要后台配合返回特殊格式的数据，TL,DR 可以看这个<a href="https://github.com/Yangfan2016/cross-domain/blob/master/9-iframe_form_postMessage/index.html" target="_blank" rel="noopener">demo</a></p><ol start="10"><li>WebSocket  </li></ol><p>WebSocket是一种通信协议，该协议不实行同源政策，<br>注意需要浏览器和服务器都支持的情况下</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"> <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"//cdn.bootcss.com/socket.io/1.7.2/socket.io.min.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> io = io.connect(<span class="string">'http://b.com'</span>);</span></span><br><span class="line"><span class="javascript">    io.on(<span class="string">'data'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(data); <span class="comment">// 接受来自服务器的消息</span></span></span><br><span class="line"><span class="undefined">    &#125;);</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>后端<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Nodejs</span></span><br><span class="line"><span class="keyword">const</span> server = <span class="built_in">require</span>(<span class="string">'http'</span>).createServer();</span><br><span class="line"><span class="keyword">const</span> io = <span class="built_in">require</span>(<span class="string">'socket.io'</span>)(server);</span><br><span class="line"></span><br><span class="line">io.on(<span class="string">'connection'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">client</span>) </span>&#123;</span><br><span class="line">    client.emit(<span class="string">'data'</span>, <span class="string">'This message from "http://b.com"'</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p><h2 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h2><ul><li>目前个人在工作中遇到的解决方法就是这些，当然还有许多其他的方法，你看，其实跨域并不难吧 ^_^</li><li>js通过xhr发的跨域请求，虽然得不到响应，但是可以发送出去，其实如果是单向通信的话，也可以，比如文章阅读统计，网站流量统计</li></ul><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><p><a href="http://www.ruanyifeng.com/blog/2016/04/cors.html" target="_blank" rel="noopener">跨域资源共享 CORS 详解—阮一峰</a><br><a href="https://segmentfault.com/a/1190000015597029?utm_source=tag-newest" target="_blank" rel="noopener">不要再问我跨域的问题了</a><br><a href="https://github.com/Yangfan2016/cross-domain" target="_blank" rel="noopener">FatDong1/cross-domain</a> </p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;figure class=&quot;image-bubble&quot;&gt;
                &lt;div class=&quot;img-lightbox&quot;&gt;
                    &lt;div class=&quot;overlay&quot;&gt;&lt;/div&gt;
                   
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Canvas 实现一个简单的贪吃蛇</title>
    <link href="http://yangfan.site/2018/11/15/Canvas-%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E8%B4%AA%E5%90%83%E8%9B%87/"/>
    <id>http://yangfan.site/2018/11/15/Canvas-实现一个简单的贪吃蛇/</id>
    <published>2018-11-15T05:46:49.000Z</published>
    <updated>2019-04-25T08:59:38.245Z</updated>
    
    <content type="html"><![CDATA[<h3 id="Intro"><a href="#Intro" class="headerlink" title="Intro"></a>Intro</h3><p><a href="https://yangfan2016.github.io/gluttonous-snake/" target="_blank" rel="noopener">点击预览</a><br>在之前的代码风格，和样式上做了大调整，如下图，主要是美化了移动端</p><ul><li>Before</li></ul><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/snake-game-old.png" alt="before-pc" title>                </div>                <div class="image-caption">before-pc</div>            </figure><ul><li>After</li></ul><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/snake-game.gif" alt="poster" title>                </div>                <div class="image-caption">poster</div>            </figure><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/snake-game-pc.JPG" alt="snake-game-pc" title>                </div>                <div class="image-caption">snake-game-pc</div>            </figure><h3 id="Start"><a href="#Start" class="headerlink" title="Start"></a>Start</h3><p>移动端：中间的圆点按钮是重新开始，周围的方向按钮和游戏手柄操作一样<br>web端：键盘方向键控制</p><h3 id="Technology-stack"><a href="#Technology-stack" class="headerlink" title="Technology stack"></a>Technology stack</h3><p><code>Typescript</code><br><code>rollup</code><br><code>yarn</code><br><code>canvas API</code>  </p><h3 id="Done"><a href="#Done" class="headerlink" title="Done"></a>Done</h3><ul><li>本次得分  </li><li>历史最高分   </li><li>移动端、web端适配</li></ul><h3 id="Todo"><a href="#Todo" class="headerlink" title="Todo"></a>Todo</h3><ul><li>蛇的样式美化    </li><li>游戏设置障碍物  </li></ul><h3 id="Review-and-issues"><a href="#Review-and-issues" class="headerlink" title="Review and issues"></a>Review and issues</h3><p><a href="https://github.com/Yangfan2016/gluttonous-snake" target="_blank" rel="noopener">github源码</a><br><a href="https://github.com/Yangfan2016" target="_blank" rel="noopener">关注我</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;Intro&quot;&gt;&lt;a href=&quot;#Intro&quot; class=&quot;headerlink&quot; title=&quot;Intro&quot;&gt;&lt;/a&gt;Intro&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://yangfan2016.github.io/gluttonous-snake/&quot; 
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>一个简单前端工具集-yanjs</title>
    <link href="http://yangfan.site/2018/10/14/%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E5%89%8D%E7%AB%AF%E5%B7%A5%E5%85%B7%E9%9B%86/"/>
    <id>http://yangfan.site/2018/10/14/一个简单前端工具集/</id>
    <published>2018-10-14T06:59:18.000Z</published>
    <updated>2019-04-25T09:01:25.711Z</updated>
    
    <content type="html"><![CDATA[<h2 id="一个简单前端工具集-yanjs"><a href="#一个简单前端工具集-yanjs" class="headerlink" title="一个简单前端工具集-yanjs"></a>一个简单前端工具集-yanjs</h2><blockquote><p>This is just a common toolkit for the Front End</p></blockquote><h3 id="安装使用"><a href="#安装使用" class="headerlink" title="安装使用"></a>安装使用</h3><ul><li><p>Install</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm install yanjs</span><br></pre></td></tr></table></figure></li><li><p>Example</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> yanjs = <span class="built_in">require</span>(<span class="string">'yanjs'</span>);</span><br></pre></td></tr></table></figure></li><li><p>Documentation<br><a href="https://github.com/Yangfan2016/yanjs#yanjs--" target="_blank" rel="noopener">使用文档</a></p></li></ul><h3 id="造轮子的初衷"><a href="#造轮子的初衷" class="headerlink" title="造轮子的初衷"></a>造轮子的初衷</h3><p>现在的前端发展正是百花齐放的时代，各种框架、各种库、各种插件层出不穷，为何还要重复造轮子内（毕竟大家都知道DRY，Don’t repeat yourself）：</p><ol><li>为了公司内部使用，减少三方插件的依赖</li><li>为了轻量级，加快页面的加载速度，现有业务用目前流行的工具库（如 lodash.js）使用率不是很高，并不是所有功能都用上</li><li>现在业务的技术栈主要是Vue，要进一步去除jQuery的依赖，做一个替代jQuery里部分工具函数的过渡</li><li>为了熟悉实践下前端开发的流程，学习一下如何造轮子（向轮子哥vczh致敬），提升一下自己的水平</li><li>为大前端的发展添砖加瓦，^_^</li></ol><h3 id="开发流程"><a href="#开发流程" class="headerlink" title="开发流程"></a>开发流程</h3><ul><li>开发需求<br>主要是根据平时业务中常用的总结如下需求  </li></ul><ol><li>ajax模块  </li><li>时间格式转换模块</li><li>字符串格式转换模块</li><li>cookie模块</li><li>url解析模块</li><li>浏览器模块</li></ol><ul><li>开发依赖<br>鉴于开发中常用的ajax库是axios，所以就不再重复造轮子了，简单的封装了下，cookie直接使用的是MDN封装好的docCookies</li></ul><ol><li><a href="https://www.npmjs.com/package/axios" target="_blank" rel="noopener">axios</a></li><li><a href="https://developer.mozilla.org/en-US/docs/DOM/document.cookie" target="_blank" rel="noopener">docCookies</a></li></ol><ul><li>开发环境<br>语言：Typescript 3.x<br>转换：babel 7.x<br>打包：webpack 4.x<br>测试：mocha+chai+phantomjs</li><li>发布环境<br>集成：<a href="https://travis-ci.org/Yangfan2016/yanjs" target="_blank" rel="noopener">Travis-ci</a><br>发布：<a href="https://travis-ci.org/Yangfan2016/yanjs" target="_blank" rel="noopener">npm</a><br>托管：<a href="https://github.com/Yangfan2016/yanjs" target="_blank" rel="noopener">github</a></li></ul><h3 id="开发心得"><a href="#开发心得" class="headerlink" title="开发心得"></a>开发心得</h3><ul><li><p>经历了<br>第一次用typescript编写业务代码<br>第一次发布npm包<br>第一次用mocha测试工具完成代码测试<br>第一次用Travis-ci集成工具  </p></li><li><p>结果<br>完整的体验了一次前端工程化开发，基本熟悉了整个开发流程<br>公司内部已有两个项目在使用此库，已经基本稳定</p></li></ul><h3 id="碎碎念"><a href="#碎碎念" class="headerlink" title="碎碎念"></a>碎碎念</h3><p>鄙人还在成长中，可能还有许多地方考虑不周，欢迎交流学习，欢迎提 <a href="https://github.com/Yangfan2016/yanjs/issues" target="_blank" rel="noopener">issue</a></p><p>联系我：<br>Github：<a href="https://github.com/Yangfan2016" target="_blank" rel="noopener">https://github.com/Yangfan2016</a><br>Blog： <a href="https://yangfan2016.github.io/" target="_blank" rel="noopener">https://yangfan2016.github.io/</a><br>Segmentfault：<a href="https://segmentfault.com/u/yangfan2016" target="_blank" rel="noopener">https://segmentfault.com/u/yangfan2016</a>  </p><p>大佬，点了<a href="https://github.com/Yangfan2016/yanjs" target="_blank" rel="noopener">star</a>再走呗，^_^</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;一个简单前端工具集-yanjs&quot;&gt;&lt;a href=&quot;#一个简单前端工具集-yanjs&quot; class=&quot;headerlink&quot; title=&quot;一个简单前端工具集-yanjs&quot;&gt;&lt;/a&gt;一个简单前端工具集-yanjs&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;This 
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>浅析js中的位运算及应用</title>
    <link href="http://yangfan.site/2018/09/23/%E6%B5%85%E6%9E%90js%E4%B8%AD%E7%9A%84%E4%BD%8D%E8%BF%90%E7%AE%97%E5%8F%8A%E5%BA%94%E7%94%A8/"/>
    <id>http://yangfan.site/2018/09/23/浅析js中的位运算及应用/</id>
    <published>2018-09-23T12:47:47.000Z</published>
    <updated>2019-04-25T09:01:02.777Z</updated>
    
    <content type="html"><![CDATA[<h1 id="浅析js中的位运算及应用"><a href="#浅析js中的位运算及应用" class="headerlink" title="浅析js中的位运算及应用"></a>浅析js中的位运算及应用</h1><h2 id="Example"><a href="#Example" class="headerlink" title="Example"></a>Example</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 关于2的倍数的乘法除法</span></span><br><span class="line"><span class="number">4</span>&gt;&gt;<span class="number">1</span> <span class="comment">// 4/Math.pow(2,1) === 2</span></span><br><span class="line"><span class="number">2</span>&lt;&lt;<span class="number">2</span> <span class="comment">// 2*Math.pow(2,2) === 8</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 取整</span></span><br><span class="line"><span class="number">3.14</span>|<span class="number">0</span> <span class="comment">// 3</span></span><br><span class="line"><span class="number">3.14</span>^<span class="number">0</span> <span class="comment">// 3</span></span><br><span class="line"><span class="number">3.14</span>&amp;<span class="number">3</span> <span class="comment">// 3</span></span><br><span class="line">~~<span class="number">3.14</span> <span class="comment">// 3</span></span><br><span class="line"><span class="number">3.14</span>&gt;&gt;<span class="number">0</span> <span class="comment">// Math.floor(3/Math.pow(2,0)) === 3</span></span><br><span class="line"><span class="number">3.14</span>&lt;&lt;<span class="number">0</span> <span class="comment">// Math.floor(3*Math.pow(2,0)) === 3</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 不借助第三个变量下交换两数</span></span><br><span class="line"><span class="keyword">let</span> a=<span class="number">1</span>,</span><br><span class="line">    b=<span class="number">2</span>;</span><br><span class="line">a^=b;</span><br><span class="line">b^=a;</span><br><span class="line">a^=b;</span><br><span class="line"><span class="comment">// a === 2,b === 1</span></span><br></pre></td></tr></table></figure><h2 id="Concept"><a href="#Concept" class="headerlink" title="Concept"></a>Concept</h2><h3 id="位运算符"><a href="#位运算符" class="headerlink" title="位运算符"></a>位运算符</h3><p><code>|</code> 或 只要有一个为1，就为1<br><code>&amp;</code> 与  只有都是1的情况，才为1<br><code>^</code> 异或  相同为0，不同为1<br><code>~</code> 否  取反<br><code>&lt;&lt;</code> 左移 向左移动指定位数，尾部补0<br><code>&gt;&gt;</code> 右移 向右移动指定位数，首部补0<br><code>&gt;&gt;&gt;</code> 带符号右移</p><h2 id="Convert"><a href="#Convert" class="headerlink" title="Convert"></a>Convert</h2><p>Demical</p><p>规则 逢十进一<br>基数 10<br>数码 0-9<br>位权 10^n-1</p><p>举例</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 转10进制</span></span><br><span class="line"><span class="number">100</span>D === <span class="number">1</span>*<span class="number">10</span>^<span class="number">2</span>+<span class="number">0</span>*<span class="number">10</span>^<span class="number">1</span>+<span class="number">0</span>*<span class="number">10</span>^<span class="number">0</span></span><br></pre></td></tr></table></figure><hr><p>Binary</p><p>规则 逢二进一<br>基数 2<br>数码 0-1<br>位权 2^n-1</p><p>举例</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 转10进制</span></span><br><span class="line"><span class="number">100</span>B === <span class="number">1</span>*<span class="number">2</span>^<span class="number">2</span>+<span class="number">0</span>*<span class="number">2</span>^<span class="number">1</span>+<span class="number">0</span>*<span class="number">2</span>^<span class="number">0</span></span><br></pre></td></tr></table></figure><hr><p>Octal</p><p>规则 逢八进一<br>基数 8<br>数码 0-7<br>位权 8^n-1</p><p>举例</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 转10进制</span></span><br><span class="line"><span class="number">100</span>O === <span class="number">1</span>*<span class="number">8</span>^<span class="number">2</span>+<span class="number">0</span>*<span class="number">8</span>^<span class="number">1</span>+<span class="number">0</span>*<span class="number">8</span>^<span class="number">0</span></span><br></pre></td></tr></table></figure><hr><p>Hex</p><p>规则 逢十六进一<br>基数 16<br>数码 0-9,a-f<br>位权 16^n-1</p><p>举例</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 转10进制</span></span><br><span class="line"><span class="number">100</span>H === <span class="number">1</span>*<span class="number">16</span>^<span class="number">2</span>+<span class="number">0</span>*<span class="number">16</span>^<span class="number">1</span>+<span class="number">0</span>*<span class="number">16</span>^<span class="number">0</span></span><br></pre></td></tr></table></figure><hr><p>Decaimal convert to others</p><p>短除法</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D220/sign=5db6d89b81cb39dbc5c06054e01709a7/728da9773912b31b302371588618367adab4e170.jpg" alt="短除法" title>                </div>                <div class="image-caption">短除法</div>            </figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">6D -&gt; 110B</span><br><span class="line">9D -&gt; 11O</span><br><span class="line">17D -&gt; 11H</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;浅析js中的位运算及应用&quot;&gt;&lt;a href=&quot;#浅析js中的位运算及应用&quot; class=&quot;headerlink&quot; title=&quot;浅析js中的位运算及应用&quot;&gt;&lt;/a&gt;浅析js中的位运算及应用&lt;/h1&gt;&lt;h2 id=&quot;Example&quot;&gt;&lt;a href=&quot;#Exampl
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Javascript 继承</title>
    <link href="http://yangfan.site/2018/09/06/Javascript-%E7%B1%BB%E4%B8%8E%E7%BB%A7%E6%89%BF/"/>
    <id>http://yangfan.site/2018/09/06/Javascript-类与继承/</id>
    <published>2018-09-06T09:19:54.000Z</published>
    <updated>2019-04-25T08:59:38.253Z</updated>
    
    <content type="html"><![CDATA[<h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><h3 id="构造函数继承"><a href="#构造函数继承" class="headerlink" title="构造函数继承"></a>构造函数继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name=<span class="string">'parent'</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Parent.prototype.run=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'We can run'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    Parent.call(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> c=<span class="keyword">new</span> Child();</span><br><span class="line">c.name; <span class="comment">// 'parent'</span></span><br><span class="line">c.run(); <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure><ul><li>缺点  </li></ul><ol><li>无法继承父类原型上的方法</li></ol><h3 id="原型链实现继承"><a href="#原型链实现继承" class="headerlink" title="原型链实现继承"></a>原型链实现继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name=<span class="string">'parent'</span>;</span><br><span class="line">    <span class="keyword">this</span>.colors=[<span class="string">"red"</span>,<span class="string">"yellow"</span>];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Parent.prototype.run=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'We can run'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Child.prototype=<span class="keyword">new</span> Parent();</span><br><span class="line">Child.prototype.constructor=Child;   </span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> c1=<span class="keyword">new</span> Child();</span><br><span class="line"><span class="keyword">var</span> c2=<span class="keyword">new</span> Child();</span><br><span class="line"></span><br><span class="line">c1.colors; <span class="comment">// ['red','yellow']</span></span><br><span class="line">c2.colors; <span class="comment">// ['red','yellow']</span></span><br><span class="line"></span><br><span class="line">c1.colors.push(<span class="string">'green'</span>);</span><br><span class="line"></span><br><span class="line">c1.colors; <span class="comment">// ['red','yellow','green']</span></span><br><span class="line">c2.colors; <span class="comment">// ['red','yellow','green']</span></span><br></pre></td></tr></table></figure><ul><li>缺点  </li></ul><ol><li>子类共用一个父类的实例，造成数据污染  </li><li>创建子类实例时，无法向父类构造函数传参</li></ol><h3 id="组合式继承"><a href="#组合式继承" class="headerlink" title="组合式继承"></a>组合式继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name=<span class="string">'parent'</span>;</span><br><span class="line">    <span class="keyword">this</span>.colors=[<span class="string">"red"</span>,<span class="string">"yellow"</span>];</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"I've executed"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Parent.prototype.run=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'We can run'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    Parent.call(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Child.prototype=<span class="keyword">new</span> Parent();</span><br><span class="line">Child.prototype.constructor=Child;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> c1=<span class="keyword">new</span> Child(); <span class="comment">// "I've executed" "I've executed"</span></span><br><span class="line"><span class="keyword">var</span> c2=<span class="keyword">new</span> Child(); <span class="comment">// "I've executed" "I've executed"</span></span><br><span class="line"></span><br><span class="line">c1.colors; <span class="comment">// ['red,yellow']</span></span><br><span class="line">c2.colors; <span class="comment">// ['red,yellow']</span></span><br><span class="line"></span><br><span class="line">c1.colors.push(<span class="string">'green'</span>);</span><br><span class="line"></span><br><span class="line">c1.colors; <span class="comment">// ['red,yellow','green']</span></span><br><span class="line">c2.colors; <span class="comment">// ['red,yellow']</span></span><br></pre></td></tr></table></figure><ul><li>缺点  </li></ul><ol><li>每新建一个子类都会调用两次父类构造器</li></ol><h3 id="寄生组合式继承"><a href="#寄生组合式继承" class="headerlink" title="寄生组合式继承"></a>寄生组合式继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name=<span class="string">'parent'</span>;</span><br><span class="line">    <span class="keyword">this</span>.colors=[<span class="string">"red"</span>,<span class="string">"yellow"</span>];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Parent.prototype.run=<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'We can run'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    Parent.call(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Super</span>(<span class="params"></span>) </span>&#123;<span class="comment">/* noop */</span>&#125;</span><br><span class="line">Super.prototype=Parent.prototype;</span><br><span class="line">Child.prototype=<span class="keyword">new</span> Super();</span><br><span class="line">Child.prototype.constructor=Child;</span><br></pre></td></tr></table></figure><ul><li>特点  </li></ul><ol><li>完美实现继承</li><li>利用寄生函数实现父类构造函数只执行一次，将原型上的方法挂载到寄生函数上，最后将寄生函数的实例作为子类的原型对象</li></ol><h3 id="ES6-继承"><a href="#ES6-继承" class="headerlink" title="ES6 继承"></a>ES6 继承</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Parent</span> </span>&#123;</span><br><span class="line">    <span class="keyword">constructor</span>() &#123;</span><br><span class="line">        <span class="keyword">this</span>.name=<span class="string">'parent'</span>;</span><br><span class="line">        <span class="keyword">this</span>.colors=[<span class="string">"red"</span>,<span class="string">"yellow"</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    run() &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'We can run'</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Child</span> <span class="keyword">extends</span> <span class="title">Parent</span></span>&#123;</span><br><span class="line">    <span class="keyword">constructor</span>() &#123;</span><br><span class="line">        <span class="keyword">super</span>();</span><br><span class="line">        <span class="keyword">this</span>.name=<span class="string">'child'</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>特点</li></ul><ol><li>简单明了 </li><li>只是一种语法糖而已</li></ol><ul><li>下面是babel将ES6转成ES5继承的实现</li></ul><h3 id="Babel-编译后的ES5代码"><a href="#Babel-编译后的ES5代码" class="headerlink" title="Babel 编译后的ES5代码"></a>Babel 编译后的ES5代码</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建类</span></span><br><span class="line"><span class="keyword">var</span> _createClass = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">defineProperties</span>(<span class="params">target, props</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; props.length; i++) &#123;</span><br><span class="line">            <span class="keyword">var</span> descriptor = props[i];</span><br><span class="line">            descriptor.enumerable = descriptor.enumerable || <span class="literal">false</span>;</span><br><span class="line">            descriptor.configurable = <span class="literal">true</span>;</span><br><span class="line">            <span class="keyword">if</span> (<span class="string">"value"</span><span class="keyword">in</span> descriptor)</span><br><span class="line">                descriptor.writable = <span class="literal">true</span>;</span><br><span class="line">            <span class="built_in">Object</span>.defineProperty(target, descriptor.key, descriptor);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">Constructor, protoProps, staticProps</span>) </span>&#123;</span><br><span class="line">        <span class="comment">// 定义原型对象的属性、方法</span></span><br><span class="line">        <span class="keyword">if</span> (protoProps)</span><br><span class="line">            defineProperties(Constructor.prototype, protoProps);</span><br><span class="line">        <span class="comment">// 定义类的静态属性、方法</span></span><br><span class="line">        <span class="keyword">if</span> (staticProps)</span><br><span class="line">            defineProperties(Constructor, staticProps);</span><br><span class="line">        <span class="keyword">return</span> Constructor;</span><br><span class="line">    &#125;</span><br><span class="line">    ;</span><br><span class="line">&#125;();</span><br><span class="line"><span class="comment">// 确保子类初始化时调用super</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">_possibleConstructorReturn</span>(<span class="params">self, call</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (!self) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">ReferenceError</span>(<span class="string">"this hasn't been initialised - super() hasn't been called"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> call &amp;&amp; (<span class="keyword">typeof</span> call === <span class="string">"object"</span> || <span class="keyword">typeof</span> call === <span class="string">"function"</span>) ? call : self;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 继承</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">_inherits</span>(<span class="params">subClass, superClass</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> superClass !== <span class="string">"function"</span> &amp;&amp; superClass !== <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">"Super expression must either be null or a function, not "</span> + <span class="keyword">typeof</span> superClass);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 利用 Object.crete 创建了一个父类原型对象的新实例，并且修正了构造器指向</span></span><br><span class="line">    subClass.prototype = <span class="built_in">Object</span>.create(superClass &amp;&amp; superClass.prototype, &#123;</span><br><span class="line">        <span class="keyword">constructor</span>: &#123;</span><br><span class="line">            value: subClass,</span><br><span class="line">            enumerable: <span class="literal">false</span>,</span><br><span class="line">            writable: <span class="literal">true</span>,</span><br><span class="line">            configurable: <span class="literal">true</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 将子类原型链链到父类上</span></span><br><span class="line">    <span class="keyword">if</span> (superClass)</span><br><span class="line">        <span class="built_in">Object</span>.setPrototypeOf ? <span class="built_in">Object</span>.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 安全检测，确保用 'new' 操作的构造函数</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">_classCallCheck</span>(<span class="params">instance, Constructor</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (!(instance <span class="keyword">instanceof</span> Constructor)) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">"Cannot call a class as a function"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> Parent = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        _classCallCheck(<span class="keyword">this</span>, Parent);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">this</span>.name = <span class="string">'parent'</span>;</span><br><span class="line">        <span class="keyword">this</span>.colors = [<span class="string">"red"</span>, <span class="string">"yellow"</span>];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    _createClass(Parent, [&#123;</span><br><span class="line">        key: <span class="string">"run"</span>,</span><br><span class="line">        value: <span class="function"><span class="keyword">function</span> <span class="title">run</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">'We can run'</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;]);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> Parent;</span><br><span class="line">&#125;();</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> Child = <span class="function"><span class="keyword">function</span>(<span class="params">_Parent</span>) </span>&#123;</span><br><span class="line">    _inherits(Child, _Parent);</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        _classCallCheck(<span class="keyword">this</span>, Child);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">var</span> _this = _possibleConstructorReturn(<span class="keyword">this</span>, (Child.__proto__ || <span class="built_in">Object</span>.getPrototypeOf(Child)).call(<span class="keyword">this</span>));</span><br><span class="line"></span><br><span class="line">        _this.name = <span class="string">'child'</span>;</span><br><span class="line">        <span class="keyword">return</span> _this;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> Child;</span><br><span class="line">&#125;(Parent);</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;继承&quot;&gt;&lt;a href=&quot;#继承&quot; class=&quot;headerlink&quot; title=&quot;继承&quot;&gt;&lt;/a&gt;继承&lt;/h2&gt;&lt;h3 id=&quot;构造函数继承&quot;&gt;&lt;a href=&quot;#构造函数继承&quot; class=&quot;headerlink&quot; title=&quot;构造函数继承&quot;&gt;&lt;/a&gt;构
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>十大经典排序算法-JavaScript篇</title>
    <link href="http://yangfan.site/2018/08/13/%E5%8D%81%E5%A4%A7%E7%BB%8F%E5%85%B8%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95-JavaScript%E7%AF%87/"/>
    <id>http://yangfan.site/2018/08/13/十大经典排序算法-JavaScript篇/</id>
    <published>2018-08-13T07:28:20.000Z</published>
    <updated>2019-04-25T09:01:16.837Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>备注 </p><ul><li><h5 id="语法为-ES6"><a href="#语法为-ES6" class="headerlink" title="语法为 ES6"></a>语法为 ES6</h5></li><li><h5 id="以下排序默认按升序排序"><a href="#以下排序默认按升序排序" class="headerlink" title="以下排序默认按升序排序"></a>以下排序默认按升序排序</h5></li><li><h5 id="测试案例均为自然数"><a href="#测试案例均为自然数" class="headerlink" title="测试案例均为自然数"></a>测试案例均为自然数</h5></li></ul></blockquote><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>排序作为十分经典的算法之一。是每一个软件工程师的必备技能，学好排序算法，可以提高软件的运行效率，最重要的是掌握其算法设计思想，才能举一反三应用到实际的实践中，为己所用。</p><h3 id="排序算法简介"><a href="#排序算法简介" class="headerlink" title="排序算法简介"></a>排序算法简介</h3><ol><li>按照数据的大小，排序算法可以分为内部排序和外部排序（数据较大，需要借助外存）</li><li>内部排序，又可以细分为 交换排序、插入排序、选择排序</li></ol><h3 id="1-冒泡排序"><a href="#1-冒泡排序" class="headerlink" title="1. 冒泡排序"></a>1. 冒泡排序</h3><h4 id="简介：两两元素进行比较，较大者放置后头，类似水中的气泡较大者浮在水的上端"><a href="#简介：两两元素进行比较，较大者放置后头，类似水中的气泡较大者浮在水的上端" class="headerlink" title="简介：两两元素进行比较，较大者放置后头，类似水中的气泡较大者浮在水的上端"></a>简介：两两元素进行比较，较大者放置后头，类似水中的气泡较大者浮在水的上端</h4><h4 id="性能"><a href="#性能" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n^2)</p><h4 id="代码："><a href="#代码：" class="headerlink" title="代码："></a>代码：</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">bubble</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> len = arr.length,</span><br><span class="line">        i = <span class="number">0</span>,</span><br><span class="line">        j = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">// 循环 n-1 趟</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; len; i++) &#123;</span><br><span class="line">        <span class="comment">// 每趟 需比较 n-i-1 次</span></span><br><span class="line">        <span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; len - <span class="number">1</span> - i; j++) &#123;</span><br><span class="line">            <span class="comment">// 如果后面的元素较大，则交换两者顺序</span></span><br><span class="line">            <span class="keyword">if</span> (arr[j + <span class="number">1</span>] &lt; arr[j]) &#123;</span><br><span class="line">                arr[j] = [arr[j + <span class="number">1</span>], arr[j + <span class="number">1</span>] = arr[j]][<span class="number">0</span>];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> arr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2-快速排序"><a href="#2-快速排序" class="headerlink" title="2. 快速排序"></a>2. 快速排序</h3><h4 id="简介：取一个元素为基准，把序列分成两部分，小于基准的放到它的左面，大于等于的放到它的右面，然后在把左面和右面的子序列再进行上述的拆分，直到子序列不可再分割（小于2个元素），最终达到整个序列有序"><a href="#简介：取一个元素为基准，把序列分成两部分，小于基准的放到它的左面，大于等于的放到它的右面，然后在把左面和右面的子序列再进行上述的拆分，直到子序列不可再分割（小于2个元素），最终达到整个序列有序" class="headerlink" title="简介：取一个元素为基准，把序列分成两部分，小于基准的放到它的左面，大于等于的放到它的右面，然后在把左面和右面的子序列再进行上述的拆分，直到子序列不可再分割（小于2个元素），最终达到整个序列有序"></a>简介：取一个元素为基准，把序列分成两部分，小于基准的放到它的左面，大于等于的放到它的右面，然后在把左面和右面的子序列再进行上述的拆分，直到子序列不可再分割（小于2个元素），最终达到整个序列有序</h4><h4 id="性能-1"><a href="#性能-1" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n*logn)</p><h4 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">quick</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 不可再分割，直接退出</span></span><br><span class="line">    <span class="keyword">if</span> (arr.length &lt;= <span class="number">1</span>) <span class="keyword">return</span> arr;</span><br><span class="line">    <span class="keyword">let</span> len = arr.length,</span><br><span class="line">        middle = len &gt;&gt; <span class="number">1</span>,</span><br><span class="line">        pivot = (len--) &amp;&amp; arr.splice(middle, <span class="number">1</span>)[<span class="number">0</span>], <span class="comment">// 取中间为基准数，并从数组中移除</span></span><br><span class="line">        left = [],</span><br><span class="line">        right = [],</span><br><span class="line">        i = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; len; i++) &#123;</span><br><span class="line">        <span class="comment">// 分组 小于基准的放到左边，反之</span></span><br><span class="line">        <span class="keyword">if</span> (arr[i] &lt; pivot) &#123;</span><br><span class="line">            left.push(arr[i]);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            right.push(arr[i]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> [...quick(left), pivot, ...quick(right)]; <span class="comment">// 合并</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-简单选择排序"><a href="#3-简单选择排序" class="headerlink" title="3. 简单选择排序"></a>3. 简单选择排序</h3><h4 id="简介：假设一个有序序列，然后由剩余的元素中选出最小的（最大的）扔到有序序列，直到无序序列元素为空，从而达到整个序列有序"><a href="#简介：假设一个有序序列，然后由剩余的元素中选出最小的（最大的）扔到有序序列，直到无序序列元素为空，从而达到整个序列有序" class="headerlink" title="简介：假设一个有序序列，然后由剩余的元素中选出最小的（最大的）扔到有序序列，直到无序序列元素为空，从而达到整个序列有序"></a>简介：假设一个有序序列，然后由剩余的元素中选出最小的（最大的）扔到有序序列，直到无序序列元素为空，从而达到整个序列有序</h4><h4 id="性能-2"><a href="#性能-2" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n^2)</p><h4 id="代码-1"><a href="#代码-1" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">selection</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> len = arr.length,</span><br><span class="line">        i = <span class="number">0</span>,</span><br><span class="line">        j = <span class="number">0</span>,</span><br><span class="line">        min = i;</span><br><span class="line">    <span class="comment">// 循环 n-1 趟</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; len - <span class="number">1</span>; i++) &#123;</span><br><span class="line">        min = i; <span class="comment">// 假设每趟的第一个数为最小值</span></span><br><span class="line">        <span class="keyword">for</span> (j = i + <span class="number">1</span>; j &lt; len; j++) &#123;</span><br><span class="line">            <span class="comment">// 如果后面的树大于最小数（min对应的数），则重新对最小值的索引赋值</span></span><br><span class="line">            <span class="keyword">if</span> (arr[j] &lt; arr[min]) &#123;</span><br><span class="line">                min = j;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 将最小数置于该趟排序的第一个位置</span></span><br><span class="line">        arr[i] = [arr[min], arr[min] = arr[i]][<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> arr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="4-堆排序"><a href="#4-堆排序" class="headerlink" title="4. 堆排序"></a>4. 堆排序</h3><h4 id="简介：是简单选择排序的改进版，利用堆结构"><a href="#简介：是简单选择排序的改进版，利用堆结构" class="headerlink" title="简介：是简单选择排序的改进版，利用堆结构"></a>简介：是简单选择排序的改进版，利用堆结构</h4><h4 id="性能-3"><a href="#性能-3" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n*logn)</p><h4 id="代码-2"><a href="#代码-2" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 堆排序</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">heapSort</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> n = arr.length,</span><br><span class="line">        i, j;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 筛选</span></span><br><span class="line">    <span class="keyword">var</span> sift = <span class="function">(<span class="params">k, m, r</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">var</span> p = k, <span class="comment">// 父结点</span></span><br><span class="line">            c = p * <span class="number">2</span> + <span class="number">1</span>; <span class="comment">// 左结点（默认最大）</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (c &lt;= m) &#123; <span class="comment">// 左结点(c=m)和左右结点(c&lt;m)</span></span><br><span class="line">            <span class="keyword">if</span> (c &lt; m &amp;&amp; r[c + <span class="number">1</span>] &gt; r[c]) c++; <span class="comment">// 选出左右结点中的最大者，指向左结点</span></span><br><span class="line">            <span class="keyword">if</span> (r[p] &gt; r[c]) <span class="keyword">break</span>; <span class="comment">// 父结点大于左结点 顺序正确，退出循环</span></span><br><span class="line">            <span class="keyword">else</span> &#123;</span><br><span class="line">                r[p] = [r[c], r[c] = r[p]][<span class="number">0</span>]; <span class="comment">// 将大的一方置于顶部（父结点）</span></span><br><span class="line">                p = c; <span class="comment">// 向下重新指向父结点</span></span><br><span class="line">                c = p * <span class="number">2</span> + <span class="number">1</span>; <span class="comment">// 向下重新指向左结点</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 构建堆</span></span><br><span class="line">    <span class="keyword">for</span> (i = (n / <span class="number">2</span> | <span class="number">0</span>) - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) &#123; <span class="comment">// 从最后一个分支结点开始向上逆序遍历 </span></span><br><span class="line">        sift(i, n - <span class="number">1</span>, arr);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 排序</span></span><br><span class="line">    <span class="keyword">for</span> (j = n - <span class="number">1</span>; j &gt;= <span class="number">0</span>; j--) &#123;</span><br><span class="line">        arr[<span class="number">0</span>] = [arr[j], arr[j] = arr[<span class="number">0</span>]][<span class="number">0</span>]; <span class="comment">// 将最大的结点存于数组的最后一位</span></span><br><span class="line">        n--; <span class="comment">// 减少数组长度，排除有序序列</span></span><br><span class="line">        sift(<span class="number">0</span>, n - <span class="number">1</span>, arr, <span class="literal">true</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> arr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="5-直接插入排序"><a href="#5-直接插入排序" class="headerlink" title="5. 直接插入排序"></a>5. 直接插入排序</h3><h4 id="简介：假设数组的一有序序列，从后面的无序序列中，扫描，与有序序列比较，插入到合适位置"><a href="#简介：假设数组的一有序序列，从后面的无序序列中，扫描，与有序序列比较，插入到合适位置" class="headerlink" title="简介：假设数组的一有序序列，从后面的无序序列中，扫描，与有序序列比较，插入到合适位置"></a>简介：假设数组的一有序序列，从后面的无序序列中，扫描，与有序序列比较，插入到合适位置</h4><h4 id="性能-4"><a href="#性能-4" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n^2)</p><h4 id="代码-3"><a href="#代码-3" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">insertion</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> len = arr.length,</span><br><span class="line">        i = <span class="number">0</span>,</span><br><span class="line">        j = <span class="number">0</span>,</span><br><span class="line">        temp;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// [7,6,2,5,4,3,1]</span></span><br><span class="line">    <span class="comment">// 从第二个元素开始循环</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">1</span>; i &lt; len; i++) &#123;</span><br><span class="line">        temp = arr[i]; <span class="comment">// 存储当前元素</span></span><br><span class="line">        j = i - <span class="number">1</span>; <span class="comment">// 待插入队列的序号</span></span><br><span class="line">        <span class="keyword">while</span> (j &gt;= <span class="number">0</span> &amp;&amp; temp &lt; arr[j]) &#123; <span class="comment">// 当没有出界 且 当前元素比待插序列元素小时，进行待插序列的元素向后移动一位</span></span><br><span class="line">            arr[j + <span class="number">1</span>] = arr[j];</span><br><span class="line">            j--;</span><br><span class="line">        &#125;</span><br><span class="line">        arr[j + <span class="number">1</span>] = temp; <span class="comment">// 将当前元素插入到待插序列的下一位</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> arr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="6-希尔排序"><a href="#6-希尔排序" class="headerlink" title="6. 希尔排序"></a>6. 希尔排序</h3><h4 id="简介：一种改进版的插入排序，每次比较的是用增量分割的序列，达到部分有序，随着增量依次递减，序列逐渐达到完全有序"><a href="#简介：一种改进版的插入排序，每次比较的是用增量分割的序列，达到部分有序，随着增量依次递减，序列逐渐达到完全有序" class="headerlink" title="简介：一种改进版的插入排序，每次比较的是用增量分割的序列，达到部分有序，随着增量依次递减，序列逐渐达到完全有序"></a>简介：一种改进版的插入排序，每次比较的是用增量分割的序列，达到部分有序，随着增量依次递减，序列逐渐达到完全有序</h4><h4 id="性能-5"><a href="#性能-5" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n*logn)</p><h4 id="代码-4"><a href="#代码-4" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">shell</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> len = arr.length,</span><br><span class="line">        i = <span class="number">0</span>,</span><br><span class="line">        j = <span class="number">0</span>,</span><br><span class="line">        temp,</span><br><span class="line">        gap = <span class="number">1</span>;</span><br><span class="line">    </span><br><span class="line">    gap = len / <span class="number">3</span> | <span class="number">0</span>; <span class="comment">// 计算增量</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (gap &gt;= <span class="number">1</span>) &#123; <span class="comment">// 增量大于2时，进行简单插入排序</span></span><br><span class="line">        <span class="keyword">for</span> (i = gap; i &lt; len; i++) &#123;</span><br><span class="line">            temp = arr[i];</span><br><span class="line">            j = i - gap;</span><br><span class="line">            <span class="keyword">while</span> (j &gt;= <span class="number">0</span> &amp;&amp; temp &lt; arr[j]) &#123;</span><br><span class="line">                arr[j + gap] = arr[j];</span><br><span class="line">                j -= gap;</span><br><span class="line">            &#125;</span><br><span class="line">            arr[j + gap] = temp;</span><br><span class="line">        &#125;</span><br><span class="line">        gap = gap / <span class="number">3</span> | <span class="number">0</span>; <span class="comment">// 增量减少</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> arr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="7-归并排序"><a href="#7-归并排序" class="headerlink" title="7. 归并排序"></a>7. 归并排序</h3><h4 id="简介：利用分治法，将序列分为许多小子序列，然后每个子序列进行排序，然后逐次合并，最后达到整体有序，这里用的是二路归并排序（归并排序中最简单的一种）"><a href="#简介：利用分治法，将序列分为许多小子序列，然后每个子序列进行排序，然后逐次合并，最后达到整体有序，这里用的是二路归并排序（归并排序中最简单的一种）" class="headerlink" title="简介：利用分治法，将序列分为许多小子序列，然后每个子序列进行排序，然后逐次合并，最后达到整体有序，这里用的是二路归并排序（归并排序中最简单的一种）"></a>简介：利用分治法，将序列分为许多小子序列，然后每个子序列进行排序，然后逐次合并，最后达到整体有序，这里用的是二路归并排序（归并排序中最简单的一种）</h4><h4 id="性能-6"><a href="#性能-6" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n*logn)</p><h4 id="代码-5"><a href="#代码-5" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">merge</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (&#123;</span><br><span class="line">        sortArr(leftArr, rightArr) &#123; <span class="comment">// 排序</span></span><br><span class="line">            <span class="keyword">let</span> res = [];</span><br><span class="line">            <span class="comment">// 合并</span></span><br><span class="line">            <span class="keyword">while</span> (leftArr.length * rightArr.length !== <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span> (leftArr[<span class="number">0</span>] &lt; rightArr[<span class="number">0</span>]) &#123;</span><br><span class="line">                    res.push(leftArr.shift());</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    res.push(rightArr.shift());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            leftArr.length &gt; <span class="number">0</span> &amp;&amp; (res = [...res, ...leftArr]);</span><br><span class="line">            rightArr.length &gt; <span class="number">0</span> &amp;&amp; (res = [...res, ...rightArr]);</span><br><span class="line">            <span class="keyword">return</span> res;</span><br><span class="line">        &#125;,</span><br><span class="line">        mergeArr(brr) &#123; <span class="comment">// 合并</span></span><br><span class="line">            <span class="keyword">if</span> (brr.length &lt;= <span class="number">1</span>) <span class="keyword">return</span> brr;</span><br><span class="line">            <span class="keyword">let</span> len = brr.length,</span><br><span class="line">                left = [],</span><br><span class="line">                right = [],</span><br><span class="line">                middle;</span><br><span class="line">            middle = len &gt;&gt; <span class="number">1</span>;</span><br><span class="line">            <span class="comment">// 分组</span></span><br><span class="line">            left = brr.slice(<span class="number">0</span>, middle);</span><br><span class="line">            right = brr.slice(middle);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">this</span>.sortArr(<span class="keyword">this</span>.mergeArr(left), <span class="keyword">this</span>.mergeArr(right));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;).mergeArr(arr)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="8-计数排序"><a href="#8-计数排序" class="headerlink" title="8. 计数排序"></a>8. 计数排序</h3><h4 id="简介：利用分配概念，将元素一一映射到桶中，每个桶只存储单一值"><a href="#简介：利用分配概念，将元素一一映射到桶中，每个桶只存储单一值" class="headerlink" title="简介：利用分配概念，将元素一一映射到桶中，每个桶只存储单一值"></a>简介：利用分配概念，将元素一一映射到桶中，每个桶只存储单一值</h4><h4 id="性能-7"><a href="#性能-7" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n+m)</p><h4 id="代码-6"><a href="#代码-6" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">countingSort</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> max = <span class="built_in">Math</span>.max(...arr),</span><br><span class="line">        min = <span class="built_in">Math</span>.min(...arr),</span><br><span class="line">        len = arr.length,</span><br><span class="line">        i,</span><br><span class="line">        bucket = [],</span><br><span class="line">        result = [];</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 入桶</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; len; i++) &#123;</span><br><span class="line">        <span class="keyword">var</span> item = arr[i];</span><br><span class="line">        bucket[item] = bucket[item] || <span class="number">0</span>; <span class="comment">// 建立映射表</span></span><br><span class="line">        bucket[item]++; <span class="comment">// 相同元素对应到同一映射表中，映射表增加1 </span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 出桶</span></span><br><span class="line">    <span class="keyword">for</span> (i = min; i &lt;= max; i++) &#123;</span><br><span class="line">        <span class="keyword">var</span> count = bucket[i]; <span class="comment">// 取每个映射表的元素数量</span></span><br><span class="line">        <span class="keyword">while</span> (count &gt; <span class="number">0</span>) &#123; <span class="comment">// 如果数量大于0 ，重复输出该元素 </span></span><br><span class="line">            result.push(i);</span><br><span class="line">            count--;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="9-桶排序"><a href="#9-桶排序" class="headerlink" title="9. 桶排序"></a>9. 桶排序</h3><h4 id="简介：利用分配概念，每个桶存储一定范围的数值，然后桶内在进行排序，最后所有桶的元素出桶达到完全有序"><a href="#简介：利用分配概念，每个桶存储一定范围的数值，然后桶内在进行排序，最后所有桶的元素出桶达到完全有序" class="headerlink" title="简介：利用分配概念，每个桶存储一定范围的数值，然后桶内在进行排序，最后所有桶的元素出桶达到完全有序"></a>简介：利用分配概念，每个桶存储一定范围的数值，然后桶内在进行排序，最后所有桶的元素出桶达到完全有序</h4><h4 id="性能-8"><a href="#性能-8" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n+m)</p><h4 id="代码-7"><a href="#代码-7" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">bucketSort</span>(<span class="params">arr, num</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> len = arr.length,</span><br><span class="line">        max = <span class="built_in">Math</span>.max(...arr),</span><br><span class="line">        min = <span class="built_in">Math</span>.min(...arr),</span><br><span class="line">        result = [],</span><br><span class="line">        bucket = [],</span><br><span class="line">        space,</span><br><span class="line">        i;</span><br><span class="line">    <span class="comment">// 至少2个桶</span></span><br><span class="line">    num = num &gt; <span class="number">2</span> ? num : <span class="number">2</span>;</span><br><span class="line">    <span class="comment">// 计算每个桶的容量</span></span><br><span class="line">    space = ((max - min) / num | <span class="number">0</span>) + <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 入桶</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; len; i++) &#123;</span><br><span class="line">        <span class="keyword">var</span> item = arr[i];</span><br><span class="line">        <span class="keyword">var</span> index = (item - min) / space | <span class="number">0</span>; <span class="comment">// 计算元素入桶的位置，要放入哪个桶</span></span><br><span class="line"></span><br><span class="line">        bucket[index] = bucket[index] || [];</span><br><span class="line">        bucket[index].push(item);</span><br><span class="line">        <span class="keyword">if</span> (bucket[index].length &gt; <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 桶里的元素再进行排序（这里使用的是简单插入排序）</span></span><br><span class="line">            bucket[index] = insertion(bucket[index]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 出桶</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; num; i++) &#123;</span><br><span class="line">        <span class="keyword">var</span> list = bucket[i] || [];</span><br><span class="line">        <span class="keyword">if</span> (list.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            result = result.concat(list);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="10-基数排序"><a href="#10-基数排序" class="headerlink" title="10. 基数排序"></a>10. 基数排序</h3><h4 id="简介：利用分配概念，根据元素的基数来分配桶"><a href="#简介：利用分配概念，根据元素的基数来分配桶" class="headerlink" title="简介：利用分配概念，根据元素的基数来分配桶"></a>简介：利用分配概念，根据元素的基数来分配桶</h4><ul><li><p>最低位优先法，简称LSD法：先从最低位开始排序，再对次低位排序，直到对最高位排序后得到一个有序序列</p></li><li><p>最高位优先法，简称MSD法：先从最高位开始排序，再逐个对各分组按次高位进行子排序，循环直到最低位</p></li></ul><h4 id="性能-9"><a href="#性能-9" class="headerlink" title="性能"></a>性能</h4><p>平均时间复杂度 O(n*m)</p><h4 id="代码-8"><a href="#代码-8" class="headerlink" title="代码"></a>代码</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">radixSort</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> len = arr.length,</span><br><span class="line">        max = <span class="built_in">Math</span>.max(...arr),</span><br><span class="line">        bucket = [],</span><br><span class="line">        result = [],</span><br><span class="line">        i,</span><br><span class="line">        j,</span><br><span class="line">        k,</span><br><span class="line">        hight = <span class="built_in">String</span>(max).length; <span class="comment">// 计算最大数的位数</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">1</span>; i &lt;= hight; i++) &#123; <span class="comment">// 其实就是循环hight次的计数排序</span></span><br><span class="line">        result = [];</span><br><span class="line">        bucket = [];</span><br><span class="line">        <span class="comment">// 入桶</span></span><br><span class="line">        <span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; len; j++) &#123;</span><br><span class="line">            <span class="keyword">var</span> item = arr[j] + <span class="string">""</span>; <span class="comment">// 这里转换为string 类型，方便取具体位数的值，当然mod10也可以</span></span><br><span class="line">            <span class="keyword">var</span> index = item.length - i &lt; <span class="number">0</span> ? <span class="number">0</span> : item.substr(item.length - i, <span class="number">1</span>); <span class="comment">// 取第(item.len-i+1)位的数</span></span><br><span class="line">            bucket[index] = bucket[index] || []; <span class="comment">// 这里就和计数排序一样了</span></span><br><span class="line">            bucket[index].push(+item);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 出桶</span></span><br><span class="line">        <span class="keyword">for</span> (k = <span class="number">0</span>; k &lt; bucket.length; k++) &#123; </span><br><span class="line">            <span class="keyword">if</span> (bucket[k] &amp;&amp; bucket[k].length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                result = result.concat(bucket[k]);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        arr = result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="性能比较"><a href="#性能比较" class="headerlink" title="性能比较"></a>性能比较</h3><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/sort.png" alt="sort" title>                </div>                <div class="image-caption">sort</div>            </figure><h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><ol><li><a href="https://github.com/Yangfan2016/JS-Sorting-Algorithm" target="_blank" rel="noopener">《十大经典排序算法》</a></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;备注 &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h5 id=&quot;语法为-ES6&quot;&gt;&lt;a href=&quot;#语法为-ES6&quot; class=&quot;headerlink&quot; title=&quot;语法为 ES6&quot;&gt;&lt;/a&gt;语法为 ES6&lt;/h5&gt;&lt;/li&gt;
&lt;li&gt;&lt;h5 id=&quot;以下
      
    
    </summary>
    
    
      <category term="算法" scheme="http://yangfan.site/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>微信扫码登录原理解析</title>
    <link href="http://yangfan.site/2018/07/03/%E5%BE%AE%E4%BF%A1%E6%89%AB%E7%A0%81%E7%99%BB%E5%BD%95%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90/"/>
    <id>http://yangfan.site/2018/07/03/微信扫码登录原理解析/</id>
    <published>2018-07-03T10:16:26.000Z</published>
    <updated>2019-04-25T09:01:12.867Z</updated>
    
    <content type="html"><![CDATA[<h1 id="微信扫码登录原理解析"><a href="#微信扫码登录原理解析" class="headerlink" title="微信扫码登录原理解析"></a>微信扫码登录原理解析</h1><blockquote><p>扫码登录是现在流行的登录方式，使用这种方式及其方便，而且安全 </p></blockquote><h2 id="扫码登录流程"><a href="#扫码登录流程" class="headerlink" title="扫码登录流程"></a>扫码登录流程</h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://upload-images.jianshu.io/upload_images/538-623026f12e28b0fa.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/659" alt="look.jpg" title>                </div>                <div class="image-caption">look.jpg</div>            </figure><h2 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h2><ol><li><p>获取唯一的uuid, 以及包含uid信息的二维码</p><p> <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/wx-qrcode-getuuid.JPG" alt="wx-qrcode-getuuid.JPG"></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">    <span class="comment">// 获取uuid</span></span><br><span class="line">    getUUID: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> e = t.defer();</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">window</span>.QRLogin = &#123;&#125;,</span><br><span class="line">        $.ajax(&#123;</span><br><span class="line">            url: i.API_jsLogin,</span><br><span class="line">            dataType: <span class="string">"script"</span></span><br><span class="line">        &#125;).done(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="number">200</span> == <span class="built_in">window</span>.QRLogin.code ? e.resolve(<span class="built_in">window</span>.QRLogin.uuid) : e.reject(<span class="built_in">window</span>.QRLogin.code)</span><br><span class="line">        &#125;).fail(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            e.reject()</span><br><span class="line">        &#125;),</span><br><span class="line">        e.promise</span><br><span class="line">    &#125;</span><br><span class="line"><span class="string">``</span><span class="string">`  </span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">2. 浏览器轮询服务器，获取扫码状态  </span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">`</span><span class="string">``</span>js</span><br><span class="line"><span class="comment">// 查看扫码状态</span></span><br><span class="line">checkLogin: <span class="function"><span class="keyword">function</span>(<span class="params">e, a</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> n = t.defer()</span><br><span class="line">        , a = a || <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">window</span>.code = <span class="number">0</span>,</span><br><span class="line">    <span class="built_in">window</span>.checkLoginPromise = $.ajax(&#123;</span><br><span class="line">        url: i.API_login + <span class="string">"?loginicon=true&amp;uuid="</span> + e + <span class="string">"&amp;tip="</span> + a + <span class="string">"&amp;r="</span> + ~<span class="keyword">new</span> <span class="built_in">Date</span>,</span><br><span class="line">        dataType: <span class="string">"script"</span>,</span><br><span class="line">        timeout: <span class="number">35e3</span></span><br><span class="line">    &#125;).done(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">"/"</span> + location.host + <span class="string">"/"</span>);</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">window</span>.redirect_uri &amp;&amp; <span class="built_in">window</span>.redirect_uri.indexOf(<span class="string">"/"</span> + location.host + <span class="string">"/"</span>) &lt; <span class="number">0</span>)</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">void</span> (location.href = <span class="built_in">window</span>.redirect_uri);</span><br><span class="line">        <span class="keyword">var</span> e = &#123;</span><br><span class="line">            code: <span class="built_in">window</span>.code,</span><br><span class="line">            redirect_uri: <span class="built_in">window</span>.redirect_uri,</span><br><span class="line">            userAvatar: <span class="built_in">window</span>.userAvatar</span><br><span class="line">        &#125;;</span><br><span class="line">        n.resolve(e)</span><br><span class="line">    &#125;).fail(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        n.reject()</span><br><span class="line">    &#125;),</span><br><span class="line">    n.promise</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>根据服务器返回的扫码状态，进行相应的操作</p><ul><li>408 扫码超时  如果手机没有扫码或没有授权登录，服务器会阻塞约25s，然后返回状态码 408 -&gt; 前端继续轮询<br><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/wx-qrcode-408-25s.JPG" alt="wx-qrcode-408-25s.JPG"><br><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/wx-qrcode-408.JPG" alt="wx-qrcode-408.JPG"><ul><li>400 二维码失效 大约5分钟的时间内不扫码，二维码失效<br><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/wx-qrcode-400.JPG" alt="wx-qrcode-400.JPG"></li><li>201 已扫码  如果手机已经扫码，服务器立即返回状态码和用户的基本信息 （window.code=201,window.code.userAvator=”…”），-&gt; 前端继续轮询<br><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/wx-qrcode-201.JPG" alt="wx-qrcode-201.JPG"></li><li>200 已授权 如果手机点击了确认登录，服务器返回200及token -&gt; 前端停止轮询, 获取到token，重定向到目标页<br><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/wx-qrcode-200.JPG" alt="wx-qrcode-200.JPG"></li></ul></li></ul></li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 根据服务器返回的扫码状态，进行相应的操作</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">o</span>(<span class="params">c</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (c.code) &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">200</span>:</span><br><span class="line">        t.newLoginPage(c.redirect_uri).then(<span class="function"><span class="keyword">function</span>(<span class="params">t</span>) </span>&#123;</span><br><span class="line">            <span class="keyword">var</span> o = t.match(<span class="regexp">/&lt;ret&gt;(.*)&lt;\/ret&gt;/</span>)</span><br><span class="line">                , r = t.match(<span class="regexp">/&lt;script&gt;(.*)&lt;\/script&gt;/</span>)</span><br><span class="line">                , c = t.match(<span class="regexp">/&lt;skey&gt;(.*)&lt;\/skey&gt;/</span>)</span><br><span class="line">                , s = t.match(<span class="regexp">/&lt;wxsid&gt;(.*)&lt;\/wxsid&gt;/</span>)</span><br><span class="line">                , l = t.match(<span class="regexp">/&lt;wxuin&gt;(.*)&lt;\/wxuin&gt;/</span>)</span><br><span class="line">                , d = t.match(<span class="regexp">/&lt;pass_ticket&gt;(.*)&lt;\/pass_ticket&gt;/</span>)</span><br><span class="line">                , f = t.match(<span class="regexp">/&lt;message&gt;(.*)&lt;\/message&gt;/</span>)</span><br><span class="line">                , u = t.match(<span class="regexp">/&lt;redirecturl&gt;(.*)&lt;\/redirecturl&gt;/</span>);</span><br><span class="line">            <span class="keyword">return</span> u ? <span class="keyword">void</span> (<span class="built_in">window</span>.location.href = u[<span class="number">1</span>]) : o &amp;&amp; <span class="string">"0"</span> != o[<span class="number">1</span>] ? (alert(f &amp;&amp; f[<span class="number">1</span>] || <span class="string">"登陆失败"</span>),</span><br><span class="line">            i.report(i.AUTH_FAIL_COUNT, <span class="number">1</span>),</span><br><span class="line">            <span class="keyword">void</span> location.reload()) : (e.$emit(<span class="string">"newLoginPage"</span>, &#123;</span><br><span class="line">                Ret: o &amp;&amp; o[<span class="number">1</span>],</span><br><span class="line">                SKey: c &amp;&amp; c[<span class="number">1</span>],</span><br><span class="line">                Sid: s &amp;&amp; s[<span class="number">1</span>],</span><br><span class="line">                Uin: l &amp;&amp; l[<span class="number">1</span>],</span><br><span class="line">                Passticket: d &amp;&amp; d[<span class="number">1</span>],</span><br><span class="line">                Code: r</span><br><span class="line">            &#125;),</span><br><span class="line">            <span class="keyword">void</span> (a.getCookie(<span class="string">"webwx_data_ticket"</span>) || n.report(n.ReportType.cookieError, &#123;</span><br><span class="line">                text: <span class="string">"webwx_data_ticket 票据丢失"</span>,</span><br><span class="line">                cookie: <span class="built_in">document</span>.cookie</span><br><span class="line">            &#125;)))</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">201</span>:</span><br><span class="line">        e.isScan = !<span class="number">0</span>,</span><br><span class="line">        n.report(n.ReportType.timing, &#123;</span><br><span class="line">            timing: &#123;</span><br><span class="line">                scan: <span class="built_in">Date</span>.now()</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;),</span><br><span class="line">        t.checkLogin(e.uuid).then(o, <span class="function"><span class="keyword">function</span>(<span class="params">t</span>) </span>&#123;</span><br><span class="line">            !t &amp;&amp; <span class="built_in">window</span>.checkLoginPromise &amp;&amp; (e.isBrokenNetwork = !<span class="number">0</span>)</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">408</span>:</span><br><span class="line">        t.checkLogin(e.uuid).then(o, <span class="function"><span class="keyword">function</span>(<span class="params">t</span>) </span>&#123;</span><br><span class="line">            !t &amp;&amp; <span class="built_in">window</span>.checkLoginPromise &amp;&amp; (e.isBrokenNetwork = !<span class="number">0</span>)</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">400</span>:</span><br><span class="line">    <span class="keyword">case</span> <span class="number">500</span>:</span><br><span class="line">    <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">var</span> s = a.getCookie(<span class="string">"refreshTimes"</span>) || <span class="number">0</span>;</span><br><span class="line">        s &lt; <span class="number">5</span> ? (s++,</span><br><span class="line">        a.setCookie(<span class="string">"refreshTimes"</span>, s, <span class="number">.5</span>),</span><br><span class="line">        <span class="built_in">document</span>.location.reload()) : e.isNeedRefresh = !<span class="number">0</span>;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">202</span>:</span><br><span class="line">        e.isScan = !<span class="number">1</span>,</span><br><span class="line">        e.isAssociationLogin = !<span class="number">1</span>,</span><br><span class="line">        a.setCookie(<span class="string">"login_frequency"</span>, <span class="number">0</span>, <span class="number">2</span>),</span><br><span class="line">        <span class="built_in">window</span>.checkLoginPromise &amp;&amp; (<span class="built_in">window</span>.checkLoginPromise.abort(),</span><br><span class="line">        <span class="built_in">window</span>.checkLoginPromise = <span class="literal">null</span> ),</span><br><span class="line">        r()</span><br><span class="line">    &#125;</span><br><span class="line">    e.code = c.code,</span><br><span class="line">    e.userAvatar = c.userAvatar,</span><br><span class="line">    a.log(<span class="string">"get code"</span>, c.code)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>轮询采用的是JSONP的形式，排除了跨域问题</li><li>轮询采用的后台根据扫码情况阻塞前台请求，优化轮询及减少前端的无效轮询</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;微信扫码登录原理解析&quot;&gt;&lt;a href=&quot;#微信扫码登录原理解析&quot; class=&quot;headerlink&quot; title=&quot;微信扫码登录原理解析&quot;&gt;&lt;/a&gt;微信扫码登录原理解析&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;扫码登录是现在流行的登录方式，使用这种方式及其方便
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Debounce and Throttle</title>
    <link href="http://yangfan.site/2018/06/22/Debounce-and-Throttle/"/>
    <id>http://yangfan.site/2018/06/22/Debounce-and-Throttle/</id>
    <published>2018-06-22T08:41:29.000Z</published>
    <updated>2019-04-25T08:59:38.251Z</updated>
    
    <content type="html"><![CDATA[<h1 id="防抖动与节流"><a href="#防抖动与节流" class="headerlink" title="防抖动与节流"></a>防抖动与节流</h1><blockquote><p><a href="http://yangfan2016.github.io/myweb2016/demo/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/%E9%98%B2%E6%8A%96%E4%B8%8E%E8%8A%82%E6%B5%81/" target="_blank" rel="noopener">DEMO</a></p></blockquote><h3 id="防抖动"><a href="#防抖动" class="headerlink" title="防抖动"></a>防抖动</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> debounce = <span class="function"><span class="keyword">function</span> (<span class="params">fn, delay, isImmediate</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> timer = <span class="literal">null</span>;</span><br><span class="line">    <span class="comment">// 默认不立即触发</span></span><br><span class="line">    isImmediate = <span class="keyword">typeof</span> isImmediate === <span class="string">"undefined"</span> ? <span class="literal">false</span> : isImmediate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> ctx = <span class="keyword">this</span>, <span class="comment">// 保存作用域</span></span><br><span class="line">            args = <span class="built_in">arguments</span>; <span class="comment">// 保存参数</span></span><br><span class="line">        <span class="comment">// 初始化清空所有定时器</span></span><br><span class="line">        <span class="keyword">if</span> (timer) &#123;</span><br><span class="line">            clearTimeout(timer);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 如果是立即触发</span></span><br><span class="line">        <span class="keyword">if</span> (isImmediate) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!timer) &#123; <span class="comment">// timer为空时触发操作</span></span><br><span class="line">                fn.apply(ctx, args);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// delay时间后置空timer</span></span><br><span class="line">            timer = setTimeout(<span class="function"><span class="params">_</span> =&gt;</span> &#123;</span><br><span class="line">                timer = <span class="literal">null</span>;</span><br><span class="line">            &#125;, delay);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123; <span class="comment">// delay时间后触发操作</span></span><br><span class="line">            timer = setTimeout(<span class="function"><span class="params">_</span> =&gt;</span> &#123;</span><br><span class="line">                fn.apply(ctx, args);</span><br><span class="line">            &#125;, delay);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>防抖动立即触发<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/debounce-immediate.png" alt="debounce-immediate.png" title>                </div>                <div class="image-caption">debounce-immediate.png</div>            </figure></p><p>防抖动<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/debounce.png" alt="debounce.png" title>                </div>                <div class="image-caption">debounce.png</div>            </figure></p><h3 id="节流"><a href="#节流" class="headerlink" title="节流"></a>节流</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> throttle = <span class="function"><span class="keyword">function</span> (<span class="params">fn, delay, isImmediate</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> timer = <span class="literal">null</span>;</span><br><span class="line">    <span class="comment">// 默认立即触发</span></span><br><span class="line">    isImmediate = <span class="keyword">typeof</span> isImmediate === <span class="string">"undefined"</span> ? <span class="literal">true</span> : isImmediate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> ctx = <span class="keyword">this</span>, <span class="comment">// 保存作用域</span></span><br><span class="line">            args = <span class="built_in">arguments</span>; <span class="comment">// 保存参数</span></span><br><span class="line">        <span class="keyword">if</span> (!timer) &#123; <span class="comment">// timer为空时</span></span><br><span class="line">            <span class="keyword">if</span> (isImmediate) fn.apply(ctx, args); <span class="comment">// 立即触发</span></span><br><span class="line">            timer = setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">                clearTimeout(timer);</span><br><span class="line">                timer = <span class="literal">null</span>;</span><br><span class="line">                <span class="keyword">if</span> (!isImmediate) fn.apply(ctx, args); <span class="comment">// delay时间后触发操作</span></span><br><span class="line">            &#125;, delay);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>节流立即触发<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/throttle-immediate.png" alt="throttle-immediate.png" title>                </div>                <div class="image-caption">throttle-immediate.png</div>            </figure><br>节流<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/throttle.png" alt="throttle.png" title>                </div>                <div class="image-caption">throttle.png</div>            </figure></p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul><li>防抖动：将多个操作合并为一个操作（例如，键盘输入关键字搜索内容），在规定延时时间后触发，如果在定时器时间范围内触发，则会清楚定时器，重新计时</li><li>节流：在给定的延时时间后触发一次操作，在此时间范围内的操作均不触发（例如，图片懒加载、向下无限滚动获取新数据）</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;防抖动与节流&quot;&gt;&lt;a href=&quot;#防抖动与节流&quot; class=&quot;headerlink&quot; title=&quot;防抖动与节流&quot;&gt;&lt;/a&gt;防抖动与节流&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://yangfan2016.github.io/myw
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="网站优化" scheme="http://yangfan.site/tags/%E7%BD%91%E7%AB%99%E4%BC%98%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>浏览器杂谈</title>
    <link href="http://yangfan.site/2018/06/05/%E6%B5%8F%E8%A7%88%E5%99%A8%E6%9D%82%E8%B0%88/"/>
    <id>http://yangfan.site/2018/06/05/浏览器杂谈/</id>
    <published>2018-06-05T02:56:31.000Z</published>
    <updated>2019-04-25T09:00:54.754Z</updated>
    
    <content type="html"><![CDATA[<h2 id="浏览器缓存（协议层的缓存）"><a href="#浏览器缓存（协议层的缓存）" class="headerlink" title="浏览器缓存（协议层的缓存）"></a>浏览器缓存（协议层的缓存）</h2><blockquote><p>主要分为强缓存和协商缓存，详情 <a href="https://segmentfault.com/a/1190000011212929" target="_blank" rel="noopener">https://segmentfault.com/a/1190000011212929</a></p></blockquote><ol><li><p>强缓存<br> 浏览器会先获取该资源缓存的header信息，根据其中的<code>Expires</code>和<code>Cahe-control</code>判断是否命中强缓存，若命中则直接从缓存中获取资源</p></li><li><p>协商缓存<br> 如果没有命中强缓存，浏览器会发送请求到服务器，该请求会携带第一次请求返回的有关缓存的header字段信息（<code>Last-Modified</code>/<code>IF-Modified-Since</code>、<code>Etag</code>/<code>IF-None-Match</code>）,由服务器根据请求中的相关header信息来对比结果是否命中协商缓存，若命中，则服务器返回新的响应header信息更新缓存中的对应header信息，但是并不返回资源内容，它会告知浏览器可以直接从缓存获取；否则返回最新的资源内容</p></li></ol><h2 id="reflow-重排-和repaint-重绘"><a href="#reflow-重排-和repaint-重绘" class="headerlink" title="reflow(重排)和repaint(重绘)"></a>reflow(重排)和repaint(重绘)</h2><blockquote><p>reflow &amp; repaint<br><a href="https://www.jianshu.com/p/40c6fc1d4800" target="_blank" rel="noopener">https://www.jianshu.com/p/40c6fc1d4800</a><br><a href="http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html" target="_blank" rel="noopener">http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html</a></p></blockquote><h4 id="浏览器解析网页的过程"><a href="#浏览器解析网页的过程" class="headerlink" title="浏览器解析网页的过程"></a>浏览器解析网页的过程</h4><ol><li>HTML代码转化成DOM</li><li>CSS代码转化成CSSOM（CSS Object Model）</li><li>结合DOM和CSSOM，生成一棵渲染树（包含每个节点的视觉信息）</li><li>生成布局（layout），即将所有渲染树的所有节点进行平面合成</li><li>将布局绘制（paint）在屏幕上</li></ol><h4 id="重排与重绘"><a href="#重排与重绘" class="headerlink" title="重排与重绘"></a>重排与重绘</h4><ul><li><p>重排：渲染树的结点发生了结构性变化，例如宽度、高度或者位置上的变化时，那么会触发reflow(重排)的逻辑。第一次进入一个页面时便会至少触发一次重排。</p></li><li><p>重绘：渲染树结点发生了非结构性变化，例如背景色等的变化时，那么会触发repaint(重绘)。</p></li></ul><h2 id="AST（抽象语法树）"><a href="#AST（抽象语法树）" class="headerlink" title="AST（抽象语法树）"></a>AST（抽象语法树）</h2><h4 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h4><p>抽象语法树（<a href="http://www.iteye.com/news/30731" target="_blank" rel="noopener">Abstract Syntax Tree</a>）也称为AST语法树，指的是源代码语法所对应的树状结构。也就是说，对于一种具体编程语言下的源代码，通过构建语法树的形式将源代码中的语句映射到树中的每一个节点上</p><h4 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h4><p>抽象语法树的作用非常的多，比如编译器、IDE、压缩优化代码等。在JavaScript中，虽然我们并不会常常与AST直接打交道，但却也会经常的涉及到它。例如使用UglifyJS来压缩代码，实际这背后就是在对JavaScript的抽象语法树进行操作，例如 <a href="https://www.cnblogs.com/tugenhua0707/p/7863616.html" target="_blank" rel="noopener">Babel编译ES6的代码</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;浏览器缓存（协议层的缓存）&quot;&gt;&lt;a href=&quot;#浏览器缓存（协议层的缓存）&quot; class=&quot;headerlink&quot; title=&quot;浏览器缓存（协议层的缓存）&quot;&gt;&lt;/a&gt;浏览器缓存（协议层的缓存）&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;主要分为强缓存和协商缓存，
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>浏览器兼容性问题Q&amp;A</title>
    <link href="http://yangfan.site/2018/05/14/%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7%E9%97%AE%E9%A2%98Q-A/"/>
    <id>http://yangfan.site/2018/05/14/浏览器兼容性问题Q-A/</id>
    <published>2018-05-14T03:07:01.000Z</published>
    <updated>2019-04-25T09:00:59.687Z</updated>
    
    <content type="html"><![CDATA[<h1 id="浏览器兼容性问题Q-amp-A"><a href="#浏览器兼容性问题Q-amp-A" class="headerlink" title="浏览器兼容性问题Q&amp;A"></a>浏览器兼容性问题Q&amp;A</h1><h3 id="Date-对象时间格式差异性"><a href="#Date-对象时间格式差异性" class="headerlink" title="Date 对象时间格式差异性"></a><code>Date</code> 对象时间格式差异性</h3><p>Q:  </p><p>日期参数为 <code>yyyy/MM/dd hh:mm:ss</code> 格式时，IE浏览器不支持，chrome和firefox支持<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">"2018-05-05 12:25:23"</span>) <span class="comment">// Invalid Date</span></span><br></pre></td></tr></table></figure></p><p>日期参数为 <code>yyyy/MM/ddThh:mm:ss</code> 格式时，IE支持,chrome和firefox也支持</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">"2018-05-05T12:25:23"</span>) <span class="comment">// [date] Sat May 05 2018 12:25:23 GMT+0800 (中国标准时间)</span></span><br></pre></td></tr></table></figure><p>A:<br>原因：<br>各个浏览器对采用的时间格式标准解析不一致</p><p>解决方法：<br>最好采用ISO的标准时间格式<code>YYYY-MM-DDTHH:mm:ss.sssZ</code><br>或者使用时间戳代替</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">"2018-05-05T12:25:23.235Z"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// or</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="number">1525523123235</span>)</span><br></pre></td></tr></table></figure><h3 id="window-open-在异步代码中执行被浏览器拦截"><a href="#window-open-在异步代码中执行被浏览器拦截" class="headerlink" title="window.open 在异步代码中执行被浏览器拦截"></a><code>window.open</code> 在异步代码中执行被浏览器拦截</h3><p>Q:<br>下面方式打开新页面会被浏览器拦截<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 异步代码</span></span><br><span class="line"></span><br><span class="line">setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">window</span>.open(<span class="string">"http://www.sogou.com"</span>)</span><br><span class="line">&#125;,<span class="number">1001</span>)</span><br><span class="line"><span class="comment">// AJAX异步请求</span></span><br><span class="line"></span><br><span class="line">$.ajax(&#123;</span><br><span class="line">    url:<span class="string">"xxx"</span>,</span><br><span class="line">    success:<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">window</span>.open(<span class="string">"yyy"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p><p>A:<br>原因：<br>出于安全考虑浏览器会拦截掉非用户操作的行为 </p><p>解决方法：<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// window.open()先执行，打开一个空的窗口（例如 加载页）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> newWin = <span class="built_in">window</span>.open(<span class="string">'http://xxx.com/loading.html'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 然后等异步代码执行完再重定向 </span></span><br><span class="line"></span><br><span class="line">newWin.location.href = <span class="string">'http://www.baidu.com'</span></span><br></pre></td></tr></table></figure></p><h3 id="a-标签href属性为javascript-void-0-时，各浏览器处理方式不同"><a href="#a-标签href属性为javascript-void-0-时，各浏览器处理方式不同" class="headerlink" title="a 标签href属性为javascript:void(0) 时，各浏览器处理方式不同"></a><code>a</code> 标签href属性为<code>javascript:void(0)</code> 时，各浏览器处理方式不同</h3><p>Q:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"javascript:void(0)"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>&gt;</span>我是空链接，在这里当做一个按钮<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></p><p>firefox和IE浏览器会弹出一个新窗口</p><p>A:<br>原因：<br>浏览器默认处理事件的顺序有差异。<br>Chrome顺序：onclick -&gt; href -&gt; target<br>IE和Firefox顺序：onclick -&gt; target -&gt; href</p><p>解决方法：  </p><ol><li><p>添加onclick事件，直接return false阻止之后浏览器默认事件的执行</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">onclick</span>=<span class="string">"return false"</span> <span class="attr">href</span>=<span class="string">"javascript:void(0);"</span>&gt;</span>点我啊<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>去掉href属性</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span>&gt;</span>点我啊<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span>&gt;</span>点我啊<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="各浏览器对-table-不规范写法解析不一致"><a href="#各浏览器对-table-不规范写法解析不一致" class="headerlink" title="各浏览器对 table 不规范写法解析不一致"></a>各浏览器对 <code>table</code> 不规范写法解析不一致</h3><p>最好以W3C的标准来写HTML，不然浏览器对HTML解析有差异  </p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">table</span> <span class="attr">border</span>=<span class="string">"1"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">thead</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">th</span>&gt;</span>Month<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">th</span>&gt;</span>Savings<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">thead</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tbody</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span>&gt;</span>January<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span>&gt;</span>$100<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tbody</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tfoot</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span>&gt;</span>Sum<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span>&gt;</span>$180<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tfoot</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="鼠标事件-mouseout-和-mouseleave-区别"><a href="#鼠标事件-mouseout-和-mouseleave-区别" class="headerlink" title="鼠标事件 mouseout 和 mouseleave 区别"></a>鼠标事件 mouseout 和 mouseleave 区别</h3><ul><li><code>mouseleave</code> 只有鼠标移开被监听的元素时，才触发 （<code>mouseenter</code>同理）  </li><li><code>mouseout</code> 不论鼠标移开被监听元素，还是子元素，均会触发（<code>mouseover</code>同理） </li></ul><h3 id="window-URL-createObjectURL-new-Blob-在Microsoft-IE和Chrome-的区别-https-blog-csdn-net-u013131203-article-details-80894440"><a href="#window-URL-createObjectURL-new-Blob-在Microsoft-IE和Chrome-的区别-https-blog-csdn-net-u013131203-article-details-80894440" class="headerlink" title="window.URL.createObjectURL(new Blob) 在Microsoft IE和Chrome 的区别  https://blog.csdn.net/u013131203/article/details/80894440"></a>window.URL.createObjectURL(new Blob) 在Microsoft IE和Chrome 的区别  <a href="https://blog.csdn.net/u013131203/article/details/80894440" target="_blank" rel="noopener">https://blog.csdn.net/u013131203/article/details/80894440</a></h3><p>Chrome 带域名</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">URL.createObjectURL(<span class="keyword">new</span> Blob())</span><br><span class="line"><span class="comment">// "blob:https://note.youdao.com/e4132750-7b95-4595-b331-158267d8d9e3"</span></span><br></pre></td></tr></table></figure><p>ie不带域名</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">URL.createObjectURL(<span class="keyword">new</span> Blob())</span><br><span class="line"><span class="comment">// "blob:e4132750-7b95-4595-b331-158267d8d9e3"</span></span><br></pre></td></tr></table></figure><h3 id="IE浏览器缓存-get方式的XHR请求-https-www-cnblogs-com-bk233-p-7280595-html"><a href="#IE浏览器缓存-get方式的XHR请求-https-www-cnblogs-com-bk233-p-7280595-html" class="headerlink" title="IE浏览器缓存 get方式的XHR请求 https://www.cnblogs.com/bk233/p/7280595.html"></a>IE浏览器缓存 get方式的XHR请求 <a href="https://www.cnblogs.com/bk233/p/7280595.html" target="_blank" rel="noopener">https://www.cnblogs.com/bk233/p/7280595.html</a></h3><p>每次发请求时携带一个随机参数 例如  GET <a href="http://123.com?t=15123153156161" target="_blank" rel="noopener">http://123.com?t=15123153156161</a></p><h3 id="浅谈-AJAX-跨域请求时的-OPTIONS-方法-https-juejin-im-entry-58eaf351a22b9d0058a8e35c"><a href="#浅谈-AJAX-跨域请求时的-OPTIONS-方法-https-juejin-im-entry-58eaf351a22b9d0058a8e35c" class="headerlink" title="浅谈 AJAX 跨域请求时的 OPTIONS 方法 https://juejin.im/entry/58eaf351a22b9d0058a8e35c"></a>浅谈 AJAX 跨域请求时的 OPTIONS 方法 <a href="https://juejin.im/entry/58eaf351a22b9d0058a8e35c" target="_blank" rel="noopener">https://juejin.im/entry/58eaf351a22b9d0058a8e35c</a></h3><p><code>For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.</code><br>非简单请求必须先发送预检请求，如果发送的请求内容类型如果不是 <code>application/x-www-form-urlencoded</code>，<code>multipart/form-data</code> 或 <code>text/plain</code> 这三者的话，便会触发 OPTIONS 请求</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;浏览器兼容性问题Q-amp-A&quot;&gt;&lt;a href=&quot;#浏览器兼容性问题Q-amp-A&quot; class=&quot;headerlink&quot; title=&quot;浏览器兼容性问题Q&amp;amp;A&quot;&gt;&lt;/a&gt;浏览器兼容性问题Q&amp;amp;A&lt;/h1&gt;&lt;h3 id=&quot;Date-对象时间格式差异
      
    
    </summary>
    
    
      <category term="浏览器" scheme="http://yangfan.site/tags/%E6%B5%8F%E8%A7%88%E5%99%A8/"/>
    
      <category term="兼容性" scheme="http://yangfan.site/tags/%E5%85%BC%E5%AE%B9%E6%80%A7/"/>
    
  </entry>
  
  <entry>
    <title>入门级的git使用指北</title>
    <link href="http://yangfan.site/2018/05/08/%E5%85%A5%E9%97%A8%E7%BA%A7%E7%9A%84git%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8C%97/"/>
    <id>http://yangfan.site/2018/05/08/入门级的git使用指北/</id>
    <published>2018-05-08T04:08:03.000Z</published>
    <updated>2019-05-14T06:07:08.770Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>Git 一种免费的开源分布式版本控制系统</p></blockquote><h2 id="Config"><a href="#Config" class="headerlink" title="Config"></a>Config</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 全局配置 加 --global 标识</span></span><br><span class="line">$ git config --global user.name <span class="string">"your name"</span> </span><br><span class="line">$ git config --global user.email <span class="string">"xxx@xxx.xxx"</span></span><br><span class="line"><span class="comment"># 本地配置</span></span><br><span class="line">$ git config user.name <span class="string">"your name"</span></span><br><span class="line"><span class="comment"># 查看配置 --list,-l</span></span><br><span class="line">$ git config --list</span><br><span class="line"><span class="comment"># 查看指定项</span></span><br><span class="line">$ git config user.name</span><br><span class="line"><span class="comment"># 修改指定项</span></span><br><span class="line">$ git config core.eol lf <span class="comment"># git config &lt;key&gt; &lt;value&gt;</span></span><br><span class="line"><span class="comment"># 删除指定项</span></span><br><span class="line">$ git config --<span class="built_in">unset</span> core.eol <span class="comment"># git config --unset &lt;key&gt;</span></span><br></pre></td></tr></table></figure><h2 id="Basic"><a href="#Basic" class="headerlink" title="Basic"></a>Basic</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># init</span></span><br><span class="line">$ git init <span class="comment"># 创建一个空的Git仓库或重新初始化一个现有仓库</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># add remote origin</span></span><br><span class="line">$ git remote add origin https://github.com/username/xxxx.git <span class="comment"># 添加一个远程仓库 git remote add &lt;shortname&gt; &lt;远程版本库&gt;</span></span><br><span class="line">$ git remote <span class="comment"># 查看已经存在的远程分支</span></span><br><span class="line">$ git remote -v <span class="comment"># 查看已经存在的远程分支的详细信息 git remote -v | --verbose</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># pull</span></span><br><span class="line">$ git pull https://github.com/username/xxxx.git master <span class="comment"># 拉取数据</span></span><br><span class="line">$ git pull origin master <span class="comment"># origin 为你之前添加一个远程仓库的名字</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># add</span></span><br><span class="line">$ git add readme.txt <span class="comment"># 添加单个文件到本地暂存区</span></span><br><span class="line">$ git add . <span class="comment"># 添加所有修改、新增的文件到本地暂存区</span></span><br><span class="line">$ git add -u <span class="comment"># 添加所有修改、删除的文件到本地暂存区</span></span><br><span class="line">$ git add -A <span class="comment"># 添加所有修改、删除、新增文件到本地暂存区</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># commit</span></span><br><span class="line">git commit -m <span class="string">"注释"</span> <span class="comment"># 此次提交的备注</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># push</span></span><br><span class="line">git push -u origin master <span class="comment"># 将本地的master分支同步到origin所在主机的master分支</span></span><br></pre></td></tr></table></figure><h2 id="Diff"><a href="#Diff" class="headerlink" title="Diff"></a>Diff</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git diff <span class="comment"># 查看冲突</span></span><br></pre></td></tr></table></figure><h2 id="Branch"><a href="#Branch" class="headerlink" title="Branch"></a>Branch</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ git branch <span class="comment"># 查看所有分支（当前分支有星号标记 e.g. *master）</span></span><br><span class="line">$ git branch -a <span class="comment"># 查看所有分支（包括远程分支）</span></span><br><span class="line">$ git branch dev <span class="comment"># 创建分支</span></span><br><span class="line">$ git checkout dev  <span class="comment"># 切换到 dev 分支</span></span><br><span class="line">$ git checkout -b feature <span class="comment"># 新建并切换到 feature 分支 </span></span><br><span class="line">$ git branch -m feature <span class="built_in">test</span> <span class="comment"># 重命名   git branch -m &lt;旧名字&gt; &lt;新名字&gt;</span></span><br><span class="line">$ git branch -D <span class="built_in">test</span> <span class="comment"># 删除分支</span></span><br></pre></td></tr></table></figure><h2 id="Merge"><a href="#Merge" class="headerlink" title="Merge"></a>Merge</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git checkout master <span class="comment"># 切换到 mastet 分支</span></span><br><span class="line">$ git merge dev <span class="comment"># 将 dev 合并到 当前分支（这里是 master）</span></span><br></pre></td></tr></table></figure><h2 id="Clone"><a href="#Clone" class="headerlink" title="Clone"></a>Clone</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ git <span class="built_in">clone</span> http://xxx.xxx/xxx.git <span class="comment"># git clone &lt;版本库的网址&gt; &lt;本地目录名&gt;</span></span><br><span class="line">$ git <span class="built_in">clone</span> http://xxx.xxx/xxx.git mydir <span class="comment"># git clone &lt;版本库的网址&gt; &lt;本地目录名&gt;</span></span><br><span class="line">$ git <span class="built_in">clone</span> -b dev http://xxx.xxx/xxx.git <span class="comment">#git clone -b &lt;分支名称&gt; &lt;版本库的网址&gt;</span></span><br></pre></td></tr></table></figure><h2 id="View"><a href="#View" class="headerlink" title="View"></a>View</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git status <span class="comment"># 查看当前工作区提交状态</span></span><br><span class="line">$ git <span class="built_in">log</span> <span class="comment"># 查看提交历史记录</span></span><br></pre></td></tr></table></figure><h2 id="Undo"><a href="#Undo" class="headerlink" title="Undo"></a>Undo</h2><p>git add 之前 （工作区）<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git checkout -- a.js <span class="comment"># 撤销某个/某些文件的更改</span></span><br></pre></td></tr></table></figure></p><p>git add 之后，git commit 之前 （暂存区）<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git reset HEAD a.js <span class="comment"># 撤销某个/某些文件的添加</span></span><br></pre></td></tr></table></figure></p><p>git commit 之后 （本地仓库）<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git reset HEAD^ --hard <span class="comment"># 撤销本次提交（commit）</span></span><br><span class="line">$ git reset &lt;commit_id&gt; --hard <span class="comment"># 撤回到指定的 commit</span></span><br></pre></td></tr></table></figure></p><h2 id="Editor-amp-amp-Git-Config"><a href="#Editor-amp-amp-Git-Config" class="headerlink" title="Editor &amp;&amp; Git Config"></a>Editor &amp;&amp; Git Config</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ git config core.autocrlf <span class="literal">false</span> <span class="comment"># 禁止自动转换换行符</span></span><br><span class="line">$ git config core.safecrlf <span class="literal">true</span> <span class="comment"># 禁止换行符混用</span></span><br><span class="line">$ git config core.eol lf <span class="comment"># 设置换行符为 LF</span></span><br></pre></td></tr></table></figure><h2 id="Reset"><a href="#Reset" class="headerlink" title="Reset"></a>Reset</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git reset HEAD^</span><br><span class="line">$ git reset HEAD~2</span><br></pre></td></tr></table></figure><h2 id="Tag"><a href="#Tag" class="headerlink" title="Tag"></a>Tag</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 新建</span></span><br><span class="line">$ git tag v0.1 <span class="comment"># git tag &lt;tagname&gt;</span></span><br><span class="line">$ git tag -a v0.1 -m <span class="string">"0.1版本"</span> <span class="comment"># git tag -a &lt;tagname&gt; -m &lt;message&gt;</span></span><br><span class="line"><span class="comment"># 显示</span></span><br><span class="line">$ git show </span><br><span class="line">$ git show v0.1 <span class="comment"># git tag show &lt;tagname&gt;</span></span><br><span class="line"><span class="comment"># 删除</span></span><br><span class="line">$ git tag -d v0.1 <span class="comment"># git tag -d &lt;tagname&gt;</span></span><br><span class="line">$ git tag -d $(git tag -i) <span class="comment"># 删除所有 tag</span></span><br></pre></td></tr></table></figure><h2 id="Remote"><a href="#Remote" class="headerlink" title="Remote"></a>Remote</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 新建远程分支</span></span><br><span class="line">$ git push origin dev <span class="comment"># git push origin &lt;branchname&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除远程分支</span></span><br><span class="line">$ git push origin --delete dev</span><br><span class="line"></span><br><span class="line"><span class="comment"># 同步本地 tag 到远程</span></span><br><span class="line">$ git push orign v0.1 <span class="comment"># git push origin &lt;tagname&gt;</span></span><br><span class="line"><span class="comment"># 推送所有 tag 到远程</span></span><br><span class="line">$ git push origin --tags</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除远程 tag</span></span><br><span class="line">$ git push origin --delete v0.1 <span class="comment"># git push origin &lt;tagname&gt;</span></span><br><span class="line"><span class="comment"># 或者 本地删除，同步到远程</span></span><br><span class="line">$ git tag -d v0.1 <span class="comment"># git tag -d &lt;tagname&gt;</span></span><br><span class="line">$ git push origin :refs/tags/v0.1 <span class="comment"># git push origin :refs/tags/&lt;tagname&gt;</span></span><br><span class="line"><span class="comment"># 删除所有远程 tag</span></span><br><span class="line">$ git push origin --delete $(git tag -l)</span><br></pre></td></tr></table></figure><h2 id="Relationship"><a href="#Relationship" class="headerlink" title="Relationship"></a>Relationship</h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://user-gold-cdn.xitu.io/2018/10/28/166b9e70067850da?w=570&h=184&f=png&s=60462" alt="git-relationship" title>                </div>                <div class="image-caption">git-relationship</div>            </figure><h2 id="Refs"><a href="#Refs" class="headerlink" title="Refs"></a>Refs</h2><ol><li><a href="https://git-scm.com/docs" target="_blank" rel="noopener">git-scm</a></li><li><a href="https://www.yiibai.com/git/" target="_blank" rel="noopener">Git教程</a></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;Git 一种免费的开源分布式版本控制系统&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Config&quot;&gt;&lt;a href=&quot;#Config&quot; class=&quot;headerlink&quot; title=&quot;Config&quot;&gt;&lt;/a&gt;Config&lt;/h2&gt;&lt;f
      
    
    </summary>
    
    
      <category term="博客" scheme="http://yangfan.site/tags/%E5%8D%9A%E5%AE%A2/"/>
    
      <category term="Git" scheme="http://yangfan.site/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>Vue工程化开发（一）</title>
    <link href="http://yangfan.site/2018/01/12/Vue%E5%B7%A5%E7%A8%8B%E5%8C%96%E5%BC%80%E5%8F%91%EF%BC%88%E4%B8%80%EF%BC%89/"/>
    <id>http://yangfan.site/2018/01/12/Vue工程化开发（一）/</id>
    <published>2018-01-12T02:58:42.000Z</published>
    <updated>2019-04-25T08:59:38.253Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Vue工程化开发（一）"><a href="#Vue工程化开发（一）" class="headerlink" title="Vue工程化开发（一）"></a>Vue工程化开发（一）</h1><blockquote><p>利用Vue-cli脚手架在现有的MVC项目中进行前端开发</p></blockquote><h4 id="开发环境"><a href="#开发环境" class="headerlink" title="开发环境"></a>开发环境</h4><ul><li>Node</li><li>npm</li><li>Vue-cli</li></ul><h2 id="搭建项目"><a href="#搭建项目" class="headerlink" title="搭建项目"></a>搭建项目</h2><h4 id="1-首先在项目中搭建一个前台文件夹，用-vue-init-webpack-projectname-（例如-vue-init-webpack-frontend）"><a href="#1-首先在项目中搭建一个前台文件夹，用-vue-init-webpack-projectname-（例如-vue-init-webpack-frontend）" class="headerlink" title="1. 首先在项目中搭建一个前台文件夹，用 vue init webpack projectname （例如: vue init webpack frontend）"></a>1. 首先在项目中搭建一个前台文件夹，用 <code>vue init webpack projectname</code> （例如: <code>vue init webpack frontend</code>）</h4><p>frontend 为Vue-cli自动生成的项目文件<br>content 目录下存放打包后的资源文件<br>views目录下存放自动生成的cshtml文件  </p><p><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/webpack-vue-cli-004.png" alt> </p><h4 id="2-进入此文件夹（这里是-frontend）-配置-package-json-，安装所需插件"><a href="#2-进入此文件夹（这里是-frontend）-配置-package-json-，安装所需插件" class="headerlink" title="2. 进入此文件夹（这里是 frontend）   配置 package.json ，安装所需插件"></a>2. 进入此文件夹（这里是 frontend）   配置 package.json ，安装所需插件</h4><p><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/webpack-vue-cli-005.png" alt> </p><h4 id="3-修改打包配置-进入-config-index-js-修改如下"><a href="#3-修改打包配置-进入-config-index-js-修改如下" class="headerlink" title="3. 修改打包配置   进入 config/index.js     修改如下"></a>3. 修改打包配置   进入 config/index.js     修改如下</h4><p><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/webpack-vue-cli-001.jpg" alt></p><h4 id="4-在当前目录下新建一个模板页-index-cshtml-如下"><a href="#4-在当前目录下新建一个模板页-index-cshtml-如下" class="headerlink" title="4. 在当前目录下新建一个模板页 index.cshtml  如下"></a>4. 在当前目录下新建一个模板页 index.cshtml  如下</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/webpack-vue-cli-002.jpg" alt title>                </div>                <div class="image-caption"></div>            </figure>  <h4 id="5-修改打包html文件的配置-进入-build-webpack-prod-conf-js"><a href="#5-修改打包html文件的配置-进入-build-webpack-prod-conf-js" class="headerlink" title="5. 修改打包html文件的配置  进入 build/webpack.prod.conf.js"></a>5. 修改打包html文件的配置  进入 build/webpack.prod.conf.js</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/webpack-vue-cli-003.png" alt title>                </div>                <div class="image-caption"></div>            </figure> <h4 id="6-npm-run-dev-测试"><a href="#6-npm-run-dev-测试" class="headerlink" title="6. npm run dev  测试"></a>6. <code>npm run dev</code>  测试</h4><h4 id="7-npm-run-build-打包"><a href="#7-npm-run-build-打包" class="headerlink" title="7. npm run build 打包"></a>7. <code>npm run build</code> 打包</h4><h2 id="项目目录"><a href="#项目目录" class="headerlink" title="项目目录"></a>项目目录</h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/webpack-vue-cli-006.png" alt title>                </div>                <div class="image-caption"></div>            </figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Vue工程化开发（一）&quot;&gt;&lt;a href=&quot;#Vue工程化开发（一）&quot; class=&quot;headerlink&quot; title=&quot;Vue工程化开发（一）&quot;&gt;&lt;/a&gt;Vue工程化开发（一）&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;利用Vue-cli脚手架在现有的MVC项目
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>[转]如何监听DOM树改变</title>
    <link href="http://yangfan.site/2017/11/08/%E8%BD%AC-%E5%A6%82%E4%BD%95%E7%9B%91%E5%90%ACDOM%E6%A0%91%E6%94%B9%E5%8F%98/"/>
    <id>http://yangfan.site/2017/11/08/转-如何监听DOM树改变/</id>
    <published>2017-11-08T02:06:44.000Z</published>
    <updated>2019-04-25T09:00:43.702Z</updated>
    
    <content type="html"><![CDATA[<h1 id="如何监听DOM树改变-转"><a href="#如何监听DOM树改变-转" class="headerlink" title="如何监听DOM树改变[转]"></a>如何监听DOM树改变[转]</h1><h2 id="读前必看"><a href="#读前必看" class="headerlink" title="读前必看"></a>读前必看</h2><p>MutationObserver MDN<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver" target="_blank" rel="noopener">https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver</a>     </p><p>Mutation Observer API   <a href="http://javascript.ruanyifeng.com/dom/mutationobserver.html#toc10" target="_blank" rel="noopener">http://javascript.ruanyifeng.com/dom/mutationobserver.html#toc10</a></p><h2 id="1-概述"><a href="#1-概述" class="headerlink" title="1 概述"></a>1 概述</h2><p>Mutation observer 是用于代替 Mutation events 作为观察DOM树结构发生变化时，做出相应处理的API。为什么要使用mutation observer 去代替 mutation events 呢，我们先了解一下mutation events</p><p>Mutation Events</p><p>Mutation events 是在 DOM3中定义，用于监听DOM树结构变化的事件</p><h3 id="它简单的用法如下："><a href="#它简单的用法如下：" class="headerlink" title="它简单的用法如下："></a>它简单的用法如下：</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'list'</span>).addEventListener(<span class="string">"DOMSubtreeModified"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'列表中子元素被修改'</span>);</span><br><span class="line">&#125;, <span class="literal">false</span>);</span><br></pre></td></tr></table></figure><h3 id="Mutation-事件列表"><a href="#Mutation-事件列表" class="headerlink" title="Mutation 事件列表"></a>Mutation 事件列表</h3><p>DOMAttrModified<br>DOMAttributeNameChanged<br>DOMCharacterDataModified<br>DOMElementNameChanged<br>DOMNodeInserted<br>DOMNodeRemoved<br>DOMNodeInsertedIntoDocument<br>DOMSubtreeModified  </p><p>其中DOMNodeRemoved，DOMNodeInserted 和 DOMSubtreeModified 分别用于 监听元素子项的删除，新增，修改(包括删除和新增），<br>DOMAttrModified 是监听元素属性的修改，并且能够提供具体的修改动作。</p><h3 id="Mutation-Events遇到的问题"><a href="#Mutation-Events遇到的问题" class="headerlink" title="Mutation Events遇到的问题"></a>Mutation Events遇到的问题</h3><p>浏览器兼容性问题<br>IE9不支持Mutation Events<br>Webkit内核不支持DOMAttrModified特性，<br>DOMElementNameChanged和DOMAttributeNameChanged 在Firefox上不被支持。<br>性能问题</p><ol><li>Mutation Events是同步执行的，它的每次调用，都需要从事件队列中取出事件，执行，然后事件队列中移除，期间需要移动队列元素。如果事件触发的较为频繁的话，每一次都需要执行上面的这些步骤，那么浏览器会被拖慢。   </li><li>Mutation Events本身是事件，所以捕获是采用的是事件冒泡的形式，如果冒泡捕获期间又触发了其他的MutationEvents的话，很有可能就会导致阻塞Javascript线程，甚至导致浏览器崩溃。</li></ol><p><code>Mutation Observer</code></p><p>Mutation Observer 是在DOM4中定义的，用于替代 mutation events 的新API，它的不同于events的是，所有监听操作以及相应处理都是在其他脚本执行完成之后异步执行的，并且是所以变动触发之后，将变得记录在数组中，统一进行回调的，也就是说，当你使用observer监听多个DOM变化时，并且这若干个DOM发生了变化，那么observer会将变化记录到变化数组中，等待一起都结束了，然后一次性的从变化数组中执行其对应的回调函数。</p><p>Mutation Observer 的浏览器兼容范围</p><h3 id="兼容性"><a href="#兼容性" class="headerlink" title="兼容性"></a>兼容性</h3><h2 id="2-方法"><a href="#2-方法" class="headerlink" title="2 方法"></a>2 方法</h2><h3 id="构造函数"><a href="#构造函数" class="headerlink" title="构造函数"></a>构造函数</h3><p>用来实例化一个Mutation观察者对象，其中的参数是一个回调函数，它是会在指定的DOM节点发送变化后，执行的函数，并且会被传入两个参数，一个是变化记录数组(MutationRecord)，另一个是观察者对象本身</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">new</span> MutationObserver(<span class="function"><span class="keyword">function</span>(<span class="params">records, itself</span>)</span>&#123;&#125;);</span><br></pre></td></tr></table></figure><p><code>observe</code></p><p>在观察者对象上，注册需要观察的DOM节点，以及相应的参数</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">void</span> observe(Node target, optional MutationObserverInit options)</span><br></pre></td></tr></table></figure><p>其中的可选参数 MutationObserverInit的属性如下：</p><p><code>childLIst</code> 观察目标节点的子节点的新增和删除。<br><code>attributes</code> 观察目标节点的属性节点(新增或删除了某个属性,以及某个属性的属性值发生了变化)。<br><code>characterData</code> 如果目标节点为characterData节点(一种抽象接口,具体可以为文本节点,注释节点,以及处理指令节点)时,也要观察该节点的文本内容是否发生变化<br><code>subtree</code> 观察目标节点的所有后代节点(观察目标节点所包含的整棵DOM树上的上述三种节点变化)<br><code>attributeOldValue</code> 在attributes属性已经设为true的前提下, 将发生变化的属性节点之前的属性值记录下来(记录到下面MutationRecord对象的oldValue属性中)<br><code>characterDataOldValue</code> 在characterData属性已经设为true的前提下,将发生变化characterData节点之前的文本内容记录下来(记录到下面MutationRecord对象的oldValue属性中)<br><code>attributeFilter</code> 一个属性名数组(不需要指定命名空间),只有该数组中包含的属性名发生变化时才会被观察到,其他名称的属性发生变化后会被忽略想要设置那些删选参数的话，<br>如果想要使用哪个参数的话，就将其值设定为true  </p><p><code>disconnect</code></p><p>暂定在观察者对象上设置的节点的变化监听，直到重新调用observe方法</p><p><code>takeRecords</code></p><p>在观察者对象上调用takeRecords 会返回 其观察节点上的变化记录(MutationRecord)数组<br>其中MutationRecord数组也会作为，观察者初始化时的回调函数的第一个参数<br>其包含的属性如下：</p><p><code>type</code> 如果是属性发生变化,则返回attributes.如果是一个CharacterData节点发生变化,则返回characterData,如果是目标节点的某个子节点发生了变化,则返回childList.<br><code>target</code> 返回此次变化影响到的节点,具体返回那种节点类型是根据type值的不同而不同的,如果type为attributes,则返回发生变化的属性节点所在的元素节点,如果type值为characterData,则返回发生变化的这个characterData节点.如果type为childList,则返回发生变化的子节点的父节点.<br><code>addedNodes</code> 返回被添加的节点<br><code>removedNodes</code> 返回被删除的节点<br><code>previousSibling</code> 返回被添加或被删除的节点的前一个兄弟节点<br><code>nextSibling</code> 返回被添加或被删除的节点的后一个兄弟节点<br><code>attributeName</code> 返回变更属性的本地名称<br><code>oldValue</code> 根据type值的不同,返回的值也会不同.如果type为attributes,则返回该属性变化之前的属性值.如果type为characterData,则返回该节点变化之前的文本数据.如果type为childList,则返回null   </p><h2 id="3-使用实例"><a href="#3-使用实例" class="headerlink" title="3 使用实例"></a>3 使用实例</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// Firefox和Chrome早期版本中带有前缀</span></span><br><span class="line"><span class="keyword">var</span> MutationObserver = <span class="built_in">window</span>.MutationObserver || <span class="built_in">window</span>.WebKitMutationObserver || <span class="built_in">window</span>.MozMutationObserver</span><br><span class="line"><span class="comment">// 选择目标节点</span></span><br><span class="line"><span class="keyword">var</span> target = <span class="built_in">document</span>.querySelector(<span class="string">'#some-id'</span>); </span><br><span class="line"><span class="comment">// 创建观察者对象</span></span><br><span class="line"><span class="keyword">var</span> observer = <span class="keyword">new</span> MutationObserver(<span class="function"><span class="keyword">function</span>(<span class="params">mutations</span>) </span>&#123;  </span><br><span class="line">  mutations.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">mutation</span>) </span>&#123; </span><br><span class="line">    <span class="built_in">console</span>.log(mutation.type); </span><br><span class="line">  &#125;); </span><br><span class="line">&#125;); </span><br><span class="line"><span class="comment">// 配置观察选项:</span></span><br><span class="line"><span class="keyword">var</span> config = &#123; <span class="attr">attributes</span>: <span class="literal">true</span>, <span class="attr">childList</span>: <span class="literal">true</span>, <span class="attr">characterData</span>: <span class="literal">true</span> &#125; </span><br><span class="line"><span class="comment">// 传入目标节点和观察选项</span></span><br><span class="line">observer.observe(target, config); </span><br><span class="line"><span class="comment">// 随后,你还可以停止观察</span></span><br><span class="line">observer.disconnect();</span><br></pre></td></tr></table></figure><p>原文：<a href="http://www.jianshu.com/p/b5c9e4c7b1e1" target="_blank" rel="noopener">http://www.jianshu.com/p/b5c9e4c7b1e1</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;如何监听DOM树改变-转&quot;&gt;&lt;a href=&quot;#如何监听DOM树改变-转&quot; class=&quot;headerlink&quot; title=&quot;如何监听DOM树改变[转]&quot;&gt;&lt;/a&gt;如何监听DOM树改变[转]&lt;/h1&gt;&lt;h2 id=&quot;读前必看&quot;&gt;&lt;a href=&quot;#读前必看&quot; c
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>axios 入门</title>
    <link href="http://yangfan.site/2017/10/12/axios-%E5%85%A5%E9%97%A8/"/>
    <id>http://yangfan.site/2017/10/12/axios-入门/</id>
    <published>2017-10-12T01:00:50.000Z</published>
    <updated>2019-04-25T08:59:38.228Z</updated>
    
    <content type="html"><![CDATA[<h1 id="axios-入门"><a href="#axios-入门" class="headerlink" title="axios 入门"></a>axios 入门</h1><h4 id="请忽略大图，不只是Vue，其他js均可用"><a href="#请忽略大图，不只是Vue，其他js均可用" class="headerlink" title="请忽略大图，不只是Vue，其他js均可用"></a>请忽略大图，不只是Vue，其他js均可用</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://devdojo.com/media/images/June2017/vue-js-and-ajax-requests.jpg?fm=jpg&q=70&s=587cf6e4e2ed983ae163ebc0ebef71a8" alt="001" title>                </div>                <div class="image-caption">001</div>            </figure><h4 id="Editor-Yangfan-2017-08-17"><a href="#Editor-Yangfan-2017-08-17" class="headerlink" title="Editor: Yangfan 2017-08-17"></a>Editor: Yangfan 2017-08-17</h4><h4 id="Intro-本文档参考axios的官方文档和网上的axios使用教程所写，后续还会不断完善，鄙人水平有限，还望批评指正"><a href="#Intro-本文档参考axios的官方文档和网上的axios使用教程所写，后续还会不断完善，鄙人水平有限，还望批评指正" class="headerlink" title="Intro: 本文档参考axios的官方文档和网上的axios使用教程所写，后续还会不断完善，鄙人水平有限，还望批评指正"></a>Intro: 本文档参考axios的官方文档和网上的axios使用教程所写，后续还会不断完善，鄙人水平有限，还望批评指正</h4><hr><p><strong>强烈建议查看完整文档，链接如下</strong></p><p>英文原文档： <a href="https://github.com/mzabriskie/axios" target="_blank" rel="noopener">https://github.com/mzabriskie/axios</a>   </p><p>中文文档：<br><a href="https://www.awesomes.cn/repo/mzabriskie/axios" target="_blank" rel="noopener">https://www.awesomes.cn/repo/mzabriskie/axios</a><br><a href="https://segmentfault.com/a/1190000008470355" target="_blank" rel="noopener">https://segmentfault.com/a/1190000008470355</a>    </p><hr><h2 id="什么是axios"><a href="#什么是axios" class="headerlink" title="什么是axios"></a>什么是axios</h2><p>引用axios的介绍：</p><blockquote><p>Promise based HTTP client for the browser and node.js</p></blockquote><p>axios是一个基于ES6的Promise的网络请求库，是一个ajax库。</p><p>可以实现：</p><ul><li><p>在浏览器里建立XHR</p></li><li><p>通过nodejs进行http请求</p></li></ul><p>甚至可以实现：</p><ul><li><p>转换或者拦截请求数据或响应数据</p></li><li><p>支持Promise的API</p></li><li><p>可以取消请求</p></li><li><p>自动转换JSON</p></li><li><p>可以防御XSRF攻击！</p></li></ul><p>浏览器支持也没什么问题，IE这种本时代异端都能支持到8+，这问题是不大了。（VUE支持到9+！）</p><table><thead><tr><th><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.github.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="Chrome](https://raw.github.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/src/safari/safari_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Edge](https://raw.github.com/alrra/browser-logos/master/src/edge/edge_48x48.png) | ![IE" title>                </div>                <div class="image-caption">Chrome](https://raw.github.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/src/safari/safari_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Edge](https://raw.github.com/alrra/browser-logos/master/src/edge/edge_48x48.png) | ![IE</div>            </figure></th></tr></thead><tbody><tr><td>Latest ✔</td><td>Latest ✔</td><td>Latest ✔</td><td>Latest ✔</td><td>Latest ✔</td><td>8+ ✔</td><td></td></tr></tbody></table><p>[<figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://saucelabs.com/u/axios" alt="Browser Matrix](https://saucelabs.com/open_sauce/build_matrix/axios.svg)" title>                </div>                <div class="image-caption">Browser Matrix](https://saucelabs.com/open_sauce/build_matrix/axios.svg)</div>            </figure></p><h2 id="怎么用"><a href="#怎么用" class="headerlink" title="怎么用"></a>怎么用</h2><h3 id="方法一-npm安装"><a href="#方法一-npm安装" class="headerlink" title="方法一  npm安装"></a>方法一  npm安装</h3><ol><li>npm下载</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install axios</span><br></pre></td></tr></table></figure><ol start="2"><li>webpack之类的打包工具导入</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">'axios'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// or</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> axios=<span class="built_in">require</span>(<span class="string">'axios'</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//===============Vue===================</span></span><br><span class="line"><span class="comment">// Vue全局引用及使用</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">'axios'</span></span><br><span class="line">Vue.prototype.$http = axios</span><br><span class="line"></span><br><span class="line"><span class="keyword">this</span>.$http.get(<span class="string">'/user?ID=12345'</span>)</span><br><span class="line">  .then(<span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(response);</span><br><span class="line">  &#125;)</span><br><span class="line">  .catch(<span class="function"><span class="keyword">function</span> (<span class="params">error</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(error);</span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure><h3 id="方法二-script标签引入"><a href="#方法二-script标签引入" class="headerlink" title="方法二  script标签引入"></a>方法二  script标签引入</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://unpkg.com/axios/dist/axios.min.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="用法及DEMO"><a href="#用法及DEMO" class="headerlink" title="用法及DEMO"></a>用法及DEMO</h2><h3 id="简单的demo"><a href="#简单的demo" class="headerlink" title="简单的demo"></a>简单的demo</h3><p><strong>一个简单的HTTP GET请求</strong></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 法一 请求参数写到url中</span></span><br><span class="line"></span><br><span class="line">axios.get(<span class="string">'http://getRes.php?id=123456&amp;name=Yangfan'</span>).then(<span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求成功的数据</span></span><br><span class="line">&#125;).catch(<span class="function"><span class="keyword">function</span> (<span class="params">error</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求失败的失败信息</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 法二 请求参数写到axios配置参数中</span></span><br><span class="line"></span><br><span class="line">axios.get(<span class="string">'http://getRes.php'</span>，&#123;</span><br><span class="line">  params:&#123;</span><br><span class="line">    id:<span class="number">123456</span>,</span><br><span class="line">    name:<span class="string">"Yangfan"</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求成功的数据</span></span><br><span class="line">&#125;).catch(<span class="function"><span class="keyword">function</span> (<span class="params">error</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求失败的失败信息</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p><strong>一个简单的HTTP POST 请求</strong></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">axios.post(<span class="string">'http://getRes.php'</span>,&#123;</span><br><span class="line">  id:<span class="number">123456</span>,</span><br><span class="line">  name:<span class="string">"Yangfan"</span></span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求成功的数据</span></span><br><span class="line">&#125;).catch(<span class="function"><span class="keyword">function</span> (<span class="params">error</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求失败的失败信息</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p><strong>自定义请求配置</strong></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 配置</span></span><br><span class="line"><span class="keyword">var</span> config=&#123;</span><br><span class="line">  method: <span class="string">'GET'</span>,  <span class="comment">// 请求方法                                           </span></span><br><span class="line">  url: <span class="string">'http://getRes.php'</span>,  <span class="comment">// 请求url                          </span></span><br><span class="line">  headers: &#123; </span><br><span class="line">    token: <span class="string">'ftv1443qby6bdfa41t90sfvq89hg3h54u989m9imog79g4'</span>   <span class="comment">// 请求头                                              </span></span><br><span class="line">  &#125;,</span><br><span class="line">  data: &#123;         <span class="comment">// 需要传递的数据                                 </span></span><br><span class="line">    id: <span class="number">123456</span>,</span><br><span class="line">    name: <span class="string">'Yangfan'</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">axios(config).then(<span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求成功的数据</span></span><br><span class="line">&#125;).catch(<span class="function"><span class="keyword">function</span> (<span class="params">error</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// TODO</span></span><br><span class="line">  <span class="comment">// 返回HTTP请求失败的失败信息</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h2 id="完整配置"><a href="#完整配置" class="headerlink" title="完整配置"></a>完整配置</h2><table><br>    <thead><br>        <tr><br>            <th>参数</th><br>            <th>类型</th><br>            <th>注解</th><br>        </tr><br>    </thead><br>    <tbody><br>        <tr><br>            <td>url</td><br>            <td>String</td><br>            <td><code>url</code>是服务器链接，用来请求</td><br>        </tr><br>        <tr><br>            <td>method</td><br>            <td>String</td><br>            <td><code>method</code>是发起请求时的请求方法</td><br>        </tr><br>        <tr><br>            <td>baseURL</td><br>            <td>String</td><br>            <td><code>baseURL</code>如果<code>url</code>不是绝对地址，那么将会加在其前面。</td><br>        </tr><br>        <tr><br>            <td>transformRequest</td><br>            <td>Function</td><br>            <td><code>transformRequest</code>允许请求的数据在传到服务器之前进行转化。</td><br>        </tr><br>        <tr><br>            <td>transformResponse</td><br>            <td>Function</td><br>            <td><code>transformResponse</code>允许返回的数据传入then/catch之前进行处理</td><br>        </tr><br>        <tr><br>            <td>headers</td><br>            <td>Object</td><br>            <td><code>headers</code>是自定义的要被发送的头信息</td><br>        </tr><br>        <tr><br>            <td>params</td><br>            <td>Object</td><br>            <td><code>params</code>是请求连接中的请求参数，必须是一个纯对象，或者URLSearchParams对象</td><br>        </tr><br>        <tr><br>            <td>paramsSerializer</td><br>            <td>Function</td><br>            <td><code>paramsSerializer</code>是一个可选的函数，是用来序列化参数</td><br>        </tr><br>        <tr><br>            <td>data</td><br>            <td>Object</td><br>            <td><code>data</code>是请求提需要设置的数据<br>    <br>只适用于应用的’PUT’,’POST’,’PATCH’，请求方法<br>    <br>当没有设置<code>transformRequest</code>时，必须是以下其中之一的类型（不可重复？）：<br>    <br>-string,plain object,ArrayBuffer,ArrayBufferView,URLSearchParams<br>    <br>-仅浏览器：FormData,File,Blob<br>    <br>-仅Node：Stream</td><br>        </tr><br>        <tr><br>            <td>timeout</td><br>            <td>Number</td><br>            <td><code>timeout</code>定义请求的时间，单位是毫秒。</td><br>        </tr><br>        <tr><br>            <td>withCredentials</td><br>            <td>Boolean</td><br>            <td><code>withCredentials</code>表明是否跨网站访问协议，</td><br>        </tr><br>        <tr><br>            <td>adapter</td><br>            <td>Function</td><br>            <td><code>adapter</code>适配器，允许自定义处理请求，这会使测试更简单。</td><br>        </tr><br>        <tr><br>            <td>auth</td><br>            <td>Object</td><br>            <td><code>auth</code>表明HTTP基础的认证应该被使用，并且提供证书。<br>    <br>这个会设置一个<code>authorization</code> 头（header），并且覆盖你在header设置的Authorization头信息。</td><br>        </tr><br>        <tr><br>            <td>responseType</td><br>            <td>String</td><br>            <td><code>responsetype</code>表明服务器返回的数据类型，这些类型的设置应该是<br>    <br>‘arraybuffer’,’blob’,’document’,’json’,’text’,stream’</td><br>        </tr><br>        <tr><br>            <td>xsrfCookieName</td><br>            <td>String</td><br>            <td><code>xsrfCookieName</code>是cookie名，用作xsrf token值</td><br>        </tr><br>        <tr><br>            <td>xsrfHeaderName</td><br>            <td>String</td><br>            <td><code>xsrfHeaderName</code> 是http头（header）的名字，并且该头携带xsrf的值</td><br>        </tr><br>        <tr><br>            <td>onUploadProgress</td><br>            <td>Function</td><br>            <td><code>onUploadProgress</code>允许处理上传过程的事件</td><br>        </tr><br>        <tr><br>            <td>onDownloadProgress</td><br>            <td>Function</td><br>            <td><code>onDownloadProgress</code>允许处理下载过程的事件</td><br>        </tr><br>        <tr><br>            <td>maxContentLength</td><br>            <td>Number</td><br>            <td><code>maxContentLength</code> 定义http返回内容的最大容量</td><br>        </tr><br>        <tr><br>            <td>validateStatus</td><br>            <td>Function</td><br>            <td><code>validateStatus</code> 定义promise的resolve和reject。<br>    <br>http返回状态码，如果<code>validateStatus</code>返回true（或者设置成null/undefined），promise将会接受；其他的promise将会拒绝。</td><br>        </tr><br>        <tr><br>            <td>maxRedirects</td><br>            <td>Number</td><br>            <td><code>maxRedirects</code>定义了node.js中要重定向的最大数量。<br>  <br>如果设置为0，则不会重定向。</td><br>        </tr><br>        <tr><br>            <td>httpAgent</td><br>            <td>Object</td><br>            <td><code>httpAgent</code> 和 <code>httpsAgent</code>当产生一个http或者https请求时分别定义一个自定义的代理，在nodejs中。<br>    <br>这个允许设置一些选选个，像是<code>keepAlive</code>–这个在默认中是没有开启的。</td><br>        </tr><br>        <tr><br>            <td>httpsAgent</td><br>            <td>Object</td><br>            <td><code>httpAgent</code> 和 <code>httpsAgent</code>当产生一个http或者https请求时分别定义一个自定义的代理，在nodejs中。<br>    <br>这个允许设置一些选选个，像是<code>keepAlive</code>–这个在默认中是没有开启的。</td><br>        </tr><br>        <tr><br>            <td>proxy</td><br>            <td>Object</td><br>            <td><code>proxy</code>定义服务器的主机名字和端口号。<br>    <br><code>auth</code>表明HTTP基本认证应该跟<code>proxy</code>相连接，并且提供证书。<br>    <br>这个将设置一个’Proxy-Authorization’头(header)，覆盖原先自定义的。</td><br>        </tr><br>        <tr><br>            <td>cancelToken</td><br>            <td>Function</td><br>            <td><code>cancelTaken</code> 定义一个取消，能够用来取消请求</td><br>        </tr><br>    </tbody><br></table><h2 id="返回结果"><a href="#返回结果" class="headerlink" title="返回结果"></a>返回结果</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">  <span class="comment">// 服务器返回的数据                                        </span></span><br><span class="line">  data: &#123;&#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 服务器返回的状态码                              </span></span><br><span class="line">  status: <span class="number">200</span>,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 服务器返回的状态信息                                                                     </span></span><br><span class="line">  statusText: <span class="string">'OK'</span>,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 服务器返回的响应头信息                      </span></span><br><span class="line">  headers: &#123;&#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// `config`是提供给`axios`的请求的配置</span></span><br><span class="line">  config: &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;axios-入门&quot;&gt;&lt;a href=&quot;#axios-入门&quot; class=&quot;headerlink&quot; title=&quot;axios 入门&quot;&gt;&lt;/a&gt;axios 入门&lt;/h1&gt;&lt;h4 id=&quot;请忽略大图，不只是Vue，其他js均可用&quot;&gt;&lt;a href=&quot;#请忽略大图，不只是
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>[转]如何监听JS变量的变化</title>
    <link href="http://yangfan.site/2017/09/20/%E8%BD%AC-%E5%A6%82%E4%BD%95%E7%9B%91%E5%90%ACJS%E5%8F%98%E9%87%8F%E7%9A%84%E5%8F%98%E5%8C%96/"/>
    <id>http://yangfan.site/2017/09/20/转-如何监听JS变量的变化/</id>
    <published>2017-09-20T06:04:08.000Z</published>
    <updated>2019-04-25T09:00:39.711Z</updated>
    
    <content type="html"><![CDATA[<h1 id="如何监听JS变量的变化-转"><a href="#如何监听JS变量的变化-转" class="headerlink" title="如何监听JS变量的变化[转]"></a>如何监听JS变量的变化[转]</h1><h2 id="读前必看"><a href="#读前必看" class="headerlink" title="读前必看"></a>读前必看</h2><p>Object.defineProperty()  <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty" target="_blank" rel="noopener">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty</a></p><h2 id="如何监听-js-中变量的变化"><a href="#如何监听-js-中变量的变化" class="headerlink" title="如何监听 js 中变量的变化?"></a>如何监听 js 中变量的变化?</h2><p>我现在有这样一个需求，需要监控js的某个变量的改变，如果该变量发生变化，则触发一些事件，不能使用timeinterval之类的定时去监控的方法，不知道有比较好的解决方案么？</p><p>这个问题问的很好。</p><p>流行的MVVM的JS库/框架都有共同的特点就是数据绑定，在数据变更后响应式的自动进行相关计算并变更DOM展现。所以这个问题也可以理解为如何实现MVVM库/框架的数据绑定。</p><p>常见的数据绑定的实现有脏值检测，基于ES5的getter和setter，以及ES已被废弃的Object.observe，和ES6中添加的Proxy。</p><h2 id="脏值检测"><a href="#脏值检测" class="headerlink" title="脏值检测"></a>脏值检测</h2><p>angular使用的就是脏值检测，原理是比较新值和旧值，当值真的发生改变时再去更改DOM，所以angular中有一个$digest。那么为什么在像ng-click这样的内置指令在触发后会自动变更呢？原理也很简单，在ng-click这样的内置指令中最后追加了$digest。</p><p>简易的实现一个脏值检测：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">title</span>&gt;</span>two-way binding<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">body</span> <span class="attr">onload</span>=<span class="string">"init()"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">ng-click</span>=<span class="string">"inc"</span>&gt;</span></span><br><span class="line">            Increase</span><br><span class="line">        <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">ng-click</span>=<span class="string">"reset"</span>&gt;</span></span><br><span class="line">            Reset</span><br><span class="line">        <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">span</span> <span class="attr">style</span>=<span class="string">"color:red"</span> <span class="attr">ng-bind</span>=<span class="string">"counter"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">span</span> <span class="attr">style</span>=<span class="string">"color:blue"</span> <span class="attr">ng-bind</span>=<span class="string">"counter"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">span</span> <span class="attr">style</span>=<span class="string">"color:green"</span> <span class="attr">ng-bind</span>=<span class="string">"counter"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">            <span class="comment">/* 数据模型区开始 */</span></span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> counter = <span class="number">0</span>;</span></span><br><span class="line"><span class="javascript">            <span class="function"><span class="keyword">function</span> <span class="title">inc</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="undefined">                counter++;</span></span><br><span class="line"><span class="undefined">            &#125;</span></span><br><span class="line"><span class="javascript">            <span class="function"><span class="keyword">function</span> <span class="title">reset</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="undefined">                counter = 0;</span></span><br><span class="line"><span class="undefined">            &#125;</span></span><br><span class="line"><span class="javascript">            <span class="comment">/* 数据模型区结束 */</span></span></span><br><span class="line"><span class="javascript">            <span class="comment">/* 绑定关系区开始 */</span></span></span><br><span class="line"><span class="javascript">            <span class="function"><span class="keyword">function</span> <span class="title">init</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="undefined">                bind();</span></span><br><span class="line"><span class="undefined">            &#125;</span></span><br><span class="line"><span class="javascript">            <span class="function"><span class="keyword">function</span> <span class="title">bind</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="keyword">var</span> list = <span class="built_in">document</span>.querySelectorAll(<span class="string">"[ng-click]"</span>);</span></span><br><span class="line"><span class="javascript">                <span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">0</span>; i&lt;list.length; i++) &#123;</span></span><br><span class="line"><span class="javascript">                    list[i].onclick = (<span class="function"><span class="keyword">function</span>(<span class="params">index</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                        <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                            <span class="built_in">window</span>[list[index].getAttribute(<span class="string">"ng-click"</span>)]();</span></span><br><span class="line"><span class="undefined">                            apply();</span></span><br><span class="line"><span class="undefined">                        &#125;;</span></span><br><span class="line"><span class="undefined">                    &#125;)(i);</span></span><br><span class="line"><span class="undefined">                &#125;</span></span><br><span class="line"><span class="undefined">            &#125;</span></span><br><span class="line"><span class="javascript">            <span class="function"><span class="keyword">function</span> <span class="title">apply</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="keyword">var</span> list = <span class="built_in">document</span>.querySelectorAll(<span class="string">"[ng-bind='counter']"</span>);</span></span><br><span class="line"><span class="javascript">                <span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">0</span>; i&lt;list.length; i++) &#123;</span></span><br><span class="line"><span class="javascript">                    <span class="keyword">if</span> (list[i].innerHTML != counter) &#123;</span></span><br><span class="line"><span class="undefined">                        list[i].innerHTML = counter;</span></span><br><span class="line"><span class="undefined">                    &#125;</span></span><br><span class="line"><span class="undefined">                &#125;</span></span><br><span class="line"><span class="undefined">            &#125;</span></span><br><span class="line"><span class="javascript">            <span class="comment">/* 绑定关系区结束 */</span></span></span><br><span class="line"><span class="undefined">        </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这样做的坏处是自己变更数据后，是无法自动改变DOM的，必须要想办法触发apply()，所以只能借助ng-click的包装，在ng-click中包含真实的click事件监听并追加脏值检测以判断是否要更新DOM。</p><p>另外一个坏处是如果不注意，每次脏值检测会检测大量的数据，而很多数据是没有检测的必要的，容易影响性能。</p><p>关于如何实现一个和angular一样的脏值检测，知道原理后还有很多工作要去做，以及如何优化等等。如果有兴趣可以看看民工叔曾经推荐的《Build Your Own Angular.js》，第一章Scope便讲了如何实现angular的作用域和脏值检测。对了，上面的例子也是从民工叔的博客稍加修改来的，建议最后去看下原文，链接在参考资料中。</p><p>ES5的getter与setter<br>在ES5中新增了一个Object.defineProperty，直接在一个对象上定义一个新属性，或者修改一个已经存在的属性， 并返回这个对象。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.defineProperty(obj, prop, descriptor)</span><br></pre></td></tr></table></figure><p>其接受的第三个参数可以取get和set并各自对应一个getter和setter方法：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">var</span> a = &#123; <span class="attr">zhihu</span>:<span class="number">0</span> &#125;;</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(a, <span class="string">'zhihu'</span>, &#123;</span><br><span class="line">  <span class="keyword">get</span>: function() &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'get：'</span> + zhihu);</span><br><span class="line">    <span class="keyword">return</span> zhihu;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="keyword">set</span>: function(value) &#123;</span><br><span class="line">    zhihu = value;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'set:'</span> + zhihu);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line">a.zhihu = <span class="number">2</span>; <span class="comment">// set:2</span></span><br><span class="line"><span class="built_in">console</span>.log(a.zhihu); <span class="comment">// get：2</span></span><br><span class="line">                      <span class="comment">// 2</span></span><br></pre></td></tr></table></figure><p>基于ES5的getter和setter可以说几乎完美符合了要求。为什么要说几乎呢？</p><p>首先IE8及更低版本IE是无法使用的，而且这个特性是没有polyfill的，无法在不支持的平台实现，<br>这也是基于ES5getter和setter的Vue.js不支持IE8及更低版本IE的原因。也许有人会提到avalon，avalon在低版本IE借助vbscript一些黑魔法实现了类似的功能。</p><p>除此之外，还有一个问题就是修改数组的length，直接用索引设置元素如items[0] = {}，以及数组的push等变异方法是无法触发setter的。<br>如果想要解决这个问题可以参考Vue的做法，在Vue的observer/array.js中，Vue直接修改了数组的原型方法：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">const</span> arrayProto = <span class="built_in">Array</span>.prototype</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> arrayMethods = <span class="built_in">Object</span>.create(arrayProto)</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Intercept mutating methods and emit events</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">;[</span><br><span class="line">  <span class="string">'push'</span>,</span><br><span class="line">  <span class="string">'pop'</span>,</span><br><span class="line">  <span class="string">'shift'</span>,</span><br><span class="line">  <span class="string">'unshift'</span>,</span><br><span class="line">  <span class="string">'splice'</span>,</span><br><span class="line">  <span class="string">'sort'</span>,</span><br><span class="line">  <span class="string">'reverse'</span></span><br><span class="line">]</span><br><span class="line">.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">method</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// cache original method</span></span><br><span class="line">  <span class="keyword">var</span> original = arrayProto[method]</span><br><span class="line">  def(arrayMethods, method, <span class="function"><span class="keyword">function</span> <span class="title">mutator</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">// avoid leaking arguments:</span></span><br><span class="line">    <span class="comment">// http://jsperf.com/closure-with-arguments</span></span><br><span class="line">    <span class="keyword">var</span> i = <span class="built_in">arguments</span>.length</span><br><span class="line">    <span class="keyword">var</span> args = <span class="keyword">new</span> <span class="built_in">Array</span>(i)</span><br><span class="line">    <span class="keyword">while</span> (i--) &#123;</span><br><span class="line">      args[i] = <span class="built_in">arguments</span>[i]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> result = original.apply(<span class="keyword">this</span>, args)</span><br><span class="line">    <span class="keyword">var</span> ob = <span class="keyword">this</span>.__ob__</span><br><span class="line">    <span class="keyword">var</span> inserted</span><br><span class="line">    <span class="keyword">switch</span> (method) &#123;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">'push'</span>:</span><br><span class="line">        inserted = args</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line">      <span class="keyword">case</span> <span class="string">'unshift'</span>:</span><br><span class="line">        inserted = args</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line">      <span class="keyword">case</span> <span class="string">'splice'</span>:</span><br><span class="line">        inserted = args.slice(<span class="number">2</span>)</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (inserted) ob.observeArray(inserted)</span><br><span class="line">    <span class="comment">// notify change</span></span><br><span class="line">    ob.dep.notify()</span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>这样重写了原型方法，在执行数组变异方法后依然能够触发视图的更新。</p><p>但是这样还是不能解决修改数组的length和直接用索引设置元素如items[0] = {}的问题，想要解决依然可以参考Vue的做法：<br>前一个问题可以直接用新的数组代替旧的数组；后一个问题可以为数组拓展一个$set方法，在执行修改后顺便触发视图的更新。</p><p>已被废弃的Object.observe<br>Object.observe曾在ES7的草案中，并在提议中进展到stage2，最终依然被废弃。<br>这里只举一个MDN上的例子：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 一个数据模型</span></span><br><span class="line"><span class="keyword">var</span> user = &#123;</span><br><span class="line">  id: <span class="number">0</span>,</span><br><span class="line">  name: <span class="string">'Brendan Eich'</span>,</span><br><span class="line">  title: <span class="string">'Mr.'</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// 创建用户的greeting</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">updateGreeting</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  user.greeting = <span class="string">'Hello, '</span> + user.title + <span class="string">' '</span> + user.name + <span class="string">'!'</span>;</span><br><span class="line">&#125;</span><br><span class="line">updateGreeting();</span><br><span class="line"><span class="built_in">Object</span>.observe(user, <span class="function"><span class="keyword">function</span>(<span class="params">changes</span>) </span>&#123;</span><br><span class="line">  changes.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">change</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 当name或title属性改变时, 更新greeting</span></span><br><span class="line">    <span class="keyword">if</span> (change.name === <span class="string">'name'</span> || change.name === <span class="string">'title'</span>) &#123;</span><br><span class="line">      updateGreeting();</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>由于是已经废弃了的特性，Chrome虽然曾经支持但也已经废弃了支持，这里不再讲更多，有兴趣可以搜一搜以前的文章，这曾经是一个被看好的特性（Object.observe()带来的数据绑定变革）。<br>当然关于它也有一些替代品Polymer/observe-js。</p><p>ES6带来的Proxy<br>人如其名，类似HTTP中的代理：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">var</span> p = <span class="keyword">new</span> <span class="built_in">Proxy</span>(target, handler);</span><br><span class="line">target为目标对象，可以是任意类型的对象，比如数组，函数，甚至是另外一个代理对象。</span><br><span class="line">handler为处理器对象，包含了一组代理方法，分别控制所生成代理对象的各种行为。</span><br></pre></td></tr></table></figure><p>举个例子：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">let</span> a = <span class="keyword">new</span> <span class="built_in">Proxy</span>(&#123;&#125;, &#123;</span><br><span class="line">  <span class="keyword">set</span>: function(obj, prop, value) &#123;</span><br><span class="line">    obj[prop] = value;</span><br><span class="line">    <span class="keyword">if</span> (prop === <span class="string">'zhihu'</span>) &#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="string">"set "</span> + prop + <span class="string">": "</span> + obj[prop]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line">a.zhihu = <span class="number">100</span>;</span><br></pre></td></tr></table></figure><p>当然，Proxy的能力远不止此，还可以实现代理转发等等。</p><p>但是要注意的是目前浏览器中只有Firefox18支持这个特性，而babel官方也表明不支持这个特性：</p><blockquote><p>Unsupported feature<br>Due to the limitations of ES5, Proxies cannot be transpiled or polyfilled.</p></blockquote><p>目前已经有babel插件可以实现，但是据说实现的比较复杂。<br>如果是Node的话升级到目前的最新版本应该就可以使用了，上面的例子测试环境为Node v6.4.0。</p><p>原文：<a href="https://blog.daraw.cn/2016/08/17/how-to-monitor-changes-of-js-variable/" target="_blank" rel="noopener">https://blog.daraw.cn/2016/08/17/how-to-monitor-changes-of-js-variable/</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;如何监听JS变量的变化-转&quot;&gt;&lt;a href=&quot;#如何监听JS变量的变化-转&quot; class=&quot;headerlink&quot; title=&quot;如何监听JS变量的变化[转]&quot;&gt;&lt;/a&gt;如何监听JS变量的变化[转]&lt;/h1&gt;&lt;h2 id=&quot;读前必看&quot;&gt;&lt;a href=&quot;#读前必
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>shell常用命令</title>
    <link href="http://yangfan.site/2017/07/16/shell%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/"/>
    <id>http://yangfan.site/2017/07/16/shell常用命令/</id>
    <published>2017-07-16T11:59:04.000Z</published>
    <updated>2019-04-25T08:59:38.253Z</updated>
    
    <content type="html"><![CDATA[<h1 id="shell常用命令"><a href="#shell常用命令" class="headerlink" title="shell常用命令"></a>shell常用命令</h1><h4 id="1-ls命令：列出文件"><a href="#1-ls命令：列出文件" class="headerlink" title="1 ls命令：列出文件"></a>1 ls命令：列出文件</h4><p> <code>ls -la</code> 列出当前目录下的所有文件和文件夹</p><p> <code>ls a*</code> 列出当前目录下所有以a字母开头的文件</p><p> <code>ls -l *.txt</code> 列出当前目录下所有后缀名为txt的文件</p><h4 id="2-cp命令：复制"><a href="#2-cp命令：复制" class="headerlink" title="2 cp命令：复制"></a>2 cp命令：复制</h4><p><code>cp a.txt b.txt</code> 把文件a的内容复制到b文件</p><p><code>cp a.txt ./test</code>  把文件a复制到text目录下</p><p><code>cp -a test test2</code> 递归的把目录test下所有文件（包括隐藏的文件）复制到新的目录 test2</p><h4 id="3-cat命令：查看-组合文件"><a href="#3-cat命令：查看-组合文件" class="headerlink" title="3  cat命令：查看 组合文件"></a>3  cat命令：查看 组合文件</h4><p><code>cat a.txt</code> 查看文件的内容</p><p><code>cat a.txt &gt;&gt; b.txt</code> 把a文件的内容组合到b文件内容的末尾</p><p><code>cat -n a.txt</code> 查看文件并给文件标上行号</p><h4 id="4-touch命令：建立文件"><a href="#4-touch命令：建立文件" class="headerlink" title="4  touch命令：建立文件"></a>4  touch命令：建立文件</h4><p><code>touch a.txt</code> 建立一个名为a的txt类型文件</p><h4 id="5-rm命令：删除文件"><a href="#5-rm命令：删除文件" class="headerlink" title="5  rm命令：删除文件"></a>5  rm命令：删除文件</h4><p><code>rm -rf a.txt</code> 强制删除文件a.txt</p><p><code>rm -i a.txt</code> 删除文件前会有提示是否确定删除该文件</p><h4 id="6-mkdir命令：创建目录"><a href="#6-mkdir命令：创建目录" class="headerlink" title="6  mkdir命令：创建目录"></a>6  mkdir命令：创建目录</h4><p><code>mkdir test</code> 创建一个名为test的目录</p><h4 id="7-rmdir命令：删除目录"><a href="#7-rmdir命令：删除目录" class="headerlink" title="7  rmdir命令：删除目录"></a>7  rmdir命令：删除目录</h4><p><code>rmdir test</code> 删除一个目录</p><h4 id="8-echo、cat命令：添加内容"><a href="#8-echo、cat命令：添加内容" class="headerlink" title="8  echo、cat命令：添加内容"></a>8  echo、cat命令：添加内容</h4><p><code>echo “hello world!” &gt;&gt; a.txt</code> 添加内容到文件a里面</p><p><code>cat &lt;&lt;EOF&gt;&gt; a.txt</code> 可以添加多行语句到文件本身内容的末尾</p><p><code>cat &lt;&lt;EOF&gt; a.txt</code> 添加内容到文件并覆盖到原始的内容</p><h4 id="9-mv命令：移动-重命名文件"><a href="#9-mv命令：移动-重命名文件" class="headerlink" title="9  mv命令：移动 重命名文件"></a>9  mv命令：移动 重命名文件</h4><p><code>mv a.txt b.txt</code> 文件a重新命名为b</p><p><code>mv a.txt ./test</code> 把文件移动到一个目录下</p><h4 id="10-cd命令：更换目录"><a href="#10-cd命令：更换目录" class="headerlink" title="10  cd命令：更换目录"></a>10  cd命令：更换目录</h4><p><code>cd ~</code>  切换到用户目录</p><p><code>cd ..</code> 返回到上一层目录</p><p><code>cd ../..</code> 返回到上二层目录</p><h4 id="11-grep命令：搜索文件"><a href="#11-grep命令：搜索文件" class="headerlink" title="11  grep命令：搜索文件"></a>11  grep命令：搜索文件</h4><p><code>ls -la | grep a.txt</code> 搜索a.txt文件</p><h4 id="12-find命令：查找文件和目录"><a href="#12-find命令：查找文件和目录" class="headerlink" title="12  find命令：查找文件和目录"></a>12  find命令：查找文件和目录</h4><p><code>find filename</code> 查找当前目录下是否有该文件/目录</p><h4 id="13-rz-sz命令：上传和下载文件"><a href="#13-rz-sz命令：上传和下载文件" class="headerlink" title="13  rz sz命令：上传和下载文件"></a>13  rz sz命令：上传和下载文件</h4><h4 id="14-head命令：显示文件的前10行内容"><a href="#14-head命令：显示文件的前10行内容" class="headerlink" title="14  head命令：显示文件的前10行内容"></a>14  head命令：显示文件的前10行内容</h4><h4 id="15-tail命令：显示文件最后10行内容"><a href="#15-tail命令：显示文件最后10行内容" class="headerlink" title="15  tail命令：显示文件最后10行内容"></a>15  tail命令：显示文件最后10行内容</h4>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;shell常用命令&quot;&gt;&lt;a href=&quot;#shell常用命令&quot; class=&quot;headerlink&quot; title=&quot;shell常用命令&quot;&gt;&lt;/a&gt;shell常用命令&lt;/h1&gt;&lt;h4 id=&quot;1-ls命令：列出文件&quot;&gt;&lt;a href=&quot;#1-ls命令：列出文件&quot; c
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（八）</title>
    <link href="http://yangfan.site/2017/03/07/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E5%85%AB%EF%BC%89/"/>
    <id>http://yangfan.site/2017/03/07/高德地图 Javascript API 入门（八）/</id>
    <published>2017-03-07T13:57:02.000Z</published>
    <updated>2019-04-25T09:00:20.705Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（八）"><a href="#高德地图-Javascript-API-入门（八）" class="headerlink" title="高德地图 Javascript API 入门（八）"></a>高德地图 Javascript API 入门（八）</h1><h2 id="点聚合插件"><a href="#点聚合插件" class="headerlink" title="点聚合插件"></a>点聚合插件</h2><p>用于地图上加载大量点标记，提高地图浏览性能。点聚合支持用户自定义点标记</p><h4 id="加载地图"><a href="#加载地图" class="headerlink" title="加载地图"></a>加载地图</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 加载地图</span></span><br><span class="line"><span class="keyword">var</span> map=<span class="keyword">new</span> AMap.Map(<span class="string">"container"</span>,&#123;</span><br><span class="line">    resizeEnable:<span class="literal">true</span>,</span><br><span class="line">    center:[<span class="number">116.397428</span>, <span class="number">39.90923</span>],</span><br><span class="line">    zoom:<span class="number">11</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h4 id="生成点标记"><a href="#生成点标记" class="headerlink" title="生成点标记"></a>生成点标记</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 生成点标记</span></span><br><span class="line"><span class="keyword">var</span> markers=[];</span><br><span class="line"><span class="keyword">var</span> marker=<span class="literal">null</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">0</span>;i&lt;<span class="number">100</span>;i++) &#123;</span><br><span class="line">    marker=<span class="keyword">new</span> AMap.Marker(&#123;</span><br><span class="line">        position:[<span class="number">116.39</span>+<span class="number">0.001</span>*<span class="built_in">Math</span>.random()*i, <span class="number">39.90</span><span class="number">-0.001</span>*<span class="built_in">Math</span>.random()*i],</span><br><span class="line">        icon: <span class="string">"http://amappc.cn-hangzhou.oss-pub.aliyun-inc.com/lbs/static/img/marker.png"</span></span><br><span class="line">    &#125;);</span><br><span class="line">    marker.setMap(map);</span><br><span class="line">    markers.push(marker);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="载入点聚合插件"><a href="#载入点聚合插件" class="headerlink" title="载入点聚合插件"></a>载入点聚合插件</h4><ul><li>默认样式</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MarkerClusterer"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> cluster=<span class="keyword">new</span> AMap.MarkerClusterer(map,markers);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap801.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><ul><li>自定义样式</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 聚合样式</span></span><br><span class="line"><span class="keyword">var</span> sts=[&#123;</span><br><span class="line">    url:<span class="string">"http://a.amap.com/lbs/static/img/1102-1.png"</span>,</span><br><span class="line">    size:<span class="keyword">new</span> AMap.Size(<span class="number">32</span>,<span class="number">32</span>),</span><br><span class="line">    offset:<span class="keyword">new</span> AMap.Pixel(<span class="number">-16</span>,<span class="number">-30</span>),</span><br><span class="line">    imageOffset:<span class="keyword">new</span> AMap.Pixel(<span class="number">0</span>,<span class="number">0</span>)</span><br><span class="line">&#125;,&#123;</span><br><span class="line">    url:<span class="string">"http://a.amap.com/lbs/static/img/2.png"</span>,</span><br><span class="line">    size:<span class="keyword">new</span> AMap.Size(<span class="number">32</span>,<span class="number">32</span>),</span><br><span class="line">    offset:<span class="keyword">new</span> AMap.Pixel(<span class="number">-16</span>,<span class="number">-30</span>)</span><br><span class="line">&#125;,&#123;</span><br><span class="line">    url:<span class="string">"http://lbs.amap.com/wp-content/uploads/2014/06/3.png"</span>,</span><br><span class="line">    size:<span class="keyword">new</span> AMap.Size(<span class="number">32</span>,<span class="number">32</span>),</span><br><span class="line">    offset:<span class="keyword">new</span> AMap.Pixel(<span class="number">-16</span>,<span class="number">-30</span>),</span><br><span class="line">    textColor:<span class="string">"#f00"</span>,</span><br><span class="line">    textSize:<span class="number">30</span></span><br><span class="line">&#125;];</span><br><span class="line"><span class="comment">// 载入插件</span></span><br><span class="line">map.plugin([<span class="string">"AMap.MarkerClusterer"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> cluster=<span class="keyword">new</span> AMap.MarkerClusterer(map,markers,&#123;</span><br><span class="line">        styles:sts</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap802.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="MarkerClustererOptions"><a href="#MarkerClustererOptions" class="headerlink" title="MarkerClustererOptions"></a>MarkerClustererOptions</h4><table style="width:100%;border-collapse:collapse;"><tbody><tr><th><p>MarkerClustererOptions</p></th><th><p>类型</p></th><th><p>说明</p></th></tr><tr><td style="white-space: nowrap;"><p><code class="inline-code">gridSize</code></p></td><td><p><code class="inline-code">Number</code></p></td><td><p>聚合计算时网格的像素大小，默认60</p></td></tr><tr><td style="white-space: nowrap;"><p><code class="inline-code">minClusterSize</code></p></td><td><p><code class="inline-code">Number</code></p></td><td><p>聚合的最小数量。默认值为2，即小于2个点则不能成为一个聚合</p></td></tr><tr><td style="white-space: nowrap;"><p><code class="inline-code">maxZoom</code></p></td><td><p><code class="inline-code">Number</code></p></td><td><p>最大的聚合级别，大于该级别就不进行相应的聚合。默认值为18，即小于18级的级别均进行聚合，18及以上级别不进行聚合</p></td></tr><tr><td style="white-space: nowrap;"><p><code class="inline-code">averageCenter</code></p></td><td><p><code class="inline-code">Boolean</code></p></td><td><p>聚合点的图标位置是否是所有聚合内点的中心点。默认为否，即聚合点的图标位置位于聚合内的第一个点处</p></td></tr><tr><td style="white-space: nowrap;"><p><code class="inline-code">styles</code></p></td><td><p><code class="inline-code">Array&lt;Object&gt;</code></p></td><td><p>自定义聚合后的点标记图标的样式，根据数组元素顺序设置1-10,11-100,101-1000…聚合样式</p><p>当用户设置聚合样式少于实际叠加的点数，未设置部分按照系统默认样式显示</p><p>单个图标样式包括以下几个属性：</p><p>1. {string}url：图标显示图片的url地址（必选）</p><p>2. {AMap.Size}size：图标显示图片的大小（必选）</p><p>3. {AMap.Pixel} offset：图标定位在地图上的位置相对于图标左上角的偏移值。默认为(0,0),不偏移（可选）</p><p>4. {AMap.Pixel} imageOffset：图片相对于可视区域的偏移值，此功能的作用等同CSS中的background-position属性。默认为(0,0)，不偏移（可选）</p><p>5. {String} textColor：文字的颜色，默认为”#000000”（可选）</p><p>6. {Number} textSize：文字的大小，默认为10（可选）</p></td></tr><tr><td style="white-space: nowrap;"><p><code class="inline-code">zoomOnClick</code></p></td><td><p><code class="inline-code">Boolean</code></p></td><td><p>点击聚合点时，是否散开，默认值为：true</p></td></tr></tbody></table><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（八）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（八）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（八）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（七）</title>
    <link href="http://yangfan.site/2017/03/04/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E4%B8%83%EF%BC%89/"/>
    <id>http://yangfan.site/2017/03/04/高德地图 Javascript API 入门（七）/</id>
    <published>2017-03-04T13:03:02.000Z</published>
    <updated>2019-04-25T09:00:30.152Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（七）"><a href="#高德地图-Javascript-API-入门（七）" class="headerlink" title="高德地图 Javascript API 入门（七）"></a>高德地图 Javascript API 入门（七）</h1><h2 id="热力图插件"><a href="#热力图插件" class="headerlink" title="热力图插件"></a>热力图插件</h2><h4 id="简单例子"><a href="#简单例子" class="headerlink" title="简单例子"></a>简单例子</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 显示地图</span></span><br><span class="line"><span class="keyword">var</span> map=<span class="keyword">new</span> AMap.Map(<span class="string">"container"</span>,&#123;</span><br><span class="line">    resizeEnable:<span class="literal">true</span>,</span><br><span class="line">    center:[<span class="number">116.397428</span>, <span class="number">39.90923</span>],</span><br><span class="line">    zoom:<span class="number">11</span></span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 坐标点</span></span><br><span class="line"><span class="keyword">var</span> points =[</span><br><span class="line">&#123;<span class="string">"lng"</span>:<span class="number">116.191031</span>,<span class="string">"lat"</span>:<span class="number">39.988585</span>,<span class="string">"count"</span>:<span class="number">100</span>&#125;,</span><br><span class="line">    &#123;<span class="string">"lng"</span>:<span class="number">116.389275</span>,<span class="string">"lat"</span>:<span class="number">39.925818</span>,<span class="string">"count"</span>:<span class="number">60</span>&#125;,</span><br><span class="line">    &#123;<span class="string">"lng"</span>:<span class="number">116.287444</span>,<span class="string">"lat"</span>:<span class="number">39.810742</span>,<span class="string">"count"</span>:<span class="number">200</span>&#125;,</span><br><span class="line">    &#123;<span class="string">"lng"</span>:<span class="number">116.481707</span>,<span class="string">"lat"</span>:<span class="number">39.940089</span>,<span class="string">"count"</span>:<span class="number">30</span>&#125;,</span><br><span class="line">    &#123;<span class="string">"lng"</span>:<span class="number">116.410588</span>,<span class="string">"lat"</span>:<span class="number">39.880172</span>,<span class="string">"count"</span>:<span class="number">200</span>&#125;,</span><br><span class="line">    &#123;<span class="string">"lng"</span>:<span class="number">116.394816</span>,<span class="string">"lat"</span>:<span class="number">39.91181</span>,<span class="string">"count"</span>:<span class="number">10</span>&#125;,</span><br><span class="line">    &#123;<span class="string">"lng"</span>:<span class="number">116.416002</span>,<span class="string">"lat"</span>:<span class="number">39.952917</span>,<span class="string">"count"</span>:<span class="number">150</span>&#125;</span><br><span class="line">];</span><br><span class="line"><span class="comment">// 加载热力图插件</span></span><br><span class="line">map.plugin([<span class="string">"AMap.Heatmap"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"> <span class="keyword">var</span> heatmap=<span class="keyword">new</span> AMap.Heatmap(map,&#123;</span><br><span class="line">    radius:<span class="number">50</span></span><br><span class="line">&#125;);</span><br><span class="line">heatmap.setDataSet(&#123;</span><br><span class="line">   data:points,</span><br><span class="line">    max:<span class="number">100</span></span><br><span class="line">   &#125;);</span><br><span class="line">)&#125;;</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap701.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h4><p>AMap.Heatmap</p><table style="width:100%;border-collapse:collapse;"><tbody><tr><th>构造函数</th><th>说明</th></tr><tr><td><code>AMap.Heatmap(<span class="punderline" title="叠加的地图对象，类型为AMap.Map">map:<a href="http://lbs.amap.com/api/javascript-api/reference/map/" target="_blank" rel="noopener">Map</a></span>,<span class="punderline" title="参考HeatmapOptions列表中的说明">opts:<a href="#m_HeatmapOptions">HeatmapOptions</a></span>)</code></td><td>构造一个热力图插件对象，map为要叠加热力图的地图对象，opts属性参考HeatmapOptions列表中的说明。</td></tr></tbody></table><p>options</p><table style="width:100%;border-collapse:collapse;"><tbody><tr><th>HeatmapOptions</th><th>类型</th><th>说明</th></tr><tr><td style="white-space: nowrap;"><code>radius</code></td><td><code>Number</code></td><td>热力图中单个点的半径，默认：30，单位：pixel</td></tr><tr><td style="white-space: nowrap;"><code>gradient</code></td><td><code>Object</code></td><td>热力图的渐变区间，热力图按照设置的颜色及间隔显示热力图，例：<br>{<br>0.4:’rgb(0, 255, 255)’,<br>0.65:’rgb(0, 110, 255)’,<br>0.85:’rgb(100, 0, 255)’,<br>1.0:’rgb(100, 0, 255)’<br>}<br> 其中 key 表示间隔位置，取值范围： [0,1]，value为颜色值。默认：heatmap.js标准配色方案</td></tr><tr><td style="white-space: nowrap;"><code>opacity</code></td><td><code>Array</code></td><td>热力图透明度数组，取值范围[0,1]，0表示完全透明，1表示不透明，默认：[0,1]</td></tr><tr><td style="white-space: nowrap;"><code>zooms</code></td><td><code>Array</code></td><td>支持的缩放级别范围，取值范围[3-18]，默认：[3,18]</td></tr></tbody></table><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（七）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（七）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（七）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（六）</title>
    <link href="http://yangfan.site/2017/02/28/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E5%85%AD%EF%BC%89/"/>
    <id>http://yangfan.site/2017/02/28/高德地图 Javascript API 入门（六）/</id>
    <published>2017-02-28T10:03:02.000Z</published>
    <updated>2019-04-25T09:00:16.705Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（六）"><a href="#高德地图-Javascript-API-入门（六）" class="headerlink" title="高德地图 Javascript API 入门（六）"></a>高德地图 Javascript API 入门（六）</h1><h2 id="出行规划"><a href="#出行规划" class="headerlink" title="出行规划"></a>出行规划</h2><h4 id="公交路径"><a href="#公交路径" class="headerlink" title="公交路径"></a>公交路径</h4><p>公交换乘服务，提供起、终点公交路线规划服务，整合步行方式</p><ul><li>初始化</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 加载公交线路插件</span></span><br><span class="line">AMap.service(<span class="string">"AMap.Transfer"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 实例化Transfer </span></span><br><span class="line">    <span class="keyword">var</span> transfer=<span class="keyword">new</span> AMap.Transfer(&#123;</span><br><span class="line">        city:<span class="string">"北京"</span>, <span class="comment">// 必须值，搭乘公交所在城市</span></span><br><span class="line">        map:map, <span class="comment">// 可选值，搜索结果的标注、线路等均会自动添加到此地图上</span></span><br><span class="line">        panel:<span class="string">"panel"</span>, <span class="comment">// 可选值，显示搜索列表的容器,</span></span><br><span class="line">        extensions:<span class="string">"all"</span>, <span class="comment">// 可选值，详细信息        </span></span><br><span class="line">        poliy:AMap.TransferPolicy.LEAST_TIME <span class="comment">// 驾驶策略：最省时模式</span></span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><ul><li>按关键字搜索</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 关键字搜索</span></span><br><span class="line">transfer.search([&#123;<span class="attr">keyword</span>:<span class="string">"北京西站"</span>&#125;,&#123;<span class="attr">keyword</span>:<span class="string">"天安门"</span>&#125;],<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">window</span>.top.data=result;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><ul><li>按坐标搜索</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 按坐标搜索</span></span><br><span class="line">transfer.search([<span class="number">116.379028</span>, <span class="number">39.865042</span>], [<span class="number">116.427281</span>, <span class="number">39.903719</span>],<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">window</span>.top.data=result;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览 </p><p><img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap601.JPG" alt="image"></p><h4 id="驾车路径"><a href="#驾车路径" class="headerlink" title="驾车路径"></a>驾车路径</h4><p>驾车路线规划服务，提供起、终点坐标的驾车导航路线查询功能</p><ul><li>初始化</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 加载驾车路径插件</span></span><br><span class="line">AMap.service(<span class="string">"AMap.Driving"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="comment">// 实例化Driving    </span></span><br><span class="line"><span class="keyword">var</span> driving=<span class="keyword">new</span> AMap.Driving(&#123;</span><br><span class="line">        map:map, <span class="comment">// 用来承载 显示路径</span></span><br><span class="line">        panel:<span class="string">"panel"</span>, <span class="comment">// 显示搜索列表的容器</span></span><br><span class="line">        extensions:<span class="string">"all"</span>, <span class="comment">// 详细信息</span></span><br><span class="line">        policy:AMap.DrivingPolicy.REAL_TRAFFIC, <span class="comment">// 驾驶策略：合理交通</span></span><br><span class="line">        showTraffic:<span class="literal">true</span>, <span class="comment">// 是否显示路况</span></span><br><span class="line">        province:<span class="string">"晋"</span>, <span class="comment">// 判断限行</span></span><br><span class="line">        number:<span class="string">"A88888"</span>, <span class="comment">// 判断限行</span></span><br><span class="line">        hideMarkers:<span class="literal">false</span>, <span class="comment">// 隐藏起点、终点的点标注</span></span><br><span class="line">        isOutline:<span class="literal">true</span>, <span class="comment">// 是否显示线路的边框</span></span><br><span class="line">        outlineColor:<span class="string">"#f00"</span> <span class="comment">// 边框颜色</span></span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><ul><li>按关键字搜索</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 按关键字搜索</span></span><br><span class="line">   driving.search([&#123;<span class="attr">keyword</span>:<span class="string">"北京西站"</span>,<span class="attr">city</span>:<span class="string">"北京"</span>&#125;,&#123;<span class="attr">keyword</span>:<span class="string">"天安门"</span>,<span class="attr">city</span>:<span class="string">"北京"</span>&#125;],<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">       <span class="built_in">window</span>.top.data=result;</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure><ul><li>按坐标搜索</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 按坐标搜索</span></span><br><span class="line">driving.search([<span class="number">116.379028</span>, <span class="number">39.865042</span>], [<span class="number">116.427281</span>, <span class="number">39.903719</span>],<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">       <span class="built_in">window</span>.top.data=result;</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap602.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><p>限行结果<br>0 代表限行已规避或未限行，即该路线没有限行路段<br>1 代表限行无法规避，即该线路有限行路段</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap603.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="步行路径"><a href="#步行路径" class="headerlink" title="步行路径"></a>步行路径</h4><p>步行导航服务，提供起、终点步行路线规划服务</p><ul><li>初始化</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 加载步行路径插件</span></span><br><span class="line">AMap.service(<span class="string">"AMap.Walking"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> walking=<span class="keyword">new</span> AMap.Walking(&#123;</span><br><span class="line">        map:map,</span><br><span class="line">        panel:<span class="string">"panel"</span></span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><ul><li>按关键字搜索 </li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">walking.search([&#123;<span class="attr">keyword</span>:<span class="string">"方恒国际中心A座"</span>&#125;,&#123;<span class="attr">keyword</span>:<span class="string">"望京站"</span>&#125;],<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line"><span class="built_in">window</span>.top.data=result;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><ul><li>按坐标搜索 </li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">walking.search([<span class="number">116.379028</span>, <span class="number">39.865042</span>],[<span class="number">116.427281</span>, <span class="number">39.903719</span>],<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line"><span class="built_in">window</span>.top.data=result;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap604.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（六）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（六）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（六）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（五）</title>
    <link href="http://yangfan.site/2017/02/26/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E4%BA%94%EF%BC%89/"/>
    <id>http://yangfan.site/2017/02/26/高德地图 Javascript API 入门（五）/</id>
    <published>2017-02-26T14:03:02.000Z</published>
    <updated>2019-04-25T09:00:24.437Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（五）"><a href="#高德地图-Javascript-API-入门（五）" class="headerlink" title="高德地图 Javascript API 入门（五）"></a>高德地图 Javascript API 入门（五）</h1><h2 id="搜索服务"><a href="#搜索服务" class="headerlink" title="搜索服务"></a>搜索服务</h2><h4 id="搜索服务-1"><a href="#搜索服务-1" class="headerlink" title="搜索服务"></a>搜索服务</h4><table style="width:100%;border-collapse:collapse;"><tbody><tr><th>名称</th><th>说明</th><th>是否插件</th></tr><tr><td><a href="#m_AMap.Autocomplete" class target>AMap.Autocomplete</a></td><td>输入提示，根据输入关键字提示匹配信息</td><td>是</td></tr><tr><td><a href="#m_AMap.PlaceSearch" class target>AMap.PlaceSearch</a></td><td>地点搜索服务插件，提供某一特定地区的位置查询服务</td><td>是</td></tr><tr><td><a href="#m_AMap.PlaceSearchLayer" class target>AMap.PlaceSearchLayer</a></td><td>麻点图插件，提供海量搜索结果的辅助显示功能</td><td>是</td></tr><tr><td><a href="#m_AMap.DistrictSearch" class target>AMap.DistrictSearch</a></td><td>行政区查询服务，提供行政区相关信息</td><td>是</td></tr><tr><td><a href="#m_AMap.LineSearch" class target>AMap.LineSearch</a></td><td>公交路线服务，提供公交路线相关信息查询服务</td><td>是</td></tr><tr><td><a href="#m_AMap.StationSearch" class target>AMap.StationSearch</a></td><td>公交站点查询服务，提供途经公交线路、站点经纬度等信息</td><td>是</td></tr></tbody></table><h4 id="地点搜索插件-AMap-PlaceSearch"><a href="#地点搜索插件-AMap-PlaceSearch" class="headerlink" title="地点搜索插件 AMap.PlaceSearch"></a>地点搜索插件 AMap.PlaceSearch</h4><ul><li>创建地点查询类的实例</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建地点查询类的实例</span></span><br><span class="line">AMap.service(<span class="string">"AMap.PlaceSearch"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> s1=<span class="keyword">new</span> AMap.PlaceSearch(&#123;</span><br><span class="line">city:<span class="string">"北京市"</span>, <span class="comment">// 搜索范围的城市</span></span><br><span class="line">type:<span class="string">"风景名胜"</span>, <span class="comment">// 搜索类型</span></span><br><span class="line">map:map, <span class="comment">// 可选，AMap示例</span></span><br><span class="line">panel:<span class="string">"result"</span>, <span class="comment">// 可选，结果列表的HTML容器id或容器元素</span></span><br><span class="line">pageSize:<span class="number">5</span>, <span class="comment">// 结果，单页展示结果数</span></span><br><span class="line">pageIndex:<span class="number">2</span>, <span class="comment">// 结果，页码</span></span><br><span class="line">extensions:<span class="string">"all"</span> <span class="comment">// 信息，默认值 "base", 详细信息 "all"</span></span><br><span class="line">&#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><ul><li>根据关键字搜索</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 关键字搜索</span></span><br><span class="line">s1.search(<span class="string">"八达岭"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line"><span class="built_in">console</span>.log(result);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap501.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><div style="margin:30px 0;border-bottom:3px dotted #9c3"></div><ul><li>根据中心点经纬度、半径以及关键字进行周边查询（周边搜索）</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 周边搜索</span></span><br><span class="line">s1.searchNearBy(<span class="string">"餐饮"</span>,[<span class="number">116.403322</span>, <span class="number">39.920255</span>],<span class="number">1000</span>,<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(result);</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap502.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><div style="margin:30px 0;border-bottom:3px dotted #9c3"></div><ul><li>根据范围和关键词进行范围查询</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> lnglat1=<span class="keyword">new</span> AMap.LngLat( <span class="number">116.403322</span>, <span class="number">39.920255</span>);</span><br><span class="line"><span class="keyword">var</span> lnglat2=<span class="keyword">new</span> AMap.LngLat( <span class="number">116.389846</span>, <span class="number">39.891365</span>);</span><br><span class="line">s1.searchInBounds(<span class="string">'酒店'</span>,<span class="keyword">new</span> AMap.Bounds(lnglat1,lnglat2));</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap503.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><div style="margin:30px 0;border-bottom:3px dotted #9c3"></div><ul><li>根据POIID 查询POI详细信息</li></ul><p>POIID是返回数据（JSON）的一个 id 值</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap504.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><div style="margin:30px 0;border-bottom:3px dotted #9c3"></div><p>获取POI的详细信息</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">s1.getDetails(<span class="string">"B000A82RP2"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(result.poiList.pois[<span class="number">0</span>].name);</span><br><span class="line">  <span class="built_in">window</span>.top.data=result.poiList.pois[<span class="number">0</span>];</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap505.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><div style="margin:30px 0;border-bottom:3px dotted #9c3"></div><h4 id="公交线路搜索插件-AMap-LineSearch"><a href="#公交线路搜索插件-AMap-LineSearch" class="headerlink" title="公交线路搜索插件 AMap.LineSearch"></a>公交线路搜索插件 AMap.LineSearch</h4><ul><li>创建公交线路查询类的实例</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">AMap.service(<span class="string">"AMap.LineSearch"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"> <span class="keyword">var</span> lineSearch=<span class="keyword">new</span> AMap.LineSearch(&#123;</span><br><span class="line">     city:<span class="string">"太原"</span>,</span><br><span class="line">   extensions:<span class="string">"all"</span>         </span><br><span class="line">   &#125;);</span><br><span class="line"> &#125;);</span><br></pre></td></tr></table></figure><ul><li>按关键字查询公交线路</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">lineSearch.search(<span class="string">"901"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">   <span class="keyword">if</span> (status===<span class="string">"complete"</span> &amp;&amp; result.info===<span class="string">"OK"</span>) &#123;</span><br><span class="line">       <span class="built_in">console</span>.log(result);</span><br><span class="line">       <span class="built_in">window</span>.top.data=result;</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap506.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><div style="margin:30px 0;border-bottom:3px dotted #9c3"></div><ul><li>按id查询公交线路</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">lineSearch.searchById(<span class="string">"140100010458"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">status,result</span>) </span>&#123;</span><br><span class="line">   <span class="keyword">if</span> (status===<span class="string">"complete"</span> &amp;&amp; result.info===<span class="string">"OK"</span>) &#123;</span><br><span class="line">       <span class="built_in">console</span>.log(result);</span><br><span class="line">       <span class="built_in">window</span>.top.data=result;</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap507.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><div style="margin:30px 0;border-bottom:3px dotted #9c3"></div><h4 id="LineInfo-对象"><a href="#LineInfo-对象" class="headerlink" title="LineInfo 对象"></a>LineInfo 对象</h4><ul><li>基本信息</li></ul><table style="width:100%;border-collapse:collapse;"><tbody><tr><th>属性</th><th>类型</th><th>说明</th></tr><tr><td style="white-space: nowrap;"><code class="inline-code">id</code></td><td><code class="inline-code">String</code></td><td>公交线路id，该id是唯一标识</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">name</code></td><td><code class="inline-code">String</code></td><td>公交线路名称</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">path</code></td><td><code class="inline-code">Array.&lt;</code><a href="/api/javascript-api/reference/core#LngLat" class target><code class="inline-code">LngLat</code></a><code class="inline-code">&gt;</code></td><td>公交线路经纬度</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">citycode</code></td><td><code class="inline-code">String</code></td><td>公交线路所在城市的城市编码</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">type</code></td><td><code class="inline-code">String</code></td><td>公交类型列表</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">type</code></td><td><code class="inline-code">String</code></td><td>公交类型列表</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">start_stop</code></td><td><code class="inline-code">String</code></td><td>首发站</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">end_stop</code></td><td><code class="inline-code">String</code></td><td>终点站</td></tr></tbody></table><ul><li>详细信息</li></ul><table style="width:100%;border-collapse:collapse;"><tbody><tr><th>属性</th><th>类型</th><th>说明</th></tr><tr><td style="white-space: nowrap;"><code class="inline-code">stime</code></td><td><code class="inline-code">String</code></td><td>首班车时间</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">etime</code></td><td><code class="inline-code">String</code></td><td>末班车时间</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">basic_price</code></td><td><code class="inline-code">String</code></td><td>起步票价，单位：元</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">total_price</code></td><td><code class="inline-code">String</code></td><td>全程票价，单位：元</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">via_stops</code></td><td><code class="inline-code">String</code></td><td>途径站，包括首发站和终点站</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">distance</code></td><td><code class="inline-code">Number</code></td><td>全程距离，单位：千米</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">bounds</code></td><td><a href="http://lbs.amap.com/api/javascript-api/reference/core/#Bounds" class target="_blank" rel="noopener"><code class="inline-code">Bounds</code></a></td><td>此公交路线的地理范围</td></tr><tr><td style="white-space: nowrap;"><code class="inline-code">company</code></td><td><code class="inline-code">String</code></td><td>所属公交公司</td></tr></tbody></table><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（五）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（五）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（五）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（四）</title>
    <link href="http://yangfan.site/2017/02/22/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E5%9B%9B%EF%BC%89/"/>
    <id>http://yangfan.site/2017/02/22/高德地图 Javascript API 入门（四）/</id>
    <published>2017-02-22T11:03:02.000Z</published>
    <updated>2019-04-25T09:00:11.915Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（四）"><a href="#高德地图-Javascript-API-入门（四）" class="headerlink" title="高德地图 Javascript API 入门（四）"></a>高德地图 Javascript API 入门（四）</h1><h2 id="地图覆盖物"><a href="#地图覆盖物" class="headerlink" title="地图覆盖物"></a>地图覆盖物</h2><h4 id="覆盖物"><a href="#覆盖物" class="headerlink" title="覆盖物"></a>覆盖物</h4><table style="width:100%;border-collapse:collapse;"><thead><tr><th class>类名</th><th class>说明</th><th>是否插件</th></tr></thead><tbody><tr><td><a href="#Marker">AMap.Marker</a></td><td><p style="margin-top:10px">点标记</p></td><td><p style="margin-top:10px">否</p></td></tr><tr><td><a href="#Icon">AMap.Icon</a></td><td><p style="margin-top:10px">覆盖物&gt;点标记&gt;复杂点标记对象，对普通点标记Marker 的扩展</p></td><td><p style="margin-top:10px">否</p></td></tr><tr><td><a href="#Polyline">AMap.Polyline</a></td><td><p style="margin-top:10px">覆盖物&gt;折线</p></td><td><p style="margin-top:10px">否</p></td></tr><tr><td><a href="#Polygon">AMap.Polygon</a></td><td><p style="margin-top:10px">覆盖物&gt;多边形</p></td><td><p style="margin-top:10px">否</p></td></tr><tr><td><a href="#Circle">AMap.Circle</a></td><td><p style="margin-top:10px">覆盖物&gt;圆</p></td><td><p style="margin-top:10px">否</p></td></tr><tr><td><a href="#GroundImage">AMap.GroundImage</a></td><td><p style="margin-top:10px">图片覆盖物</p></td><td><p style="margin-top:10px">否</p></td></tr><tr><td><a href="#ContextMenu">AMap.ContextMenu</a></td><td><p style="margin-top:10px">地图右键菜单</p></td><td><p style="margin-top:10px">否</p></td></tr></tbody></table><h4 id="点标记"><a href="#点标记" class="headerlink" title="点标记"></a>点标记</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> marker=<span class="keyword">new</span> AMap.Marker(&#123;</span><br><span class="line">map:map,</span><br><span class="line">position:<span class="keyword">new</span> AMap.LngLat(<span class="number">112.736465</span>,<span class="number">37.696495</span>)</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap401.JPG" alt="iamge" title>                </div>                <div class="image-caption">iamge</div>            </figure><p>自定义点标记</p><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> marker=<span class="keyword">new</span> AMap.Marker(&#123;</span><br><span class="line">map:map,</span><br><span class="line">position:<span class="keyword">new</span> AMap.LngLat(<span class="number">112.736465</span>,<span class="number">37.696495</span>),</span><br><span class="line">icon:<span class="keyword">new</span> AMap.Icon(&#123;</span><br><span class="line">image:<span class="string">"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2803620233,1906638381&amp;fm=23&amp;gp=0.jpg"</span>,</span><br><span class="line">size:[<span class="number">72</span>,<span class="number">72</span>],</span><br><span class="line">imageSize:[<span class="number">36</span>,<span class="number">36</span>]</span><br><span class="line">&#125;),</span><br><span class="line">draggable:<span class="literal">true</span>,</span><br><span class="line">raiseOnDrag:<span class="literal">true</span>,</span><br><span class="line">shape:<span class="keyword">new</span> AMap.MarkerShape(&#123;</span><br><span class="line">type:<span class="string">"circle"</span>,</span><br><span class="line">coords:[<span class="number">112.736465</span>,<span class="number">37.696495</span>,<span class="number">100</span>]</span><br><span class="line">&#125;),</span><br><span class="line">label:&#123;</span><br><span class="line">content:<span class="string">"label"</span>,</span><br><span class="line">offset:<span class="keyword">new</span> AMap.Pixel(<span class="number">0</span>,<span class="number">-36</span>)</span><br><span class="line">&#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap402.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h5 id="多边形"><a href="#多边形" class="headerlink" title="多边形"></a>多边形</h5><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> lineArr=[</span><br><span class="line">[<span class="number">112.49157</span>,<span class="number">37.897392</span>],</span><br><span class="line">[<span class="number">112.602806</span>,<span class="number">37.898747</span>],</span><br><span class="line">[<span class="number">112.608643</span>,<span class="number">37.797355</span>],</span><br><span class="line">[<span class="number">112.49775</span>,<span class="number">37.79627</span>]</span><br><span class="line">];</span><br><span class="line"><span class="keyword">var</span> polygon=<span class="keyword">new</span> AMap.Polygon(&#123;</span><br><span class="line">map:map,</span><br><span class="line">path:lineArr</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap404.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="右键菜单"><a href="#右键菜单" class="headerlink" title="右键菜单"></a>右键菜单</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> contextmenu=<span class="keyword">new</span> AMap.ContextMenu();</span><br><span class="line"><span class="keyword">var</span> pos=[];</span><br><span class="line"><span class="comment">// 添加右键菜单内容项</span></span><br><span class="line">contextmenu.addItem(<span class="string">"放大"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">map.zoomIn();</span><br><span class="line">&#125;,<span class="number">0</span>);</span><br><span class="line">contextmenu.addItem(<span class="string">"缩小"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">map.zoomOut();</span><br><span class="line">&#125;,<span class="number">1</span>);</span><br><span class="line">contextmenu.addItem(<span class="string">"添加点标记"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> marker=<span class="keyword">new</span> AMap.Marker(&#123;</span><br><span class="line">map:map,</span><br><span class="line">position:pos</span><br><span class="line">&#125;);</span><br><span class="line">&#125;,<span class="number">2</span>);</span><br><span class="line"><span class="comment">// 监听鼠标右击事件</span></span><br><span class="line">map.on(<span class="string">"rightclick"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span><br><span class="line">contextmenu.open(map,e.lnglat);</span><br><span class="line">pos=e.lnglat;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap405.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h2 id="信息窗体"><a href="#信息窗体" class="headerlink" title="信息窗体"></a>信息窗体</h2><h4 id="信息窗体-1"><a href="#信息窗体-1" class="headerlink" title="信息窗体"></a>信息窗体</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> infowindow=<span class="keyword">new</span> AMap.InfoWindow(&#123;</span><br><span class="line">isCustom:<span class="literal">false</span>,</span><br><span class="line">content:<span class="string">"&lt;h3&gt;Hello,Yuanping&lt;/h3&gt;"</span>,</span><br><span class="line">offset:<span class="keyword">new</span> AMap.Pixel(<span class="number">0</span>,<span class="number">-36</span>),</span><br><span class="line">showShadow:<span class="literal">true</span>,</span><br><span class="line">closeWhenClickMap:<span class="literal">true</span>,</span><br><span class="line">autoMove:<span class="literal">true</span></span><br><span class="line">&#125;);</span><br><span class="line">infowindow.open(map,<span class="keyword">new</span> AMap.LngLat(<span class="number">112.736465</span>,<span class="number">38.696495</span>));</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap406.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h2 id="小练习"><a href="#小练习" class="headerlink" title="小练习"></a>小练习</h2><h4 id="鼠标划过山西大剧院时，弹出信息窗体"><a href="#鼠标划过山西大剧院时，弹出信息窗体" class="headerlink" title="鼠标划过山西大剧院时，弹出信息窗体"></a>鼠标划过山西大剧院时，弹出信息窗体</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 坐标</span></span><br><span class="line"><span class="keyword">var</span> lineArr=[</span><br><span class="line">[<span class="number">112.532802</span>,<span class="number">37.808395</span>],</span><br><span class="line">[<span class="number">112.533049</span>,<span class="number">37.808395</span>],</span><br><span class="line">[<span class="number">112.533124</span>,<span class="number">37.808476</span>],</span><br><span class="line">[<span class="number">112.533521</span>,<span class="number">37.808459</span>],</span><br><span class="line">[<span class="number">112.533558</span>,<span class="number">37.808391</span>],</span><br><span class="line">[<span class="number">112.533832</span>,<span class="number">37.808391</span>],</span><br><span class="line">[<span class="number">112.533848</span>,<span class="number">37.80792</span>],</span><br><span class="line">[<span class="number">112.534159</span>,<span class="number">37.807959</span>],</span><br><span class="line">[<span class="number">112.534159</span>,<span class="number">37.80748</span>],</span><br><span class="line">[<span class="number">112.533826</span>,<span class="number">37.807514</span>],</span><br><span class="line">[<span class="number">112.533832</span>,<span class="number">37.807179</span>],</span><br><span class="line">[<span class="number">112.533966</span>,<span class="number">37.806848</span>],</span><br><span class="line">[<span class="number">112.533376</span>,<span class="number">37.806683</span>],</span><br><span class="line">[<span class="number">112.533054</span>,<span class="number">37.806687</span>],</span><br><span class="line">[<span class="number">112.532684</span>,<span class="number">37.806878</span>],</span><br><span class="line">[<span class="number">112.53278</span>,<span class="number">37.807191</span>],</span><br><span class="line">[<span class="number">112.532796</span>,<span class="number">37.80745</span>],</span><br><span class="line">[<span class="number">112.532013</span>,<span class="number">37.807285</span>],</span><br><span class="line">[<span class="number">112.532019</span>,<span class="number">37.808213</span>],</span><br><span class="line">[<span class="number">112.532796</span>,<span class="number">37.808018</span>],</span><br><span class="line">[<span class="number">112.532818</span>,<span class="number">37.808412</span>]</span><br><span class="line">];</span><br><span class="line"><span class="comment">// 实例化Polygon类</span></span><br><span class="line"><span class="keyword">var</span> polygon=<span class="keyword">new</span> AMap.Polygon(&#123;</span><br><span class="line">map:map,</span><br><span class="line">path:lineArr</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 适应窗口</span></span><br><span class="line">map.setFitView();</span><br><span class="line"><span class="comment">// 实例化信息窗体类</span></span><br><span class="line"><span class="keyword">var</span> infowindow=<span class="keyword">new</span> AMap.InfoWindow(&#123;</span><br><span class="line">content:<span class="string">"&lt;h3&gt;太原市&lt;/h3&gt;&lt;p&gt;山西大剧院&lt;/p&gt;"</span>,</span><br><span class="line">closeWhenClickMap:<span class="literal">true</span></span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 监听鼠标移入、移除事件</span></span><br><span class="line">polygon.on(<span class="string">"mouseover"</span>,<span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span><br><span class="line">infowindow.open(map,map.getCenter());</span><br><span class="line">&#125;).on(<span class="string">"mouseout"</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">infowindow.close();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap407.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（四）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（四）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（四）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（三）</title>
    <link href="http://yangfan.site/2017/02/22/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E4%B8%89%EF%BC%89/"/>
    <id>http://yangfan.site/2017/02/22/高德地图 Javascript API 入门（三）/</id>
    <published>2017-02-22T04:52:44.000Z</published>
    <updated>2019-04-25T09:00:32.857Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（三）"><a href="#高德地图-Javascript-API-入门（三）" class="headerlink" title="高德地图 Javascript API 入门（三）"></a>高德地图 Javascript API 入门（三）</h1><h2 id="距离测量插件"><a href="#距离测量插件" class="headerlink" title="距离测量插件"></a>距离测量插件</h2><h4 id="区别"><a href="#区别" class="headerlink" title="区别"></a>区别</h4><p>虽然鼠标工具插件也提供距离量测功能，<br>但是距离量测插件，提供更为丰富的样式设置功能。</p><h4 id="加载插件"><a href="#加载插件" class="headerlink" title="加载插件"></a>加载插件</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.RangingTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> rangingTool=<span class="keyword">new</span> AMap.RangingTool(map);</span><br><span class="line">rangingTool.turnOn(); <span class="comment">// 开启量测功能</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap301.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="样式设置"><a href="#样式设置" class="headerlink" title="样式设置"></a>样式设置</h4><table style="width:100%;border-collapse:collapse;"><tbody><tr><th><p>RangingToolOptions</p></th><th><p>类型</p></th><th><p>说明</p></th></tr><tr><td><p><code class="inline-code">startMarkerOptions</code></p></td><td><p><code class="inline-code">Object</code></p></td><td><p>设置量测起始点标记属性对象，包括点标记样式、大小等，参考 &nbsp;&nbsp;<a href="/api/javascript-api/reference/overlay#MarkerOptions" class target>MarkerOptions</a> &nbsp;列表</p></td></tr><tr><td><p><code class="inline-code">midMarkerOptions</code></p></td><td><p><code class="inline-code">Object</code></p></td><td><p>设置量测中间点标记属性对象，包括点标记样式、大小等，参考 &nbsp;<a href="/api/javascript-api/reference/overlay#MarkerOptions" class target>MarkerOptions</a> &nbsp;列表</p></td></tr><tr><td><p><code class="inline-code">endMarkerOptions</code></p></td><td><p><code class="inline-code">Object</code></p></td><td><p>设置量测结束点标记属性对象，包括点标记样式、大小等，参考 &nbsp;<a href="/api/javascript-api/reference/overlay#MarkerOptions" class target>MarkerOptions</a> &nbsp;列表</p></td></tr><tr><td><p><code class="inline-code">lineOptions</code></p></td><td><p><code class="inline-code">Object</code></p></td><td><p>设置距离量测线的属性对象，包括线样式、颜色等，参考 &nbsp;<a href="/api/javascript-api/reference/overlay#PolylineOptions" class target>PolylineOptions </a>列表</p></td></tr><tr><td><p><code class="inline-code">tmpLineOptions</code></p></td><td><p><code class="inline-code">Object</code></p></td><td><p>设置距离量测过程中临时量测线的属性对象，包括线样式、颜色等，参考 &nbsp;<a href="/api/javascript-api/reference/overlay#PolylineOptions" class target>PolylineOptions</a> &nbsp;列表</p></td></tr><tr><td><p><code class="inline-code">startLabelText</code></p></td><td><p><code class="inline-code">String</code></p></td><td><p>设置量测起始点标签的文字内容，默认为“起点”</p></td></tr><tr><td><p><code class="inline-code">midLabelText</code></p></td><td><p><code class="inline-code">String</code></p></td><td><p>设置量测中间点处标签的文字内容，默认为当前量测结果值</p></td></tr><tr><td><p><code class="inline-code">endLabelText</code></p></td><td><p><code class="inline-code">String</code></p></td><td><p>设置量测结束点处标签的文字内容，默认为当前量测结果值</p></td></tr><tr><td><p><code class="inline-code">startLabelOffset</code></p></td><td><p><a href="http://lbs.amap.com/api/javascript-api/reference/core/#Pixel" class target="_blank" rel="noopener"><code class="inline-code">Pixel</code></a>&nbsp;</p></td><td><p>设置量测起始点标签的偏移量。默认值：Pixel(-6, 6)</p></td></tr><tr><td><p><code class="inline-code">midLabelOffset</code></p></td><td><p><a href="http://lbs.amap.com/api/javascript-api/reference/core/#Pixel" class target="_blank" rel="noopener"><code class="inline-code">Pixel</code></a>&nbsp;</p></td><td><p>设置量测中间点标签的偏移量。默认值：Pixel(-6, 6)</p></td></tr><tr><td><p><code class="inline-code">endLabelOffset</code></p></td><td><p><a href="http://lbs.amap.com/api/javascript-api/reference/core/#Pixel" class target="_blank" rel="noopener"><code class="inline-code">Pixel</code></a>&nbsp;</p></td><td><p>设置量测结束点标签的偏移量。默认值：Pixel(-6, 6)</p></td></tr></tbody></table><h4 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h4><h6 id="改变标签文字"><a href="#改变标签文字" class="headerlink" title="改变标签文字"></a>改变标签文字</h6><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.RangingTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> rangingTool=<span class="keyword">new</span> AMap.RangingTool(map,&#123;</span><br><span class="line">startLabelText:<span class="string">"START"</span>,</span><br><span class="line">midLabelText:<span class="string">"MID"</span>,</span><br><span class="line">endLabelText:<span class="string">"END"</span></span><br><span class="line">&#125;);</span><br><span class="line">rangingTool.turnOn();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap302.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h6 id="改变线条样式"><a href="#改变线条样式" class="headerlink" title="改变线条样式"></a>改变线条样式</h6><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.RangingTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> rangingTool=<span class="keyword">new</span> AMap.RangingTool(map,&#123;</span><br><span class="line">lineOptions:&#123;</span><br><span class="line">strokeColor:<span class="string">"#ff3300"</span>,</span><br><span class="line">strokeStyle:<span class="string">"dashed"</span>,</span><br><span class="line">strokeWeight:<span class="number">10</span>,</span><br><span class="line">strokeOpacity:<span class="number">0.5</span>,</span><br><span class="line">isOutline:<span class="literal">true</span>,</span><br><span class="line">outlineColor:<span class="string">"#009933"</span>,</span><br><span class="line">showDir:<span class="literal">true</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;);</span><br><span class="line">rangingTool.turnOn();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap303.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h2 id="小练习"><a href="#小练习" class="headerlink" title="小练习"></a>小练习</h2><h4 id="绘制太原市区的大概范围"><a href="#绘制太原市区的大概范围" class="headerlink" title="绘制太原市区的大概范围"></a>绘制太原市区的大概范围</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 用坐标拾取器获得坐标</span></span><br><span class="line"><span class="keyword">var</span> lineArr=[</span><br><span class="line">[<span class="number">112.490931</span>,<span class="number">37.898793</span>],</span><br><span class="line">[<span class="number">112.553588</span>,<span class="number">37.898793</span>],</span><br><span class="line">[<span class="number">112.603026</span>,<span class="number">37.899877</span>],</span><br><span class="line">[<span class="number">112.605086</span>,<span class="number">37.855028</span>],</span><br><span class="line">[<span class="number">112.605601</span>,<span class="number">37.831169</span>],</span><br><span class="line">[<span class="number">112.610236</span>,<span class="number">37.824661</span>],</span><br><span class="line">[<span class="number">112.610236</span>,<span class="number">37.798487</span>],</span><br><span class="line">[<span class="number">112.602683</span>,<span class="number">37.793739</span>],</span><br><span class="line">[<span class="number">112.499171</span>,<span class="number">37.793739</span>],</span><br><span class="line">[<span class="number">112.495051</span>,<span class="number">37.794553</span>],</span><br><span class="line">[<span class="number">112.500544</span>,<span class="number">37.830762</span>],</span><br><span class="line">[<span class="number">112.500716</span>,<span class="number">37.843099</span>],</span><br><span class="line">[<span class="number">112.48973</span>,<span class="number">37.847301</span>],</span><br><span class="line">[<span class="number">112.489901</span>,<span class="number">37.896897</span>],</span><br><span class="line">[<span class="number">112.492476</span>,<span class="number">37.8992</span>]</span><br><span class="line">];</span><br><span class="line"><span class="comment">// 实例化一个Polyline类</span></span><br><span class="line"><span class="keyword">var</span> polyline=<span class="keyword">new</span> AMap.Polyline(&#123;</span><br><span class="line">path:lineArr,</span><br><span class="line">strokeColor:<span class="string">"#ff2200"</span>,</span><br><span class="line">strokeWeight:<span class="number">5</span></span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 添加到地图中</span></span><br><span class="line">polyline.setMap(map);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap304.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（三）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（三）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（三）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（二）</title>
    <link href="http://yangfan.site/2017/02/21/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E4%BA%8C%EF%BC%89/"/>
    <id>http://yangfan.site/2017/02/21/高德地图 Javascript API 入门（二）/</id>
    <published>2017-02-21T05:53:12.000Z</published>
    <updated>2019-04-25T09:00:27.205Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（二）"><a href="#高德地图-Javascript-API-入门（二）" class="headerlink" title="高德地图 Javascript API 入门（二）"></a>高德地图 Javascript API 入门（二）</h1><h2 id="鼠标工具插件"><a href="#鼠标工具插件" class="headerlink" title="鼠标工具插件"></a>鼠标工具插件</h2><h4 id="测量距离"><a href="#测量距离" class="headerlink" title="测量距离"></a>测量距离</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.rule();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap201.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="测量面积"><a href="#测量面积" class="headerlink" title="测量面积"></a>测量面积</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.measureArea();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap202.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="绘制点标注"><a href="#绘制点标注" class="headerlink" title="绘制点标注"></a>绘制点标注</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.marker();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap203.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="绘制折线"><a href="#绘制折线" class="headerlink" title="绘制折线"></a>绘制折线</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.polyline();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap204.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="绘制多边形"><a href="#绘制多边形" class="headerlink" title="绘制多边形"></a>绘制多边形</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.polygon();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap205.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="绘制矩形"><a href="#绘制矩形" class="headerlink" title="绘制矩形"></a>绘制矩形</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.rectangle();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap206.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="绘制圆"><a href="#绘制圆" class="headerlink" title="绘制圆"></a>绘制圆</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.circle();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap207.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="全部功能"><a href="#全部功能" class="headerlink" title="全部功能"></a>全部功能</h4><table style="width:100%;border-collapse:collapse;"><tbody><tr><th style="white-space:nowrap;"><p>方法</p></th><th style="white-space:nowrap;"><p>返回值</p></th><th><p>说明</p></th></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">marker( options：</code><a href="/api/javascript-api/reference/overlay#MarkerOptions" class target><code class="inline-code">MarkerOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p><p>&nbsp;</p></td><td><p>开启鼠标画点标注模式。鼠标在地图上单击绘制点标注，标注样式参考MarkerOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">polyline( options：</code><a href="/api/javascript-api/reference/overlay#PolylineOptions" class target><code class="inline-code">PolylineOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启鼠标画折线模式。鼠标在地图上点击绘制折线，鼠标左键双击或右键单击结束绘制，折线样式参考PolylineOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">polygon( options：</code><a href="/api/javascript-api/reference/overlay#PolygonOptions" class target><code class="inline-code">PolygonOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启鼠标画多边形模式。鼠标在地图上单击开始绘制多边形，鼠标左键双击或右键单击结束当前多边形的绘制，多边形样式参考PolygonOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">rectangle( options：</code><a href="/api/javascript-api/reference/overlay#PolygonOptions" class target><code class="inline-code">PolygonOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启鼠标画矩形模式。鼠标在地图上拉框即可绘制相应的矩形。矩形样式参考PolygonOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">circle( options：</code><a href="/api/javascript-api/reference/overlay#CircleOptions" class target><code class="inline-code">CircleOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启鼠标画圆模式。鼠标在地图上拖动绘制相应的圆形。圆形样式参考CircleOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">rule( options：</code><a href="/api/javascript-api/reference/overlay#PolylineOptions" class target><code class="inline-code">PolylineOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启距离量测模式。鼠标在地图上单击绘制量测节点，并计算显示两两节点之间的距离，鼠标左键双击或右键单击结束当前量测操作。量测线样式参考 <a href="/api/javascript-api/reference/overlay#PolylineOptions" class target>PolylineOptions</a> 设置</p><p>注：不能同时使用rule方法和RangTool插件进行距离量测</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">measureArea( options：</code><a href="/api/javascript-api/reference/overlay#PolygonOptions" class target><code class="inline-code">PolygonOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启面积量测模式。鼠标在地图上单击绘制量测区域，鼠标左键双击或右键单击结束当前量测操作，并显示本次量测结果。量测面样式参考PolygonOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">rectZoomIn( options：</code><a href="/api/javascript-api/reference/overlay#PolygonOptions" class target><code class="inline-code">PolygonOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启鼠标拉框放大模式。鼠标可在地图上拉框放大地图。矩形框样式参考PolygonOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">rectZoomOut( options：</code><a href="/api/javascript-api/reference/overlay#PolygonOptions" class target><code class="inline-code">PolygonOptions</code></a><code class="inline-code">)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>开启鼠标拉框缩小模式。鼠标可在地图上拉框缩小地图。矩形框样式参考PolygonOptions设置</p></td></tr><tr><td style="white-space:nowrap;"><p><code class="inline-code">close( Boolean)</code></p></td><td style="white-space:nowrap;"><p><br></p></td><td><p>关闭当前鼠标操作。参数arg设为true时，鼠标操作关闭的同时清除地图上绘制的所有覆盖物对象；设为false时，保留所绘制的覆盖物对象。默认为false</p></td></tr></tbody></table><h4 id="自定义覆盖物样式"><a href="#自定义覆盖物样式" class="headerlink" title="自定义覆盖物样式"></a>自定义覆盖物样式</h4><p>以折线为例 Polyline</p><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.MouseTool"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> mouseTool=<span class="keyword">new</span> AMap.MouseTool(map);</span><br><span class="line">mouseTool.polyline(&#123;</span><br><span class="line">strokeColor:<span class="string">"#f50"</span>, <span class="comment">// 线条颜色，十六进制</span></span><br><span class="line">strokeOpacity:<span class="number">0.5</span>, <span class="comment">// 线条透明度</span></span><br><span class="line">strokeWeight:<span class="number">10</span>, <span class="comment">// 线条宽度</span></span><br><span class="line">strokeStyle:<span class="string">"dashed"</span> <span class="comment">// 线条样式 solid || dashed</span></span><br><span class="line">&#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>更多详细参数参考 <a href="http://lbs.amap.com/api/javascript-api/reference/overlay#PolylineOptions" title="Polyline类" target="_blank" rel="noopener">http://lbs.amap.com/api/javascript-api/reference/overlay#PolylineOptions</a></p><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap208.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（二）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（二）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（二）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>高德地图 Javascript API 入门（一）</title>
    <link href="http://yangfan.site/2017/02/20/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE%20Javascript%20API%20%E5%85%A5%E9%97%A8%EF%BC%88%E4%B8%80%EF%BC%89/"/>
    <id>http://yangfan.site/2017/02/20/高德地图 Javascript API 入门（一）/</id>
    <published>2017-02-20T11:32:00.000Z</published>
    <updated>2019-04-25T09:00:36.531Z</updated>
    
    <content type="html"><![CDATA[<h1 id="高德地图-Javascript-API-入门（一）"><a href="#高德地图-Javascript-API-入门（一）" class="headerlink" title="高德地图 Javascript API 入门（一）"></a>高德地图 Javascript API 入门（一）</h1><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><h4 id="首先注册个开发者账号"><a href="#首先注册个开发者账号" class="headerlink" title="首先注册个开发者账号"></a>首先注册个开发者账号</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap101.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="然后创建应用，获取Key"><a href="#然后创建应用，获取Key" class="headerlink" title="然后创建应用，获取Key"></a>然后创建应用，获取Key</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap102.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="新建HTML文件，在body标签中引入如下代码（把你的Key值填入即可）"><a href="#新建HTML文件，在body标签中引入如下代码（把你的Key值填入即可）" class="headerlink" title="新建HTML文件，在body标签中引入如下代码（把你的Key值填入即可）"></a>新建HTML文件，在body标签中引入如下代码（把你的Key值填入即可）</h4><p>HTML</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"http://webapi.amap.com/maps?v=1.3&amp;key=您申请的key值"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="创建设置地图容器"><a href="#创建设置地图容器" class="headerlink" title="创建设置地图容器"></a>创建设置地图容器</h4><p>HTML</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"container"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>CSS</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#container</span> &#123;<span class="attribute">width</span>:<span class="number">300px</span>; <span class="attribute">height</span>: <span class="number">180px</span>; &#125;</span><br></pre></td></tr></table></figure><h2 id="地图初始化"><a href="#地图初始化" class="headerlink" title="地图初始化"></a>地图初始化</h2><h4 id="创建地图"><a href="#创建地图" class="headerlink" title="创建地图"></a>创建地图</h4><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> map = <span class="keyword">new</span> AMap.Map(<span class="string">'container'</span>);</span><br></pre></td></tr></table></figure><h4 id="设置地图参数"><a href="#设置地图参数" class="headerlink" title="设置地图参数"></a>设置地图参数</h4><p>可以通过以下设置<br>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> map = <span class="keyword">new</span> AMap.Map(<span class="string">'container'</span>,&#123;</span><br><span class="line">   zoom: <span class="number">12</span>,</span><br><span class="line">   center: [<span class="number">112.549248</span>,<span class="number">37.852135</span>]</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>也可通过map对象的方法设置</p><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> map = <span class="keyword">new</span> AMap.Map(<span class="string">'container'</span>);</span><br><span class="line">map.setZoom(<span class="number">12</span>);</span><br><span class="line">map.setCenter([<span class="number">112.549248</span>,<span class="number">37.852135</span>]);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap103.JPG" alt="image" title="高德地图">                </div>                <div class="image-caption">高德地图</div>            </figure><h2 id="个性化地图"><a href="#个性化地图" class="headerlink" title="个性化地图"></a>个性化地图</h2><h4 id="改变地图样式"><a href="#改变地图样式" class="headerlink" title="改变地图样式"></a>改变地图样式</h4><p>目前支持五种地图配色模版</p><p>地图类型列表</p><table style="width:100%;border-collapse:collapse;"><tbody><tr><th><p>名称</p></th><th><p>说明</p></th></tr><tr><td><p>normal</p></td><td><p>默认样式</p></td></tr><tr><td><p>dark</p></td><td><p>深色样式</p></td></tr><tr><td><p>blue_night</p></td><td><p>夜空蓝样式</p></td></tr><tr><td><p>fresh</p></td><td><p>浅色样式</p></td></tr><tr><td><p>light</p></td><td><p>osm清新风格样式</p></td></tr></tbody></table><p>可以这样设置<br>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> map = <span class="keyword">new</span> AMap.Map(<span class="string">'container'</span>, &#123;</span><br><span class="line">       resizeEnable: <span class="literal">true</span>,</span><br><span class="line">       mapStyle:<span class="string">'fresh'</span>,</span><br><span class="line">       center: [<span class="number">116.408075</span>, <span class="number">39.950187</span>]</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure><p>也可以这样设置<br>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">map.setMapStyle(<span class="string">"fresh"</span>);</span><br></pre></td></tr></table></figure><p>预览</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap104.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h4 id="显示指定地图内容（地图要素）"><a href="#显示指定地图内容（地图要素）" class="headerlink" title="显示指定地图内容（地图要素）"></a>显示指定地图内容（地图要素）</h4><table style="width:100%;border-collapse:collapse;"><tbody><tr><th><p>名称</p></th><th><p>说明</p></th></tr><tr><td><p>bg</p></td><td><p>背景地图</p></td></tr><tr><td><p>point</p></td><td><p>兴趣点</p></td></tr><tr><td><p>road</p></td><td><p>道路</p></td></tr><tr><td><p>building</p></td><td><p>建筑</p></td></tr></tbody></table><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">map.setFeatures(<span class="string">"road"</span>);<span class="comment">//单一种类要素显示</span></span><br><span class="line">map.setFeatures([<span class="string">'road'</span>,<span class="string">'point'</span>])<span class="comment">//多个种类要素显示</span></span><br></pre></td></tr></table></figure><p>预览（只显示道路要素的地图）</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap105.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><h2 id="地图控件"><a href="#地图控件" class="headerlink" title="地图控件"></a>地图控件</h2><p>JavaScript API提供了工具条、比例尺、定位、鹰眼、基本图层切换等常用的控件</p><table style="width:100%;border-collapse:collapse;"><tbody><tr><th><p>名称</p></th><th><p>类名</p></th><th><p>简介</p></th></tr><tr><td><p>工具条</p></td><td><p>ToolBar</p></td><td><p>集成了缩放、平移、定位等功能按钮在内的组合控件</p></td></tr><tr><td><p>比例尺</p></td><td><p>Scale</p></td><td><p>展示地图在当前层级和纬度下的比例尺</p></td></tr><tr><td><p>定位</p></td><td><p>Geolocation</p></td><td><p>用来获取和展示用户主机所在的经纬度位置</p></td></tr><tr><td><p>鹰眼</p></td><td><p>OverView</p></td><td><p>在地图右下角显示地图的缩略图</p></td></tr><tr><td><p>类别切换</p></td><td><p>MapType</p></td><td><p>实现默认图层与卫星图、实施交通图层之间切换的控</p></td></tr></tbody></table><p>添加控件</p><p>JS</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">map.plugin([<span class="string">"AMap.ToolBar"</span>],<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">map.addControl(<span class="keyword">new</span> AMap.ToolBar()); <span class="comment">// 工具条控件</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>（其他控件添加方式同上）</p><p>预览（带有工具条控件的地图）</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/AMap/amap106.JPG" alt="image" title>                </div>                <div class="image-caption">image</div>            </figure><hr><p>参考来源：<a href="http://lbs.amap.com/" title="高德地图开放平台" target="_blank" rel="noopener">http://lbs.amap.com/</a><br>作者：<a href="http://yangfan.ga" title="http://yangfan.ga" target="_blank" rel="noopener">Yangfan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;高德地图-Javascript-API-入门（一）&quot;&gt;&lt;a href=&quot;#高德地图-Javascript-API-入门（一）&quot; class=&quot;headerlink&quot; title=&quot;高德地图 Javascript API 入门（一）&quot;&gt;&lt;/a&gt;高德地图 Javasc
      
    
    </summary>
    
    
      <category term="JS" scheme="http://yangfan.site/tags/JS/"/>
    
      <category term="GIS" scheme="http://yangfan.site/tags/GIS/"/>
    
      <category term="API" scheme="http://yangfan.site/tags/API/"/>
    
  </entry>
  
  <entry>
    <title>HTML+CSS+JAVASCRIPT 网易云音乐播放器</title>
    <link href="http://yangfan.site/2017/02/18/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%92%AD%E6%94%BE%E5%99%A8/"/>
    <id>http://yangfan.site/2017/02/18/网易云音乐播放器/</id>
    <published>2017-02-18T12:15:55.000Z</published>
    <updated>2019-04-25T09:00:46.714Z</updated>
    
    <content type="html"><![CDATA[<h2 id="HTML-CSS-JAVASCRIPT-高仿低配网页版网易云音乐播放器"><a href="#HTML-CSS-JAVASCRIPT-高仿低配网页版网易云音乐播放器" class="headerlink" title="HTML+CSS+JAVASCRIPT 高仿低配网页版网易云音乐播放器"></a>HTML+CSS+JAVASCRIPT 高仿低配网页版网易云音乐播放器</h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/cloud-music-pc.gif" alt="app-poster" title>                </div>                <div class="image-caption">app-poster</div>            </figure><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>没有使用任何框架，只是想用最简单纯js的代码实现下  </p><ul><li>前台: Javascript+jQuery  </li><li>后台: php/nodejs（php是参考网上的例子写的，nodejs代码是在php的基础上重新写的）  </li><li>还有她的姊妹篇（网易云音乐移动端），请查看这里  <a href="https://github.com/Yangfan2016/cloud-music-mobile#cloud-music-mobile" target="_blank" rel="noopener">https://github.com/Yangfan2016/cloud-music-mobile#cloud-music-mobile</a></li></ul><h3 id="写在前头的话"><a href="#写在前头的话" class="headerlink" title="写在前头的话"></a>写在前头的话</h3><p>鄙人野生前端一只，gis专业，自学前端已经一年多了，为什么要写个音乐播放器呢？原因有两个：  </p><ol><li>本人是网易云音乐的重度用户，近乎疯狂  </li><li>自学了前端这么久了，也是想检验下自己的成果吧</li></ol><h3 id="本播放器要干什么呢"><a href="#本播放器要干什么呢" class="headerlink" title="本播放器要干什么呢"></a>本播放器要干什么呢</h3><ol><li>简单的 <strong>播放</strong> <strong>暂停</strong> 那当然不能少</li><li>切换歌曲，<strong>上一首</strong> 、 <strong>下一首</strong> 也得有</li><li><strong>进度条</strong> ，这个有点复杂，本来想用 input[range] 写，但是样式不好改，自己用多个div代替吧</li><li>进度条都有了，<strong>音量调节</strong> 不能少吧，毕竟他俩UI样式差不多，照猫画虎呗</li><li>再加一个 <strong>静音功能</strong> ，省的音乐太大声，邻居找茬哦(⊙o⊙)</li></ol><h3 id="本播放器还能干什么呢"><a href="#本播放器还能干什么呢" class="headerlink" title="本播放器还能干什么呢"></a>本播放器还能干什么呢</h3><ol><li><strong>歌词滚动</strong> 有木有</li><li><strong>搜索单曲</strong> </li><li><strong>指定歌单播放</strong>  这个需要知道歌单的 id 不是很好找，（得上<a href="http://music.163.com" target="_blank" rel="noopener">网易云音乐官网</a>登录自己的账号，找到歌单，点进去，抬头看URL 里最后的 id 参数）暂时用的是“我喜欢的音乐”（歌单）的id</li></ol><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/cloud-music-pc-wins003.JPG" alt="music-163" title>                </div>                <div class="image-caption">music-163</div>            </figure><h3 id="那闲话不多说，开整吧（原谅一个理科生的表达能力）"><a href="#那闲话不多说，开整吧（原谅一个理科生的表达能力）" class="headerlink" title="那闲话不多说，开整吧（原谅一个理科生的表达能力）"></a>那闲话不多说，开整吧（原谅一个理科生的表达能力）</h3><p>我模仿的是网易云音乐的PC端，所用到的技术都是前端的基本技术 HTML、CSS、JAVASCRIPT<br>由于我是自学的，没有那么多规矩，我这个人看到是我感兴趣的，我立马就会去做，这个播放器也不例外。</p><blockquote><p>首先先的将它“画”出来（HTML+CSS）</p></blockquote><p>我仔细看了下网易云音乐PC端的布局，大致分为四部分，四个模块</p><ol><li>顶部菜单（顶部导航，叫什么名无所谓了）</li><li>底部播放条 这是播放器的核心</li><li>主体内容在右边 歌单的详细信息和歌曲列表</li><li>左侧是导航和歌单组</li><li>左下角还有一个小窗，显示正在播放歌曲的简要信息，点击小窗 展开一个歌曲详情页</li></ol><p>无图不真相<br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/cloud-music-pc-wins001.JPG" alt="pc-music" title>                </div>                <div class="image-caption">pc-music</div>            </figure><br><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://raw.githubusercontent.com/Yangfan2016/PicBed/master/Blog/cloud-music-pc-wins002.JPG" alt="pc-music" title>                </div>                <div class="image-caption">pc-music</div>            </figure></p><blockquote><p>然后呢，写页面逻辑JavaScript</p></blockquote><h3 id="播放器"><a href="#播放器" class="headerlink" title="播放器"></a>播放器</h3><ol><li>播放器的控制按钮<br>播放(暂停)按钮，这个可以通过<code>play()</code>和<code>pause()</code>方法实现</li><li>进度条<br>这个通过监听<code>timeupdate</code>事件，实施更新当前播放位置，<br>通过监听鼠标移动事件，改变进度条的长度</li><li>静音按钮，可以通过<code>audio.muted=true</code>实现</li></ol><h3 id="初始化歌单列表"><a href="#初始化歌单列表" class="headerlink" title="初始化歌单列表"></a>初始化歌单列表</h3><p>网易云音乐获取歌单的API<br><a href="http://music.163.com/api/playlist/detail?id=[id]" target="_blank" rel="noopener">http://music.163.com/api/playlist/detail?id=[id]</a></p><pre><code>id 歌单id</code></pre><p>因为涉及到跨域问题。暂时我前台这边又没有办法跨域，所以参考了网上的代码，<del>写个PHP做代理</del> （2018-09-14更新：现在代码已改为Nodejs做代理服务），这样就不存在跨域问题了。<br>获取到歌单数据后，重新渲染下DOM</p><h3 id="搜索歌曲"><a href="#搜索歌曲" class="headerlink" title="搜索歌曲"></a>搜索歌曲</h3><p>网易云音乐获取歌曲的API<br><a href="http://s.music.163.com/search/get?s=[songname]&amp;type=1&amp;limit=10" target="_blank" rel="noopener">http://s.music.163.com/search/get?s=[songname]&amp;type=1&amp;limit=10</a></p><pre><code>s           搜索内容type        搜索类型limit       搜索返回结果数</code></pre><h3 id="歌曲详情页"><a href="#歌曲详情页" class="headerlink" title="歌曲详情页"></a>歌曲详情页</h3><p>主要是歌词和歌词滚动</p><p>网易云音乐获取歌词API<br><a href="http://music.163.com/api/song/lyric?os=pc&amp;id=[id]" target="_blank" rel="noopener">http://music.163.com/api/song/lyric?os=pc&amp;id=[id]</a></p><pre><code>id 歌曲id</code></pre><p>歌词滚动，先把获取到的歌词数据分割成时间点和歌词两部分，将这两部分存入dataset中，<br>通过监听timeupdate事件，判断和当前播放时间相近的歌词，记录它的getBoundingClient()的top值，将滚动条设置到指定位置 例如：<code>ele.srcollTop=100;</code></p><h3 id="先写到这里吧"><a href="#先写到这里吧" class="headerlink" title="先写到这里吧"></a>先写到这里吧</h3><p>总结能力太差了，原谅理科生的无奈</p><h3 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h3><p><a href="https://github.com/Yangfan2016/cloud-music-web" target="_blank" rel="noopener">完整源码，点击查看</a><br><a href="https://github.com/Yangfan2016/cloud-music-web/tree/master/server" target="_blank" rel="noopener">后台代码，点击查看</a></p><p>此文源自我的<a href="https://yangfan2016.github.io/2017/02/18/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%92%AD%E6%94%BE%E5%99%A8/" target="_blank" rel="noopener">博客</a></p><h4 id="大佬，给个start呗"><a href="#大佬，给个start呗" class="headerlink" title="大佬，给个start呗^_^"></a>大佬，给个<a href="https://github.com/Yangfan2016/cloud-music-web" target="_blank" rel="noopener">start</a>呗^_^</h4>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;HTML-CSS-JAVASCRIPT-高仿低配网页版网易云音乐播放器&quot;&gt;&lt;a href=&quot;#HTML-CSS-JAVASCRIPT-高仿低配网页版网易云音乐播放器&quot; class=&quot;headerlink&quot; title=&quot;HTML+CSS+JAVASCRIPT 高仿
      
    
    </summary>
    
    
      <category term="前端" scheme="http://yangfan.site/tags/%E5%89%8D%E7%AB%AF/"/>
    
      <category term="音乐播放器" scheme="http://yangfan.site/tags/%E9%9F%B3%E4%B9%90%E6%92%AD%E6%94%BE%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>教你快速搭建个人博客</title>
    <link href="http://yangfan.site/2017/02/03/%E6%95%99%E4%BD%A0%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/"/>
    <id>http://yangfan.site/2017/02/03/教你快速搭建个人博客/</id>
    <published>2017-02-03T12:15:55.000Z</published>
    <updated>2019-04-25T09:01:06.601Z</updated>
    
    <content type="html"><![CDATA[<h3 id="基于HEXO博客框架和Github搭建个人博客简单教程"><a href="#基于HEXO博客框架和Github搭建个人博客简单教程" class="headerlink" title="基于HEXO博客框架和Github搭建个人博客简单教程"></a>基于HEXO博客框架和Github搭建个人博客简单教程</h3><p>Author: <a href="https://github.com/Yangfan2016" target="_blank" rel="noopener">Yangfan</a><br>Time: 2017-02-03  </p><p><img src="http://upload-images.jianshu.io/upload_images/1400844-40d8b2e5a0a5c036?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="poster"></p><blockquote><h4 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h4></blockquote><p>配置环境</p><p>安装<a href="https://nodejs.org/en/" target="_blank" rel="noopener">Node.js</a><br>安装<a href="https://git-scm.com/" target="_blank" rel="noopener">Git</a><br>注册<a href="https://github.com" target="_blank" rel="noopener">GitHub</a>    </p><blockquote><h4 id="Hexo-部分"><a href="#Hexo-部分" class="headerlink" title="Hexo 部分"></a>Hexo 部分</h4></blockquote><ol><li><p>Hexo简介<br>Hexo 是一个轻量的静态博客框架。通过Hexo可以快速生成一个静态博客框架,仅需要几条命令就可以完成,相当方便。<br>而架设Hexo的环境更简单了 不需要 lnmp/lamp/XAMPP 这些繁琐复杂的环境 仅仅需要一个简单的http服务器即可使用 或者使用互联网上免费的页面托管服务</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="http://upload.chinaz.com/2016/0105/1451965733809.jpg" alt="hexo" title>                </div>                <div class="image-caption">hexo</div>            </figure></li><li><p>Hexo安装方法<br>参考<a href="https://hexo.io" target="_blank" rel="noopener">官网</a>中文文档,只需要一条命令即可自动安装hexo框架。<br><code>$ npm install -g hexo-cli #使用 npm 安装 Hexo</code></p></li></ol><ol><li>初始化<br>创建一个文件夹，如：Blog，cd到Blog里执行hexo init的。命令：<br><code>hexo init</code></li><li><p>生成静态页面<br>继续再Blog目录下执行如下命令，生成静态页面<br><code>hexo generate （或者 hexo g）</code> </p></li><li><p>本地启动<br>启动本地服务，进行文章预览调试，命令：<br><code>hexo server</code> </p></li><li>本地测试<br>浏览器输入 <a href="http://localhost:4000" target="_blank" rel="noopener">http://localhost:4000</a></li></ol><blockquote><h4 id="Github-部分"><a href="#Github-部分" class="headerlink" title="Github 部分"></a>Github 部分</h4></blockquote><ol><li>注册github<br><a href="https://github.com" target="_blank" rel="noopener">Github</a></li><li>新建仓库<br>建立与你用户名对应的仓库，仓库名必须为【your_user_name.github.io】， <strong>固定写法</strong>  !!!</li><li>本地_config.yml文配置件，建立关联<br>我们需要_config.yml文件，来建立关联(注意冒号后面要有空格)</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">deploy:  </span><br><span class="line">   type: git   </span><br><span class="line">   repository: https://github.com/leopardpan/  leopardpan.github.io.git  </span><br><span class="line">   branch: master</span><br></pre></td></tr></table></figure><blockquote><h4 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h4></blockquote><p>执行如下命令才能使用git部署<br><code>npm install hexo-deployer-git --save</code><br>(我没用SSH Keys如果你用了SSH Keys的话直接在github里复制SSH的就行了，总共就两种协议，相信你懂的。)<br> 执行配置命令：<br><code>hexo deploy</code><br>然后再浏览器中输入<a href="http://username.github.io/就行了，把" target="_blank" rel="noopener">http://username.github.io/就行了，把</a> username ,改成你 github 的账户名就行了</p><blockquote><h4 id="发文章"><a href="#发文章" class="headerlink" title="发文章"></a>发文章</h4></blockquote><p>每次部署的步骤，可按以下三步来进行。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">hexo clean  </span><br><span class="line">hexo generate  </span><br><span class="line">hexo deploy</span><br></pre></td></tr></table></figure><p>一些常用命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">hexo new &quot;postName&quot; #新建文章  </span><br><span class="line">hexo new page &quot;pageName&quot; #新建页面  </span><br><span class="line">hexo generate #生成静态页面至public目录  </span><br><span class="line">hexo server #开启预览访问端口（默认端口4000，&apos;ctrl + c&apos;关闭server）  </span><br><span class="line">hexo deploy #将.deploy目录部署到GitHub  </span><br><span class="line">hexo help  #查看帮助  </span><br><span class="line">hexo version  #查看Hexo的版本</span><br></pre></td></tr></table></figure><hr><p>参考：  </p><ol><li><a href="http://www.jianshu.com/p/465830080ea9" target="_blank" rel="noopener">http://www.jianshu.com/p/465830080ea9</a>  </li><li><a href="http://www.chinaz.com/web/2016/0105/491998.shtml" target="_blank" rel="noopener">http://www.chinaz.com/web/2016/0105/491998.shtml</a></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;基于HEXO博客框架和Github搭建个人博客简单教程&quot;&gt;&lt;a href=&quot;#基于HEXO博客框架和Github搭建个人博客简单教程&quot; class=&quot;headerlink&quot; title=&quot;基于HEXO博客框架和Github搭建个人博客简单教程&quot;&gt;&lt;/a&gt;基于HEX
      
    
    </summary>
    
    
      <category term="博客" scheme="http://yangfan.site/tags/%E5%8D%9A%E5%AE%A2/"/>
    
      <category term="建站" scheme="http://yangfan.site/tags/%E5%BB%BA%E7%AB%99/"/>
    
      <category term="Hexo" scheme="http://yangfan.site/tags/Hexo/"/>
    
  </entry>
  
</feed>
