<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://karl-cheung.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://karl-cheung.github.io/" rel="alternate" type="text/html" /><updated>2024-09-25T09:12:27+00:00</updated><id>https://karl-cheung.github.io/feed.xml</id><title type="html">Zhang Yu</title><subtitle>A practice trip for a front-end r&amp;d engineer.
</subtitle><author><name>karl-cheung</name></author><entry><title type="html">防抖函数与节流函数</title><link href="https://karl-cheung.github.io/jekyll/update/2023/04/21/debounce-and-throttle.html" rel="alternate" type="text/html" title="防抖函数与节流函数" /><published>2023-04-21T00:00:00+00:00</published><updated>2023-04-21T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2023/04/21/debounce-and-throttle</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2023/04/21/debounce-and-throttle.html"><![CDATA[<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 防抖函数</span>
<span class="kd">function</span> <span class="nx">debounce</span><span class="p">(</span><span class="nx">fun</span><span class="p">,</span> <span class="nx">delay</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="kd">function</span> <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">fun</span><span class="p">.</span><span class="nx">timer</span><span class="p">)</span>
    <span class="nx">fun</span><span class="p">.</span><span class="nx">timer</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">fun</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">args</span><span class="p">)</span>
    <span class="p">},</span> <span class="nx">delay</span><span class="p">)</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// 节流函数</span>
<span class="kd">function</span> <span class="nx">throttle</span><span class="p">(</span><span class="nx">fun</span><span class="p">,</span> <span class="nx">delay</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="kd">function</span> <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">fun</span><span class="p">.</span><span class="nx">timer</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
    <span class="nx">fun</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">args</span><span class="p">)</span>
    <span class="nx">fun</span><span class="p">.</span><span class="nx">timer</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">fun</span><span class="p">.</span><span class="nx">timer</span> <span class="o">=</span> <span class="kc">null</span>
    <span class="p">},</span> <span class="nx">delay</span><span class="p">)</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// 验证</span>
<span class="kd">function</span> <span class="nx">test</span><span class="p">(</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">delay</span><span class="p">,</span> <span class="nx">num</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">while</span> <span class="p">(</span><span class="nx">num</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">random</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">round</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="nx">delay</span><span class="p">)</span>
    <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">random</span><span class="p">)</span>
      <span class="nx">fn</span><span class="p">(</span><span class="nx">random</span><span class="p">)</span>
    <span class="p">},</span> <span class="nx">random</span><span class="p">)</span>
    <span class="nx">num</span><span class="o">--</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">DELAY</span> <span class="o">=</span> <span class="mi">1000</span> <span class="c1">// 时间阈值</span>
<span class="kd">const</span> <span class="nx">NUM</span> <span class="o">=</span> <span class="mi">3</span> <span class="c1">// 验证次数</span>

<span class="nx">test</span><span class="p">(</span><span class="nx">debounce</span><span class="p">((</span><span class="nx">last</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">只有最后一次实际执行</span><span class="dl">'</span><span class="p">,</span> <span class="nx">last</span><span class="p">),</span> <span class="nx">DELAY</span><span class="p">),</span> <span class="nx">DELAY</span><span class="p">,</span> <span class="nx">NUM</span><span class="p">)</span>
<span class="c1">// test(throttle((first) =&gt; console.log('只有第一次实际执行', first), DELAY), DELAY, NUM)</span>
</code></pre></div></div>]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[```js // 防抖函数 function debounce(fun, delay) { return function (…args) { clearTimeout(fun.timer) fun.timer = setTimeout(() =&gt; { fun.apply(this, args) }, delay) } }]]></summary></entry><entry><title type="html">GitHub email 变更同步 contributions</title><link href="https://karl-cheung.github.io/jekyll/update/2022/09/01/github-email-change-contributions-copy.html" rel="alternate" type="text/html" title="GitHub email 变更同步 contributions" /><published>2022-09-01T00:00:00+00:00</published><updated>2022-09-01T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2022/09/01/github-email-change-contributions%20copy</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2022/09/01/github-email-change-contributions-copy.html"><![CDATA[<h2 id="变更">变更</h2>

<blockquote>
  <p>命令行运行</p>
</blockquote>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git filter-branch <span class="nt">--env-filter</span> <span class="s1">'

OLD_EMAIL="old_email@example.com"
CORRECT_NAME="correct_name"
CORRECT_EMAIL="correct_email@example.com"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
'</span> <span class="nt">--tag-name-filter</span> <span class="nb">cat</span> <span class="nt">--</span> <span class="nt">--branches</span> <span class="nt">--tags</span>
</code></pre></div></div>

<h2 id="提交">提交</h2>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push <span class="nt">--force</span>
</code></pre></div></div>]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[变更]]></summary></entry><entry><title type="html">egg 集群定时任务调度</title><link href="https://karl-cheung.github.io/jekyll/update/2019/09/05/egg-cluster-schedule.html" rel="alternate" type="text/html" title="egg 集群定时任务调度" /><published>2019-09-05T00:00:00+00:00</published><updated>2019-09-05T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2019/09/05/egg-cluster-schedule</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2019/09/05/egg-cluster-schedule.html"><![CDATA[<h2 id="案例一">案例一</h2>

<blockquote>
  <p>5 分钟调度一次</p>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">/app/schedule/cluster.js</code></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">'</span><span class="s1">use strict</span><span class="dl">'</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">schedule</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">interval</span><span class="p">:</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>
    <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">cluster</span><span class="dl">'</span>
  <span class="p">},</span>

  <span class="k">async</span> <span class="nx">task</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// do something...</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">/agent.js</code></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">'</span><span class="s1">use strict</span><span class="dl">'</span>

<span class="kd">const</span> <span class="nx">sleep</span> <span class="o">=</span> <span class="nx">s</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="nx">resolve</span> <span class="o">=&gt;</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">s</span><span class="p">))</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">agent</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">class</span> <span class="nx">ClusterStrategy</span> <span class="kd">extends</span> <span class="nx">agent</span><span class="p">.</span><span class="nx">ScheduleStrategy</span> <span class="p">{</span>
    <span class="nx">start</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">try</span> <span class="p">{</span>
        <span class="p">;(</span><span class="k">async</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
          <span class="k">while</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">const</span> <span class="p">{</span> <span class="nx">interval</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">schedule</span>
            <span class="k">await</span> <span class="nx">sleep</span><span class="p">(</span><span class="nx">interval</span><span class="p">)</span>
            <span class="k">this</span><span class="p">.</span><span class="nx">sendOne</span><span class="p">()</span>
          <span class="p">}</span>
        <span class="p">})()</span>
      <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">ctx</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="nx">agent</span><span class="p">.</span><span class="nx">schedule</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="dl">'</span><span class="s1">cluster</span><span class="dl">'</span><span class="p">,</span> <span class="nx">ClusterStrategy</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="案例二">案例二</h2>

<blockquote>
  <p>每天凌晨调度一次</p>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">/app/schedule/cluster.js</code></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">'</span><span class="s1">use strict</span><span class="dl">'</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">schedule</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">cron</span><span class="p">:</span> <span class="dl">'</span><span class="s1">0 0 0 * * *</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">cluster</span><span class="dl">'</span>
  <span class="p">},</span>

  <span class="k">async</span> <span class="nx">task</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// do something...</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">/agent.js</code></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">'</span><span class="s1">use strict</span><span class="dl">'</span>

<span class="kd">const</span> <span class="nx">parser</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">cron-parser</span><span class="dl">'</span><span class="p">)</span>

<span class="kd">const</span> <span class="nx">sleep</span> <span class="o">=</span> <span class="nx">s</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="nx">resolve</span> <span class="o">=&gt;</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">s</span><span class="p">))</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">agent</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">class</span> <span class="nx">ClusterStrategy</span> <span class="kd">extends</span> <span class="nx">agent</span><span class="p">.</span><span class="nx">ScheduleStrategy</span> <span class="p">{</span>
    <span class="nx">start</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">try</span> <span class="p">{</span>
        <span class="p">;(</span><span class="k">async</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
          <span class="kd">const</span> <span class="p">{</span> <span class="nx">cron</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">schedule</span>
          <span class="kd">const</span> <span class="nx">interval</span> <span class="o">=</span> <span class="nx">parser</span><span class="p">.</span><span class="nx">parseExpression</span><span class="p">(</span><span class="nx">cron</span><span class="p">)</span>
          <span class="k">while</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">const</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">interval</span><span class="p">.</span><span class="nx">next</span><span class="p">()</span>
            <span class="kd">const</span> <span class="nx">date</span> <span class="o">=</span> <span class="nx">next</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
            <span class="kd">const</span> <span class="nx">timestamp</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">date</span><span class="p">).</span><span class="nx">getTime</span><span class="p">()</span>
            <span class="k">await</span> <span class="nx">sleep</span><span class="p">(</span><span class="nx">timestamp</span> <span class="o">-</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">())</span>
            <span class="k">this</span><span class="p">.</span><span class="nx">sendOne</span><span class="p">()</span>
          <span class="p">}</span>
        <span class="p">})()</span>
      <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">ctx</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="nx">agent</span><span class="p">.</span><span class="nx">schedule</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="dl">'</span><span class="s1">cluster</span><span class="dl">'</span><span class="p">,</span> <span class="nx">ClusterStrategy</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[案例一]]></summary></entry><entry><title type="html">hammerjs 在 react 中的使用</title><link href="https://karl-cheung.github.io/jekyll/update/2019/08/12/hammer-react.html" rel="alternate" type="text/html" title="hammerjs 在 react 中的使用" /><published>2019-08-12T00:00:00+00:00</published><updated>2019-08-12T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2019/08/12/hammer-react</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2019/08/12/hammer-react.html"><![CDATA[<h2 id="使用">使用</h2>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react</span><span class="dl">'</span>
<span class="k">import</span> <span class="nx">Hammer</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">hammerjs</span><span class="dl">'</span>

<span class="kd">class</span> <span class="nx">HammerReact</span> <span class="kd">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span> <span class="p">{</span>
  <span class="nx">state</span> <span class="o">=</span> <span class="p">{</span> <span class="na">container</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createRef</span><span class="p">()</span> <span class="p">}</span>

  <span class="nx">componentDidMount</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="p">{</span> <span class="na">container</span><span class="p">:</span> <span class="p">{</span> <span class="nx">current</span> <span class="p">}</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">listener</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Hammer</span><span class="p">(</span><span class="nx">current</span><span class="p">)</span>
    <span class="c1">// 给监听的元素对象添加长按(press)事件</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">listener</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">press</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="c1">// Do some thing...</span>
    <span class="p">})</span>
  <span class="p">}</span>

  <span class="nx">componentWillUnmount</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">listener</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span> <span class="c1">// 销毁</span>
  <span class="p">}</span>

  <span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
    <span class="o">&lt;</span><span class="nx">div</span> <span class="nx">ref</span><span class="o">=</span><span class="p">{</span><span class="nx">container</span><span class="p">}</span><span class="o">&gt;</span><span class="nx">我是</span> <span class="nx">div</span><span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">}</span>
<span class="p">}</span>

<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">HammerReact</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">root</span><span class="dl">'</span><span class="p">))</span>
</code></pre></div></div>

<h2 id="附注">附注</h2>

<blockquote>
  <p>在添加的手势元素是动态渲染的情况下，通过事件委托的方式在父级元素处理。</p>
</blockquote>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">.</span><span class="nx">listener</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">press</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="na">target</span><span class="p">:</span> <span class="p">{</span> <span class="nx">nodeName</span> <span class="p">}</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">e</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">nodeName</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">DIV</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Do some thing...</span>
  <span class="p">}</span>
<span class="p">})</span>
</code></pre></div></div>]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[使用]]></summary></entry><entry><title type="html">二维码与链接相互转化</title><link href="https://karl-cheung.github.io/jekyll/update/2019/08/12/qrcode-link.html" rel="alternate" type="text/html" title="二维码与链接相互转化" /><published>2019-08-12T00:00:00+00:00</published><updated>2019-08-12T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2019/08/12/qrcode-link</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2019/08/12/qrcode-link.html"><![CDATA[<h2 id="二维码识别链接">二维码识别链接</h2>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"file"</span> <span class="na">accept=</span><span class="s">"image/*"</span> <span class="na">onChange=</span><span class="s">"{handleFileChange}"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// image2array.js</span>
<span class="k">export</span> <span class="k">default</span> <span class="kd">function</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">image</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Image</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span>
  <span class="nx">image</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">try</span> <span class="p">{</span>
      <span class="kd">let</span> <span class="p">{</span> <span class="na">naturalWidth</span><span class="p">:</span> <span class="nx">width</span><span class="p">,</span> <span class="na">naturalHeight</span><span class="p">:</span> <span class="nx">height</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">image</span>
      <span class="kd">const</span> <span class="nx">ratio</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="mi">500</span> <span class="o">/</span> <span class="nx">width</span><span class="p">,</span> <span class="mi">500</span> <span class="o">/</span> <span class="nx">height</span><span class="p">)</span>
      <span class="kd">const</span> <span class="nx">cWidth</span> <span class="o">=</span> <span class="o">~~</span><span class="p">(</span><span class="nx">ratio</span> <span class="o">*</span> <span class="nx">width</span><span class="p">)</span>
      <span class="kd">const</span> <span class="nx">cHeight</span> <span class="o">=</span> <span class="o">~~</span><span class="p">(</span><span class="nx">ratio</span> <span class="o">*</span> <span class="nx">height</span><span class="p">)</span>
      <span class="kd">const</span> <span class="nx">canvas</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">canvas</span><span class="dl">'</span><span class="p">)</span>
      <span class="kd">const</span> <span class="nx">ctx</span> <span class="o">=</span> <span class="nx">canvas</span><span class="p">.</span><span class="nx">getContext</span><span class="p">(</span><span class="dl">'</span><span class="s1">2d</span><span class="dl">'</span><span class="p">)</span>
      <span class="nx">canvas</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="nx">cWidth</span>
      <span class="nx">canvas</span><span class="p">.</span><span class="nx">height</span> <span class="o">=</span> <span class="nx">cHeight</span>
      <span class="nx">ctx</span><span class="p">.</span><span class="nx">drawImage</span><span class="p">(</span><span class="nx">image</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">width</span><span class="p">,</span> <span class="nx">height</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">cWidth</span><span class="p">,</span> <span class="nx">cHeight</span><span class="p">)</span>
      <span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">ctx</span><span class="p">.</span><span class="nx">getImageData</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">cWidth</span><span class="p">,</span> <span class="nx">cHeight</span><span class="p">)</span>
      <span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span>
    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">callback</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="nx">image</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">callback</span><span class="p">(</span><span class="dl">'</span><span class="s1">image load fail</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">}</span>
  <span class="nx">image</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="nx">url</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">jsQR</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">jsqr</span><span class="dl">'</span>
<span class="k">import</span> <span class="nx">image2array</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../../../utils/image2array</span><span class="dl">'</span>

<span class="kd">function</span> <span class="nx">handleFileChange</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">files</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">files</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span>
  <span class="kd">const</span> <span class="nx">reader</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FileReader</span><span class="p">()</span>
  <span class="kd">const</span> <span class="nx">file</span> <span class="o">=</span> <span class="nx">files</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
  <span class="c1">// 休眠等待 image2array 计算，数据流格式转化至 Uint8ClampedArray</span>
  <span class="k">await</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">res</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">res</span><span class="p">()</span> <span class="p">},</span> <span class="mi">100</span><span class="p">)</span> <span class="p">})</span>
  <span class="kd">const</span> <span class="nx">imageUrl</span> <span class="o">=</span> <span class="nx">URL</span><span class="p">.</span><span class="nx">createObjectURL</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span>
  <span class="k">try</span> <span class="p">{</span>
    <span class="nx">image2array</span><span class="p">(</span><span class="nx">imageUrl</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">info</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">err</span><span class="p">)</span> <span class="k">return</span>
      <span class="kd">const</span> <span class="p">{</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">width</span><span class="p">,</span> <span class="nx">height</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">info</span>
      <span class="kd">const</span> <span class="nx">binaryData</span> <span class="o">=</span> <span class="nx">jsQR</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="nx">width</span><span class="p">,</span> <span class="nx">height</span><span class="p">)</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">binaryData</span> <span class="o">&amp;&amp;</span> <span class="nx">binaryData</span><span class="p">.</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">link</span> <span class="o">=</span> <span class="nx">binaryData</span><span class="p">.</span><span class="nx">data</span>
        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">link</span><span class="p">)</span>
      <span class="p">}</span>
    <span class="p">})</span>
  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="链接生成二维码">链接生成二维码</h2>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">QRCode</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">qrcode</span><span class="dl">'</span>

<span class="kd">const</span> <span class="nx">link</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">https://karl-cheung.github.io</span><span class="dl">'</span>

<span class="nx">QRCode</span><span class="p">.</span><span class="nx">toDataURL</span><span class="p">(</span><span class="nx">link</span><span class="p">,</span> <span class="p">{},</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">url</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="k">return</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[二维码识别链接]]></summary></entry><entry><title type="html">DES 加密算法与三重数据加密算法（Triple DES）的简易封装</title><link href="https://karl-cheung.github.io/jekyll/update/2019/07/14/tdes.html" rel="alternate" type="text/html" title="DES 加密算法与三重数据加密算法（Triple DES）的简易封装" /><published>2019-07-14T00:00:00+00:00</published><updated>2019-07-14T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2019/07/14/tdes</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2019/07/14/tdes.html"><![CDATA[]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">ios 模拟器预览内嵌网页</title><link href="https://karl-cheung.github.io/jekyll/update/2019/02/17/ios-web-simulator.html" rel="alternate" type="text/html" title="ios 模拟器预览内嵌网页" /><published>2019-02-17T00:00:00+00:00</published><updated>2019-02-17T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2019/02/17/ios-web-simulator</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2019/02/17/ios-web-simulator.html"><![CDATA[]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">SPA 应用开启 History 模式</title><link href="https://karl-cheung.github.io/jekyll/update/2019/02/11/spa-History.html" rel="alternate" type="text/html" title="SPA 应用开启 History 模式" /><published>2019-02-11T00:00:00+00:00</published><updated>2019-02-11T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2019/02/11/spa-History</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2019/02/11/spa-History.html"><![CDATA[<h2 id="nginx">nginx</h2>

<h3 id="根目录">根目录</h3>

<blockquote>
  <p>部署在根目录的项目</p>
</blockquote>

<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">location</span> <span class="n">/</span> <span class="p">{</span>
  <span class="kn">try_files</span> <span class="nv">$uri</span> <span class="nv">$uri</span><span class="n">/</span> <span class="n">/index.html</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="子目录">子目录</h3>

<blockquote>
  <p>未部署在根目录的项目</p>
</blockquote>

<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="s">(!-e</span> <span class="nv">$request_filename</span><span class="s">)</span> <span class="p">{</span>
  <span class="kn">rewrite</span> <span class="s">^/(.*)</span> <span class="n">/index.html</span> <span class="s">last</span><span class="p">;</span>
  <span class="kn">break</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>或</p>

<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">location</span> <span class="n">/</span> <span class="p">{</span>
  <span class="kn">try_files</span> <span class="nv">$uri</span> <span class="nv">$uri</span><span class="n">/</span> <span class="s">@router</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">location</span> <span class="s">@router</span> <span class="p">{</span>
  <span class="kn">rewrite</span> <span class="s">^.*</span>$ <span class="n">/index.html</span> <span class="s">last</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="其他后端配置例子">其他后端配置例子</h2>

<p><a href="https://router.vuejs.org/zh/guide/essentials/history-mode.html">Vue Router</a></p>

<h2 id="client">client</h2>

<h3 id="vue">Vue</h3>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">router</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">VueRouter</span><span class="p">({</span>
  <span class="na">mode</span><span class="p">:</span> <span class="dl">'</span><span class="s1">history</span><span class="dl">'</span><span class="p">,</span>
<span class="p">})</span>
</code></pre></div></div>

<blockquote>
  <p>如果应用服务在 <code class="language-plaintext highlighter-rouge">/app/</code> 下（非根目录）</p>
</blockquote>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">router</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">VueRouter</span><span class="p">({</span>
  <span class="na">base</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/app/</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">mode</span><span class="p">:</span> <span class="dl">'</span><span class="s1">history</span><span class="dl">'</span><span class="p">,</span>
<span class="p">})</span>
</code></pre></div></div>

<h3 id="react">React</h3>

<p>React Router 默认开启 browserHistory</p>

<blockquote>
  <p>如果应用服务在 <code class="language-plaintext highlighter-rouge">/app/</code> 下（非根目录）</p>
</blockquote>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;</span><span class="nx">BrowserRouter</span> <span class="nx">basename</span><span class="o">=</span><span class="dl">'</span><span class="s1">/app</span><span class="dl">'</span><span class="o">&gt;&lt;</span><span class="sr">/BrowserRouter</span><span class="err">&gt;
</span></code></pre></div></div>

<h3 id="参阅">参阅</h3>

<ul>
  <li>
    <p><a href="https://router.vuejs.org/zh/guide/essentials/history-mode.html">Vue Router</a></p>
  </li>
  <li>
    <p><a href="https://reacttraining.com/react-router/web/guides/server-rendering">React Router</a></p>
  </li>
</ul>]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[nginx]]></summary></entry><entry><title type="html">Zhang Yu - 个人讲演的归档</title><link href="https://karl-cheung.github.io/jekyll/update/2018/10/21/lectures.html" rel="alternate" type="text/html" title="Zhang Yu - 个人讲演的归档" /><published>2018-10-21T00:00:00+00:00</published><updated>2018-10-21T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2018/10/21/lectures</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2018/10/21/lectures.html"><![CDATA[]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">基于 Vue CLI 3 快速生成 Vue 项目的初步封装，组装或必要的零件。开箱即用</title><link href="https://karl-cheung.github.io/jekyll/update/2018/09/02/vue-app.html" rel="alternate" type="text/html" title="基于 Vue CLI 3 快速生成 Vue 项目的初步封装，组装或必要的零件。开箱即用" /><published>2018-09-02T00:00:00+00:00</published><updated>2018-09-02T00:00:00+00:00</updated><id>https://karl-cheung.github.io/jekyll/update/2018/09/02/vue-app</id><content type="html" xml:base="https://karl-cheung.github.io/jekyll/update/2018/09/02/vue-app.html"><![CDATA[]]></content><author><name>karl-cheung</name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[]]></summary></entry></feed>