<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>网中的小鱼</title>
  
  <subtitle>wzdxy</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://blog.wzdxy.com/"/>
  <updated>2020-12-30T08:53:57.889Z</updated>
  <id>https://blog.wzdxy.com/</id>
  
  <author>
    <name>网中的小鱼</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>当你遇到一个年久失修的npm包有bug时...</title>
    <link href="https://blog.wzdxy.com/2020/12/%E5%BD%93%E4%BD%A0%E9%81%87%E5%88%B0%E4%B8%80%E4%B8%AA%E5%B9%B4%E4%B9%85%E5%A4%B1%E4%BF%AE%E7%9A%84npm%E5%8C%85%E6%9C%89bug%E6%97%B6/"/>
    <id>https://blog.wzdxy.com/2020/12/当你遇到一个年久失修的npm包有bug时/</id>
    <published>2020-12-16T21:31:10.000Z</published>
    <updated>2020-12-30T08:53:57.889Z</updated>
    
    <content type="html"><![CDATA[<p>1.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;1.&lt;/p&gt;

      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Node.js使用QConf踩坑记录(CentOS)</title>
    <link href="https://blog.wzdxy.com/2020/12/node-qconf-start/"/>
    <id>https://blog.wzdxy.com/2020/12/node-qconf-start/</id>
    <published>2020-12-07T20:53:04.000Z</published>
    <updated>2020-12-30T08:53:57.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="一、安装QConf客户端（如果服务器上已安装可以跳过此步骤）"><a href="#一、安装QConf客户端（如果服务器上已安装可以跳过此步骤）" class="headerlink" title="一、安装QConf客户端（如果服务器上已安装可以跳过此步骤）"></a>一、安装QConf客户端（如果服务器上已安装可以跳过此步骤）</h2><h3 id="1、安装CMake-（如果已安装可以跳过）"><a href="#1、安装CMake-（如果已安装可以跳过）" class="headerlink" title="1、安装CMake （如果已安装可以跳过）"></a>1、安装CMake （如果已安装可以跳过）</h3><h4 id="1-1-准备编译环境"><a href="#1-1-准备编译环境" class="headerlink" title="1.1 准备编译环境"></a>1.1 准备编译环境</h4><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">yum -y install gcc gcc-c++</span><br></pre></td></tr></table></figure><h4 id="1-2-获取源码，并解压"><a href="#1-2-获取源码，并解压" class="headerlink" title="1.2 获取源码，并解压"></a>1.2 获取源码，并解压</h4><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">wget https://github.com/Kitware/CMake/releases/download/v3.19.1/cmake-3.19.1.tar.gz</span><br><span class="line">tar -zxf cmake-3.19.1.tar.gz</span><br><span class="line"><span class="built_in">cd</span> cmake-3.19.1</span><br></pre></td></tr></table></figure><h4 id="1-3-编译安装"><a href="#1-3-编译安装" class="headerlink" title="1.3 编译安装"></a>1.3 编译安装</h4><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">./bootstrap --prefix=/usr --datadir=share/cmake --docdir=doc/cmake &amp;&amp; make</span><br><span class="line">sudo make install</span><br><span class="line">cmake --version <span class="comment"># 检查是否正确安装</span></span><br></pre></td></tr></table></figure><h2 id="2、安装-QConf"><a href="#2、安装-QConf" class="headerlink" title="2、安装 QConf"></a>2、安装 QConf</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></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> git@github.com:Qihoo360/QConf.git  (如果没有权限可以直接去 Github 主页下载 zip 包)</span><br><span class="line"><span class="built_in">cd</span> QConf/</span><br><span class="line">mkdir build &amp;&amp; <span class="built_in">cd</span> build</span><br><span class="line">cmake ..</span><br><span class="line">make</span><br><span class="line">make install</span><br></pre></td></tr></table></figure><h2 id="3、启动"><a href="#3、启动" class="headerlink" title="3、启动"></a>3、启动</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">/usr/<span class="built_in">local</span>/qconf/bin/qconf_agent</span><br></pre></td></tr></table></figure><p>结尾可能出现 <code>Failed to get conf!</code> 是一个 WARNING，可以暂时忽略，已经启动成功了。</p><h2 id="二、在-Node-js-调用"><a href="#二、在-Node-js-调用" class="headerlink" title="二、在 Node.js 调用"></a>二、在 Node.js 调用</h2><h3 id="1、在项目中安装-node-qconf"><a href="#1、在项目中安装-node-qconf" class="headerlink" title="1、在项目中安装 node-qconf"></a>1、在项目中安装 node-qconf</h3><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"><span class="built_in">export</span> QCONF_INSTALL=/home/work/<span class="built_in">local</span>/qconf</span><br></pre></td></tr></table></figure><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 install node-qconf</span><br></pre></td></tr></table></figure></p><h3 id="2、调用"><a href="#2、调用" class="headerlink" title="2、调用"></a>2、调用</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// qconf.js</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">'启动'</span>)</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">  <span class="keyword">var</span> qconf = <span class="built_in">require</span>(<span class="string">'node-qconf'</span>)</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'version:'</span>, qconf.version())</span><br><span class="line">&#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">  <span class="built_in">console</span>.error(e)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>qconf 的错误处理不太完善，又十分依赖本机环境，容易出现程序直接中断而没有报错的情况。因此需要 try catch （包括 require(‘node-conf’) 语句）</p><h2 id="三、常见问题"><a href="#三、常见问题" class="headerlink" title="三、常见问题"></a>三、常见问题</h2><p>Q：报错：<code>Error: QConf init failed: 201</code></p><p>A：大概率是因为 QConf 没有启动 （参考 <a href="https://github.com/Qihoo360/QConf/issues/22）" target="_blank" rel="noopener">https://github.com/Qihoo360/QConf/issues/22）</a></p><p>Q：npm 安装 node-qconf 报错：</p><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></pre></td><td class="code"><pre><span class="line">../qconf.cc:2:19: fatal error: qconf.h: No such file or directory</span><br><span class="line"><span class="comment">#include &lt;qconf.h&gt;</span></span><br><span class="line">^</span><br><span class="line">compilation terminated.</span><br></pre></td></tr></table></figure><p>A：安装 node-qconf 前，需确保 QConf 已经被正确安装，并配置了 QCONF_INSTALL 环境变量</p><p>Q：<code>require(&#39;node-qconf&#39;)</code> 报错：</p><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></pre></td><td class="code"><pre><span class="line">Error: libqconf.so: cannot open shared object file: No such file or directory</span><br><span class="line">at Object.Module._extensions..node (internal/modules/cjs/loader.js:731:18)</span><br><span class="line">at Module.load (internal/modules/cjs/loader.js:612:32)</span><br><span class="line">at tryModuleLoad (internal/modules/cjs/loader.js:551:12)</span><br><span class="line">at Function.Module._load (internal/modules/cjs/loader.js:543:3)</span><br><span class="line">at Module.require (internal/modules/cjs/loader.js:650:17)</span><br><span class="line">at require (internal/modules/cjs/helpers.js:20:18)</span><br><span class="line">at Object.&lt;anonymous&gt; (/home/wwwroot/acs-platform-server/node_modules/node-qconf/qconf.js:1:80)</span><br><span class="line">at Module._compile (internal/modules/cjs/loader.js:702:30)</span><br><span class="line">at Object.Module._extensions..js (internal/modules/cjs/loader.js:713:10)</span><br><span class="line">at Module.load (internal/modules/cjs/loader.js:612:32)</span><br></pre></td></tr></table></figure><p>A：找不到<code>libqconf.so</code>文件，需要在/usr/lib或/usr/lib64下创建libqconf的软连接</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">sudo ln -s /usr/<span class="built_in">local</span>/qconf/lib/libqconf.so /usr/lib64/libqconf.so</span><br></pre></td></tr></table></figure><p>参考链接：</p><p><a href="https://github.com/Qihoo360/QConf" target="_blank" rel="noopener">https://github.com/Qihoo360/QConf</a></p><p><a href="https://github.com/Qihoo360/QConf/blob/master/doc/Qconf%20Node%20Doc.md" target="_blank" rel="noopener">https://github.com/Qihoo360/QConf/blob/master/doc/Qconf%20Node%20Doc.md</a></p><p><a href="https://github.com/bluedapp/node-qconf" target="_blank" rel="noopener">https://github.com/bluedapp/node-qconf</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;一、安装QConf客户端（如果服务器上已安装可以跳过此步骤）&quot;&gt;&lt;a href=&quot;#一、安装QConf客户端（如果服务器上已安装可以跳过此步骤）&quot; class=&quot;headerlink&quot; title=&quot;一、安装QConf客户端（如果服务器上已安装可以跳过此步骤）&quot;&gt;
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>微信小程序多人协作工作流程</title>
    <link href="https://blog.wzdxy.com/2020/12/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%A4%9A%E4%BA%BA%E5%8D%8F%E4%BD%9C%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B/"/>
    <id>https://blog.wzdxy.com/2020/12/微信小程序多人协作工作流程/</id>
    <published>2020-12-05T18:48:38.000Z</published>
    <updated>2020-12-30T08:53:57.889Z</updated>
    
    <summary type="html">
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Typescript在开发中的体验提升</title>
    <link href="https://blog.wzdxy.com/2020/11/typescript-efficient/"/>
    <id>https://blog.wzdxy.com/2020/11/typescript-efficient/</id>
    <published>2020-11-06T11:06:01.000Z</published>
    <updated>2020-12-30T08:53:57.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="1-标记参数和返回值，方便维护"><a href="#1-标记参数和返回值，方便维护" class="headerlink" title="1. 标记参数和返回值，方便维护"></a>1. 标记参数和返回值，方便维护</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// login</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">checkUserLogin</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> configData = <span class="keyword">this</span>.getUserConfig()</span><br><span class="line">  <span class="keyword">if</span> (configData.username) &#123;</span><br><span class="line"></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">// user-config.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getUserConfig</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// do something and return userConfig</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> UserConfig &#123;</span><br><span class="line">  username: <span class="built_in">String</span></span><br><span class="line">  uid: <span class="built_in">Number</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">checkUserLogin</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> userConfig:UserConfig = <span class="keyword">this</span>.getUserConfig()</span><br><span class="line">  <span class="built_in">console</span>.log(configData.name)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// user-config.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getUserConfig</span>:<span class="title">UserConfig</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// do something and return userConfig</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="2-代码补全"><a href="#2-代码补全" class="headerlink" title="2. 代码补全"></a>2. 代码补全</h1><h2 id="声明文件-d-ts"><a href="#声明文件-d-ts" class="headerlink" title="声明文件 d.ts"></a>声明文件 d.ts</h2><p>其实我们一直在用 ts</p><h3 id="VSCode-对-d-ts-的支持"><a href="#VSCode-对-d-ts-的支持" class="headerlink" title="VSCode 对 d.ts 的支持"></a>VSCode 对 d.ts 的支持</h3><p><code>Automatic Type Acquisition</code> 功能，会将自动下载社区中流行的 @types</p><h3 id="Webstorm-对-d-ts-的支持"><a href="#Webstorm-对-d-ts-的支持" class="headerlink" title="Webstorm 对 d.ts 的支持"></a>Webstorm 对 d.ts 的支持</h3><p>自动</p><p>对于自己的库，可以编写自己的 d.ts，发布到 <code>@types/</code> 下</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><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">// @types/xxx/index.d.ts</span></span><br><span class="line"><span class="keyword">declare</span> <span class="keyword">namespace</span> $ACS &#123;</span><br><span class="line">  <span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 工具方法</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">  <span class="keyword">export</span> <span class="keyword">const</span> utils: &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">      * 是否处于微信小程序</span></span><br><span class="line"><span class="comment">      */</span></span><br><span class="line">    isMini(): <span class="built_in">Boolean</span></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">      * 当前是否处于APP内</span></span><br><span class="line"><span class="comment">      */</span></span><br><span class="line">    isApp(): <span class="built_in">Boolean</span></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取当前所在的联调、测试、本地、线上、预发布等环境及域名信息</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    getEnv(): &#123;</span><br><span class="line">      env: <span class="string">'local-dev'</span>|<span class="string">'online'</span>|<span class="string">'pre'</span>|<span class="string">'test'</span></span><br><span class="line">      mHost: <span class="built_in">String</span></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><img src="https://static.wzdxy.com/img/20201206002435.png" alt=""></p><p><img src="https://static.wzdxy.com/img/20201206212158.png" alt=""></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;1-标记参数和返回值，方便维护&quot;&gt;&lt;a href=&quot;#1-标记参数和返回值，方便维护&quot; class=&quot;headerlink&quot; title=&quot;1. 标记参数和返回值，方便维护&quot;&gt;&lt;/a&gt;1. 标记参数和返回值，方便维护&lt;/h2&gt;&lt;figure class=&quot;high
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>uniapp微信小程序自动页面埋点和曝光埋点踩坑</title>
    <link href="https://blog.wzdxy.com/2020/10/uniapp-st/"/>
    <id>https://blog.wzdxy.com/2020/10/uniapp-st/</id>
    <published>2020-10-26T11:17:58.000Z</published>
    <updated>2020-12-30T08:53:57.881Z</updated>
    
    <content type="html"><![CDATA[<h2 id="基本功能介绍"><a href="#基本功能介绍" class="headerlink" title="基本功能介绍"></a>基本功能介绍</h2><h3 id="页面埋点"><a href="#页面埋点" class="headerlink" title="页面埋点"></a>页面埋点</h3><p>在页面的 onShow 勾子函数中上传埋点数据</p><h3 id="曝光埋点"><a href="#曝光埋点" class="headerlink" title="曝光埋点"></a>曝光埋点</h3><p>利用小程序提供的 <code>createIntersectionObserver</code>  API, 监听元素露出屏幕的事件，并触发回调（参数为元素的相关信息），由业务组件在回调中自己上传埋点数据。</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">Exposure</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(selector, callback, vm, options) &#123;</span><br><span class="line">    <span class="keyword">this</span>.callback = callback</span><br><span class="line">    <span class="keyword">this</span>.selector = selector</span><br><span class="line">    <span class="keyword">this</span>.lockTimer = <span class="literal">null</span></span><br><span class="line">    <span class="keyword">if</span> (options) &#123;</span><br><span class="line">      <span class="keyword">this</span>.bottom = options.bottom || <span class="number">0</span></span><br><span class="line">      <span class="keyword">this</span>.top = options.top || <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">this</span>.init(vm) <span class="comment">// 为什么把vm传来传去而不用this.vm：因为会出现循环引用导致报错</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="comment"> * 初始化</span></span><br><span class="line"><span class="comment"> * @param vm 组件的 $vm 实例 (vue 实例)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  init(vm) &#123;</span><br><span class="line">    <span class="comment">// 创建 IntersectionObserver 的实例</span></span><br><span class="line">    <span class="keyword">this</span>.ob = vm</span><br><span class="line">      ? vm.createIntersectionObserver(&#123; <span class="attr">observeAll</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">      : uni.createIntersectionObserver(<span class="literal">null</span>, &#123; <span class="attr">observeAll</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">    <span class="comment">// 开始监听，当露出时触发回调</span></span><br><span class="line">    <span class="keyword">this</span>.ob</span><br><span class="line">      .relativeToViewport(&#123;</span><br><span class="line">        bottom: <span class="keyword">this</span>.bottom,</span><br><span class="line">        top: <span class="keyword">this</span>.top</span><br><span class="line">      &#125;)</span><br><span class="line">      .observe(<span class="keyword">this</span>.selector, (result) =&gt; &#123;</span><br><span class="line">        <span class="keyword">if</span> (result.intersectionRatio &gt; <span class="number">0</span>) &#123;</span><br><span class="line">          <span class="keyword">this</span>.callback(result)</span><br><span class="line">        &#125;</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><h3 id="由于业务需求，页面埋点和曝光埋点还需要有以下逻辑"><a href="#由于业务需求，页面埋点和曝光埋点还需要有以下逻辑" class="headerlink" title="由于业务需求，页面埋点和曝光埋点还需要有以下逻辑"></a>由于业务需求，页面埋点和曝光埋点还需要有以下逻辑</h3><h4 id="1-进入页面时（用户未操作），立即触发页面埋点和曝光埋点"><a href="#1-进入页面时（用户未操作），立即触发页面埋点和曝光埋点" class="headerlink" title="1. 进入页面时（用户未操作），立即触发页面埋点和曝光埋点"></a>1. 进入页面时（用户未操作），立即触发<strong>页面埋点</strong>和<strong>曝光埋点</strong></h4><h4 id="2-跳到其他页面再返回时，需要再次触发页面埋点和当前在屏幕露出的元素的埋点"><a href="#2-跳到其他页面再返回时，需要再次触发页面埋点和当前在屏幕露出的元素的埋点" class="headerlink" title="2. 跳到其他页面再返回时，需要再次触发页面埋点和当前在屏幕露出的元素的埋点"></a>2. 跳到其他页面再返回时，需要再次触发<strong>页面埋点</strong>和<strong>当前在屏幕露出的元素的埋点</strong></h4><p>页面埋点很容易处理，而曝光埋点很麻烦，因为 <code>IntersectionObserver</code> 只能监听元素可见性变化，无法静态获取是否露出元素，因此需要在每个页面监听 <code>onHide</code> 和 <code>onShow</code> 事件，在 <code>onHide</code> 时销毁所有监听实例，在 <code>onShow</code> 时重新监听（因为 <code>IntersectionObserver</code> 创建时会默认触发一次事件，即可达到重新触发曝光的目的）<br>但如果这些逻辑放在业务代码中，非常繁琐且重复，因此使用全局 mixin 处理。</p><h2 id="二、-全局-mixin"><a href="#二、-全局-mixin" class="headerlink" title="二、 全局 mixin"></a>二、 全局 mixin</h2><ul><li><p>页面埋点</p><p>每次 onShow 时都触发一次页面埋点</p></li><li><p>曝光埋点</p><p>首次 onShow 时初始化曝光埋点（初始化不在此控制，因为加载时机不同，所以放在在业务逻辑中）并将曝光埋点实例存在 exposureObservers 中以备后用；同时标记 isPageFirstLoad 为 false</p><p>每次 onHide 时销毁所有曝光埋点</p><p>下次 onShow 时，遍历并调用 <code>exposureObservers</code> 中的所有实例的 <code>reInit</code> 方法</p></li></ul><p><strong>Mixin代码</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">import</span> &#123; reportData &#125; <span class="keyword">from</span> <span class="string">'@/common/report-data'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 曝光埋点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> pageAndExposureObservers = &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      exposureObservers: [], <span class="comment">// 用于存储曝光埋点</span></span><br><span class="line">      isPageFirstLoad: <span class="literal">true</span> <span class="comment">// 标记页面是否第一次加载</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  onShow() &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(</span><br><span class="line">      <span class="keyword">this</span>.route,</span><br><span class="line">      <span class="string">'=====================onShow 前========================'</span></span><br><span class="line">    )</span><br><span class="line">    <span class="built_in">console</span>.log(</span><br><span class="line">      <span class="keyword">this</span>.route,</span><br><span class="line">      <span class="string">'=====================onShow 后========================'</span></span><br><span class="line">    )</span><br><span class="line">    <span class="comment">// 1. 首次和之后每次显示页面。发送页面埋点（从页面组件的 pageTrackConfig 中读取数据）</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="keyword">this</span>.pageTrackConfig === <span class="string">'undefined'</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> pageTrackConfig = <span class="keyword">this</span>.$options.pageTrackConfig</span><br><span class="line">      <span class="keyword">let</span> dataForReport</span><br><span class="line">      <span class="keyword">if</span> (<span class="keyword">typeof</span> pageTrackConfig === <span class="string">'function'</span>) &#123;</span><br><span class="line">        dataForReport = &#123; <span class="attr">type</span>: <span class="number">3</span>, ...pageTrackConfig.call(<span class="keyword">this</span>) &#125;</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> pageTrackConfig === <span class="string">'object'</span> &amp;&amp; pageTrackConfig.info) &#123;</span><br><span class="line">        dataForReport = &#123; <span class="attr">type</span>: <span class="number">3</span>, ...pageTrackConfig &#125;</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> pageTrackConfig === <span class="string">'string'</span>) &#123;</span><br><span class="line">        dataForReport = &#123; <span class="attr">type</span>: <span class="number">3</span>, <span class="attr">info</span>: pageTrackConfig &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      dataForReport &amp;&amp; reportData(dataForReport)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 2.如果是从其他页面切换，重新初始化曝光埋点</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="keyword">this</span>.isPageFirstLoad) &#123;</span><br><span class="line">      <span class="keyword">this</span>.exposureObservers.forEach(<span class="function">(<span class="params">item</span>) =&gt;</span> item.reInit(<span class="keyword">this</span>))</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">this</span>.isPageFirstLoad = <span class="literal">false</span></span><br><span class="line">  &#125;,</span><br><span class="line">  onHide() &#123;</span><br><span class="line">    <span class="comment">// 2.页面隐藏时，销毁所有曝光</span></span><br><span class="line">    <span class="keyword">this</span>.exposureObservers.forEach(<span class="function">(<span class="params">item</span>) =&gt;</span> item.disconnect(<span class="keyword">this</span>))</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>Exposure修改为：</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">Exposure</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(selector, callback, vm, options) &#123;</span><br><span class="line">    <span class="keyword">this</span>.callback = callback</span><br><span class="line">    <span class="keyword">this</span>.selector = selector</span><br><span class="line">    <span class="keyword">this</span>.lockTimer = <span class="literal">null</span></span><br><span class="line">    <span class="keyword">if</span> (options) &#123;</span><br><span class="line">      <span class="keyword">this</span>.bottom = options.bottom || <span class="number">0</span></span><br><span class="line">      <span class="keyword">this</span>.top = options.top || <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">this</span>.init(vm) <span class="comment">// 为什么把vm传来传去而不用this.vm：因为会出现循环引用导致报错</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="comment"> * 初始化</span></span><br><span class="line"><span class="comment"> * @param vm 组件的 $vm 实例 (vue 实例)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  init(vm) &#123;</span><br><span class="line">    <span class="comment">// 创建 IntersectionObserver 的实例</span></span><br><span class="line">    <span class="keyword">this</span>.ob = vm</span><br><span class="line">      ? vm.createIntersectionObserver(&#123; <span class="attr">observeAll</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">      : uni.createIntersectionObserver(<span class="literal">null</span>, &#123; <span class="attr">observeAll</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">    <span class="comment">// 切断循环引用，防止报错</span></span><br><span class="line">    <span class="keyword">this</span>.ob._component = <span class="literal">null</span></span><br><span class="line">    <span class="comment">// 开始监听，当露出时触发回调</span></span><br><span class="line">    <span class="built_in">console</span>.log(&#123; <span class="attr">bottom</span>: <span class="keyword">this</span>.bottom, <span class="attr">top</span>: <span class="keyword">this</span>.top &#125;)</span><br><span class="line">    <span class="keyword">this</span>.ob</span><br><span class="line">      .relativeToViewport(&#123;</span><br><span class="line">        bottom: <span class="keyword">this</span>.bottom,</span><br><span class="line">        top: <span class="keyword">this</span>.top</span><br><span class="line">      &#125;)</span><br><span class="line">      .observe(<span class="keyword">this</span>.selector, (result) =&gt; &#123;</span><br><span class="line">        <span class="keyword">if</span> (result.intersectionRatio &gt; <span class="number">0</span>) &#123;</span><br><span class="line">          <span class="keyword">this</span>.callback(result)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">    <span class="comment">// push 到当前页面组件的 exposureObservers 数组中</span></span><br><span class="line">    <span class="keyword">this</span>.getRootPageComponent(vm).exposureObservers.push(<span class="keyword">this</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="comment"> * 销毁所有监听</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  disconnect(vm) &#123;</span><br><span class="line">    <span class="keyword">this</span>.ob.disconnect()</span><br><span class="line">    <span class="keyword">const</span> rootPageComponent = <span class="keyword">this</span>.getRootPageComponent(vm)</span><br><span class="line">    <span class="keyword">const</span> index = rootPageComponent.exposureObservers.indexOf(<span class="keyword">this</span>)</span><br><span class="line">    <span class="keyword">if</span> (index) &#123;</span><br><span class="line">      rootPageComponent.exposureObservers.splice(index, <span class="number">1</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">/**</span></span><br><span class="line"><span class="comment"> * 重新监听所有曝光埋点</span></span><br><span class="line"><span class="comment"> * @param vm</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  reInit(vm) &#123;</span><br><span class="line">    <span class="keyword">this</span>.disconnect(vm)</span><br><span class="line">    <span class="keyword">this</span>.init(vm)</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="comment"> * 获取组件所属的最上层组件(页面组件)</span></span><br><span class="line"><span class="comment"> * @param vm</span></span><br><span class="line"><span class="comment"> * @returns &#123;*&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  getRootPageComponent(vm) &#123;</span><br><span class="line">    <span class="keyword">if</span> (vm.mpType === <span class="string">'component'</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">this</span>.getRootPageComponent(vm.$parent)</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (vm.mpType === <span class="string">'page'</span> || vm.$parent === <span class="literal">undefined</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> vm</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> vm</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><h2 id="三、坑：iOS微信bug导致页面和曝光不准"><a href="#三、坑：iOS微信bug导致页面和曝光不准" class="headerlink" title="三、坑：iOS微信bug导致页面和曝光不准"></a>三、坑：iOS微信bug导致页面和曝光不准</h2><h3 id="1-问题描述"><a href="#1-问题描述" class="headerlink" title="1. 问题描述"></a>1. 问题描述</h3><p>iOS版本微信存在一个问题：从一个非TabBar页面A切换到TabBar页面B时，如果TabBar当前不处于目标页面B，会先短暂展示一下当前TabBar所在页面C，然后再切换到B。</p><p>结果就是页面C的 <code>onShow</code> 和 <code>onHide</code> 被执行，导致多发送一次页面和一批曝光事件。</p><p>除此之外，当二次复现此路径时，还会额外多触发一次B埋点，也就是发送2次B埋点。</p><p>相关链接<br><a href="">https://developers.weixin.qq.com/community/develop/doc/000ea812d54ab0cfea3a23eaf51400</a></p><h3 id="2-解决方案"><a href="#2-解决方案" class="headerlink" title="2. 解决方案"></a>2. 解决方案</h3><h4 id="过滤页面埋点"><a href="#过滤页面埋点" class="headerlink" title="过滤页面埋点"></a>过滤页面埋点</h4><p>在调用 <code>switchTab</code> 前，记录全局变量 <code>isSwitchingTab</code>（表示当前正在切换TAB）<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">Vue.prototype.isSwitchingTab = <span class="string">'pages/shopping-cart'</span></span><br></pre></td></tr></table></figure></p><p>在全局 mixin 的 onShow 方法中，判断这个变量，如果当前页面路由和 <code>isSwitchingTab</code> 的值相同，才认为当前是真正想跳转的页面，而不是由于 bug 短暂展示的页面。这样就过滤掉了本就不应该触发的C页面的 onShow。<br>同时，在进入B页面 onShow 后，延迟2s清除 isSwitchingTab ，防止影响下次跳转。</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="keyword">if</span> (</span><br><span class="line">  Vue.prototype.isSwitchingTab === <span class="literal">undefined</span> ||</span><br><span class="line">  <span class="keyword">this</span>[<span class="string">'__route__'</span>] === Vue.prototype.isSwitchingTab</span><br><span class="line">) &#123;</span><br><span class="line">  setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> (Vue.prototype.isSwitchingTab = <span class="literal">undefined</span>), <span class="number">2000</span>)</span><br><span class="line">  <span class="comment">// 下面继续埋点逻辑</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>此处还有一个点需要注意：在使用 <code>getCurrentPages()</code> 获取的页面栈中，并不包含C页面，只能在 <code>this[__route__]</code> 中读取当前页面的 route 属性。这说明<strong>对于微信小程序来说，C页面的意外展示是不被承认的</strong>，毕竟它连一个痕迹都木有留下。</p><h4 id="过滤重复发送的B埋点"><a href="#过滤重复发送的B埋点" class="headerlink" title="过滤重复发送的B埋点"></a>过滤重复发送的B埋点</h4><p>在发送埋点时，判断当前页面是否刚刚发送埋点，如果2s内有发送过，就不再发送</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 class="comment">// 防止重复曝光</span></span><br><span class="line"><span class="keyword">if</span> (</span><br><span class="line">  dataForReport &amp;&amp;</span><br><span class="line">  Vue.prototype.CurrentPageForMaidian !== dataForReport.info</span><br><span class="line">) &#123;</span><br><span class="line">  dataForReport &amp;&amp; reportData(dataForReport)</span><br><span class="line">  Vue.prototype.CurrentPageForMaidian = dataForReport.info</span><br><span class="line">  setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    Vue.prototype.CurrentPageForMaidian = <span class="literal">undefined</span></span><br><span class="line">  &#125;, <span class="number">2000</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="四、最终代码"><a href="#四、最终代码" class="headerlink" title="四、最终代码"></a>四、最终代码</h2><p><strong>Mixin代码</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; reportData &#125; <span class="keyword">from</span> <span class="string">'@/common/report-data'</span></span><br><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">'vue'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 曝光埋点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> pageAndExposureObservers = &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      exposureObservers: [], <span class="comment">// 用于存储曝光埋点</span></span><br><span class="line">      isPageFirstLoad: <span class="literal">true</span> <span class="comment">// 标记页面是否第一次加载</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  onShow() &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(</span><br><span class="line">      <span class="string">'当前页面栈'</span>,</span><br><span class="line">      getCurrentPages()</span><br><span class="line">        .map(<span class="function">(<span class="params">i</span>) =&gt;</span> i.route)</span><br><span class="line">        .join(<span class="string">' ====&gt; '</span>)</span><br><span class="line">    )</span><br><span class="line">    <span class="keyword">const</span> currentPages = getCurrentPages()</span><br><span class="line">    <span class="keyword">const</span> currentPage = currentPages[currentPages.length - <span class="number">1</span>]</span><br><span class="line">    <span class="keyword">const</span> currentRoute = currentPage ? currentPage.route : <span class="literal">false</span></span><br><span class="line">    <span class="built_in">console</span>.log(currentRoute, <span class="string">'===========onShow=========='</span>)</span><br><span class="line">    <span class="keyword">if</span> (</span><br><span class="line">      Vue.prototype.isSwitchingTab === <span class="literal">undefined</span> ||</span><br><span class="line"><span class="keyword">this</span>[<span class="string">'__route__'</span>] === Vue.prototype.isSwitchingTab</span><br><span class="line">    ) &#123;</span><br><span class="line">      <span class="comment">// 为了处理 ios switch tab 的bug，记录当前正在切换的页面</span></span><br><span class="line">      setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> (Vue.prototype.isSwitchingTab = <span class="literal">undefined</span>), <span class="number">2000</span>)</span><br><span class="line">      <span class="comment">// 1. 首次和之后每次显示页面。发送页面埋点（从页面组件的 pageTrackConfig 中读取数据）</span></span><br><span class="line">      <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="keyword">this</span>.pageTrackConfig === <span class="string">'undefined'</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> pageTrackConfig = <span class="keyword">this</span>.$options.pageTrackConfig</span><br><span class="line">        <span class="keyword">let</span> dataForReport</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">typeof</span> pageTrackConfig === <span class="string">'function'</span>) &#123;</span><br><span class="line">          dataForReport = &#123; <span class="attr">type</span>: <span class="number">3</span>, ...pageTrackConfig.call(<span class="keyword">this</span>) &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (</span><br><span class="line">          <span class="keyword">typeof</span> pageTrackConfig === <span class="string">'object'</span> &amp;&amp;</span><br><span class="line">pageTrackConfig.info</span><br><span class="line">        ) &#123;</span><br><span class="line">          dataForReport = &#123; <span class="attr">type</span>: <span class="number">3</span>, ...pageTrackConfig &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> pageTrackConfig === <span class="string">'string'</span>) &#123;</span><br><span class="line">          dataForReport = &#123; <span class="attr">type</span>: <span class="number">3</span>, <span class="attr">info</span>: pageTrackConfig &#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">if</span> (</span><br><span class="line">          dataForReport &amp;&amp;</span><br><span class="line">Vue.prototype.CurrentPageForMaidian !== dataForReport.info</span><br><span class="line">        ) &#123;</span><br><span class="line">          dataForReport &amp;&amp; reportData(dataForReport)</span><br><span class="line">          Vue.prototype.CurrentPageForMaidian = dataForReport.info</span><br><span class="line">          setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">            Vue.prototype.CurrentPageForMaidian = <span class="literal">undefined</span></span><br><span class="line">          &#125;, <span class="number">2000</span>)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// 2.如果是从其他页面切换，重新初始化曝光埋点</span></span><br><span class="line">      <span class="keyword">if</span> (!<span class="keyword">this</span>.isPageFirstLoad) &#123;</span><br><span class="line">        <span class="keyword">this</span>.exposureObservers.forEach(<span class="function">(<span class="params">item</span>) =&gt;</span> item.reInit(<span class="keyword">this</span>))</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'reInit this.exposureObservers'</span>, <span class="keyword">this</span>.exposureObservers)</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">this</span>.isPageFirstLoad = <span class="literal">false</span></span><br><span class="line">  &#125;,</span><br><span class="line">  onHide() &#123;</span><br><span class="line">    <span class="comment">// 2.页面隐藏时，销毁所有曝光</span></span><br><span class="line">    <span class="keyword">this</span>.exposureObservers.forEach(<span class="function">(<span class="params">item</span>) =&gt;</span> item.disconnect(<span class="keyword">this</span>))</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>Exposure</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">Exposure</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(selector, callback, vm, options) &#123;</span><br><span class="line">    <span class="keyword">this</span>.callback = callback</span><br><span class="line">    <span class="keyword">this</span>.selector = selector</span><br><span class="line">    <span class="keyword">this</span>.lockTimer = <span class="literal">null</span></span><br><span class="line">    <span class="keyword">if</span> (options) &#123;</span><br><span class="line">      <span class="keyword">this</span>.bottom = options.bottom || <span class="number">0</span></span><br><span class="line">      <span class="keyword">this</span>.top = options.top || <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">this</span>.init(vm) <span class="comment">// 为什么把vm传来传去而不用this.vm：因为会出现循环引用导致报错</span></span><br><span class="line">    <span class="keyword">this</span>.getRootPageComponent(vm).exposureObservers.push(<span class="keyword">this</span>) <span class="comment">// push 到当前页面组件的 pageAndExposureObservers 数组中</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="comment"> * 初始化</span></span><br><span class="line"><span class="comment"> * @param vm 组件的 $vm 实例 (vue 实例)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  init(vm) &#123;</span><br><span class="line">    <span class="comment">// 创建 IntersectionObserver 的实例</span></span><br><span class="line">    <span class="keyword">this</span>.ob = vm</span><br><span class="line">      ? vm.createIntersectionObserver(&#123; <span class="attr">observeAll</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">      : uni.createIntersectionObserver(<span class="literal">null</span>, &#123; <span class="attr">observeAll</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">    <span class="comment">// 开始监听，当露出时触发回调</span></span><br><span class="line">    <span class="comment">// 开始监听，当露出时触发回调</span></span><br><span class="line">    <span class="keyword">this</span>.ob</span><br><span class="line">      .relativeToViewport(&#123;</span><br><span class="line">        bottom: <span class="keyword">this</span>.bottom,</span><br><span class="line">        top: <span class="keyword">this</span>.top</span><br><span class="line">      &#125;)</span><br><span class="line">      .observe(<span class="keyword">this</span>.selector, (result) =&gt; &#123;</span><br><span class="line">        <span class="keyword">if</span> (result.intersectionRatio &gt; <span class="number">0</span>) &#123;</span><br><span class="line">          <span class="keyword">this</span>.callback(result)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">    <span class="comment">// 切断循环引用，防止报错（此语句必须放在.observe之后，否则会找不到组件内的元素）</span></span><br><span class="line">    <span class="keyword">this</span>.ob._component = <span class="literal">null</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="comment"> * 销毁所有监听</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  disconnect() &#123;</span><br><span class="line">    <span class="keyword">this</span>.ob.disconnect()</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="comment"> * 重新监听所有曝光埋点</span></span><br><span class="line"><span class="comment"> * @param vm</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  reInit(vm) &#123;</span><br><span class="line">    <span class="keyword">this</span>.init(vm)</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="comment"> * 获取组件所属的最上层组件(页面组件)</span></span><br><span class="line"><span class="comment"> * @param vm</span></span><br><span class="line"><span class="comment"> * @returns &#123;*&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">  getRootPageComponent(vm) &#123;</span><br><span class="line">    <span class="keyword">if</span> (vm.mpType === <span class="string">'component'</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">this</span>.getRootPageComponent(vm.$parent)</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (vm.mpType === <span class="string">'page'</span> || vm.$parent === <span class="literal">undefined</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> vm</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> vm</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><h2 id="五、调用方法"><a href="#五、调用方法" class="headerlink" title="五、调用方法"></a>五、调用方法</h2><h3 id="页面埋点-1"><a href="#页面埋点-1" class="headerlink" title="页面埋点"></a>页面埋点</h3><p>在页面组件中定义 <code>pageTrackConfig</code> 属性即可，无需额外处理<br>支持 <code>String</code> 和 <code>Function</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="comment">// string</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  pageTrackConfig: <span class="string">'hnav_home_page'</span>,</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// function，返回复杂的埋点信息</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  pageTrackConfig() &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123; <span class="attr">info</span>: <span class="string">'plist_product_detail_page'</span>, <span class="attr">ext</span>: &#123; <span class="attr">product_id</span>: <span class="keyword">this</span>.pid &#125;&#125;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="曝光埋点-1"><a href="#曝光埋点-1" 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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 参数：选择器（支持多个），曝光回调，当前组件实例（即this）</span></span><br><span class="line"><span class="comment">// 可以在回调参数中读取 dom 的 dataset 等属性</span></span><br><span class="line"><span class="keyword">this</span>.$registerExposure(</span><br><span class="line">  <span class="string">'.tofu .leaf-node'</span>,</span><br><span class="line">  (result) =&gt; &#123;</span><br><span class="line">    <span class="comment">// 在回调中发送埋点，可以通过 result 的 id和 dataset 获取信息，dataset就是DOM上的 data-xx=xx</span></span><br><span class="line">    <span class="keyword">this</span>.$reportData(&#123;</span><br><span class="line">      info: <span class="string">'hnav_homepage_tofu_exposure'</span>,</span><br><span class="line">      ext: &#123;</span><br><span class="line">        serial_num: result.dataset.num</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">this</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 支持传递触发阈值，如被吸底的价格条遮挡的情况：</span></span><br><span class="line"><span class="keyword">this</span>.$registerExposure(</span><br><span class="line">  <span class="string">'.section.rights'</span>,</span><br><span class="line">  () =&gt; &#123;</span><br><span class="line">    <span class="keyword">this</span>.$reportData(&#123; <span class="attr">info</span>: <span class="string">'plist_productdetail_policy_exposure'</span> &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="keyword">this</span>,</span><br><span class="line">  &#123; <span class="attr">bottom</span>: <span class="number">-60</span> &#125;</span><br><span class="line">)</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;页
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>VSCode中的油猴--powertools插件试用</title>
    <link href="https://blog.wzdxy.com/2020/09/powertools-start/"/>
    <id>https://blog.wzdxy.com/2020/09/powertools-start/</id>
    <published>2020-09-09T09:43:38.000Z</published>
    <updated>2020-12-30T08:53:57.881Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>Power Tools 是一个 VSCode 插件, 可以让用户随时编写自己的脚本, 并能很方便地在 VSCode 中运行, 而且支持 VSCode 扩展的 API.<br>下面来使用 Power Tools 实现一个半自动 px 转 rpx 的快捷功能.</p><h2 id="使用条件"><a href="#使用条件" class="headerlink" title="使用条件"></a>使用条件</h2><ul><li>VSCode</li><li>Power Tools 插件</li></ul><h2 id="一、-安装"><a href="#一、-安装" class="headerlink" title="一、 安装"></a>一、 安装</h2><p>直接从 <a href="https://marketplace.visualstudio.com/items?itemName=ego-digital.vscode-powertools" target="_blank" rel="noopener">ego-digital.vscode-powertools</a> 安装<br>或在VSCode中搜索<br><img src="https://static.wzdxy.com//img/Code_VCt9E3tfVC.png" alt=""></p><a id="more"></a><h2 id="二、-配置"><a href="#二、-配置" class="headerlink" title="二、 配置"></a>二、 配置</h2><h3 id="F1启动命令窗口，-输入-settings-搜索，-选择-settings（JSON）"><a href="#F1启动命令窗口，-输入-settings-搜索，-选择-settings（JSON）" class="headerlink" title="F1启动命令窗口， 输入 settings 搜索， 选择 settings（JSON）"></a>F1启动命令窗口， 输入 settings 搜索， 选择 settings（JSON）</h3><p><img src="https://static.wzdxy.com/img/M8MeV2WaSw.png" alt=""></p><h3 id="在底部添加配置-创建一个名为-px2rpx-的命令，-并指向-px2rpx-js-文件"><a href="#在底部添加配置-创建一个名为-px2rpx-的命令，-并指向-px2rpx-js-文件" class="headerlink" title="在底部添加配置, 创建一个名为 px2rpx 的命令， 并指向 px2rpx.js 文件"></a>在底部添加配置, 创建一个名为 <code>px2rpx</code> 的命令， 并指向 <code>px2rpx.js</code> 文件</h3><figure class="highlight"><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">"ego.power-tools": &#123;</span><br><span class="line">      "commands": &#123;</span><br><span class="line">          "px2rpx": &#123;</span><br><span class="line">              "script": "px2rpx.js",</span><br><span class="line">              "button": &#123;</span><br><span class="line">                  "text": "Click here to start the command."</span><br><span class="line">              &#125;,</span><br><span class="line"></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><img src="https://static.wzdxy.com/img/Code_h8RO4tBXrJ.png" alt=""></p><h3 id="在项目目录下的-vscode-文件夹下创建-px2rpx-js-文件-内容如下"><a href="#在项目目录下的-vscode-文件夹下创建-px2rpx-js-文件-内容如下" class="headerlink" title="在项目目录下的 .vscode 文件夹下创建 px2rpx.js 文件, 内容如下:"></a>在项目目录下的 .vscode 文件夹下创建 <code>px2rpx.js</code> 文件, 内容如下:</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></pre></td><td class="code"><pre><span class="line">exports.execute = <span class="keyword">async</span> (args) =&gt; &#123;</span><br><span class="line">  <span class="comment">// args =&gt; https://egodigital.github.io/vscode-powertools/api/interfaces/_contracts_.buttonactionscriptarguments.html</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// s. https://code.visualstudio.com/api/references/vscode-api</span></span><br><span class="line">  <span class="keyword">const</span> vscode = args.require(<span class="string">'vscode'</span>);</span><br><span class="line">  <span class="keyword">const</span> activeTextEditor = vscode.window.activeTextEditor;</span><br><span class="line">  <span class="keyword">const</span> selection = activeTextEditor.selection</span><br><span class="line">  <span class="keyword">const</span> oldText = activeTextEditor.document.getText(selection)</span><br><span class="line">  <span class="keyword">const</span> r = <span class="regexp">/^(\d+)px$/</span>.exec(oldText)</span><br><span class="line">  <span class="keyword">if</span> (r!==<span class="literal">null</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> newText = r[<span class="number">1</span>] * <span class="number">2</span> + <span class="string">'rpx'</span></span><br><span class="line">    activeTextEditor.edit(<span class="function"><span class="params">builder</span> =&gt;</span> &#123;</span><br><span class="line">      builder.replace(selection, newText);</span><br><span class="line">    &#125;)</span><br><span class="line">    vscode.window.showInformationMessage(<span class="string">`<span class="subst">$&#123;oldText&#125;</span> =&gt; <span class="subst">$&#123;newText&#125;</span>`</span>)</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    vscode.window.showInformationMessage(<span class="string">`没有选中PX值`</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p><img src="https://static.wzdxy.com/img/CwL4GYcTIr.png" alt=""></p><h2 id="三、试用"><a href="#三、试用" class="headerlink" title="三、试用"></a>三、试用</h2><p>配置完成后, 在 VSCode 左下角会出现一个按钮, 选中代码中的 <code>12px</code>, 点击按钮, <code>12px</code> 就会被替换成 <code>24rpx</code> 了.<br><img src="https://static.wzdxy.com/img/vUvwZNo4dq.png" alt=""></p><h2 id="四、配置快捷键"><a href="#四、配置快捷键" class="headerlink" title="四、配置快捷键"></a>四、配置快捷键</h2><p>点击鼠标很不方便, 我们可以为这段脚本配置一个快捷键.<br>在 <code>File-Preference-Keyborad Shorcuts</code> 中, 搜索 <code>px2rpx</code>, 双击设置一个快捷键, 我设置为了 <code>Ctrl + Alt + Shift + A</code>.<br>现在就可以流畅快速的操作了, 只需要<code>双击鼠标-按快捷键-双击鼠标-按快捷键</code>.</p><p><img src="https://static.wzdxy.com/img/px2rpx.gif" alt=""></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;p&gt;Power Tools 是一个 VSCode 插件, 可以让用户随时编写自己的脚本, 并能很方便地在 VSCode 中运行, 而且支持 VSCode 扩展的 API.&lt;br&gt;下面来使用 Power Tools 实现一个半自动 px 转 rpx 的快捷功能.&lt;/p&gt;
&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;ul&gt;
&lt;li&gt;VSCode&lt;/li&gt;
&lt;li&gt;Power Tools 插件&lt;/li&gt;
&lt;/ul&gt;
&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;p&gt;直接从 &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ego-digital.vscode-powertools&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ego-digital.vscode-powertools&lt;/a&gt; 安装&lt;br&gt;或在VSCode中搜索&lt;br&gt;&lt;img src=&quot;https://static.wzdxy.com//img/Code_VCt9E3tfVC.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>使用AST实现自动配置WebPack接口代理</title>
    <link href="https://blog.wzdxy.com/2020/07/ast-auto-proxy/"/>
    <id>https://blog.wzdxy.com/2020/07/ast-auto-proxy/</id>
    <published>2020-07-24T23:27:28.000Z</published>
    <updated>2020-12-30T08:53:57.881Z</updated>
    
    <content type="html"><![CDATA[<h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>在开发物料平台的过程中, 为了提升物料开发的效率, 对 api 接口做了约定, 将物料用到的接口都配置到同一个 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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> mApi = &#123;</span><br><span class="line">  getList: <span class="function">(<span class="params">params</span>) =&gt;</span> axios.get(<span class="string">"/api/get-list"</span>, params),</span><br><span class="line">  setItem: <span class="function">(<span class="params">params</span>) =&gt;</span></span><br><span class="line">    axios(&#123;</span><br><span class="line">      method: <span class="string">"post"</span>,</span><br><span class="line">      url: <span class="string">"/api/set-item"</span>,</span><br><span class="line">    &#125;),</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">const</span> adminApi = &#123;</span><br><span class="line">  getList: <span class="function">(<span class="params">params</span>) =&gt;</span> axios.get(<span class="string">"/admin-api/get-list"</span>, params),</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">export</span> &#123; mApi, adminApi &#125;;</span><br></pre></td></tr></table></figure><p>为了减少操作, 打算根据这个文件自动配置代理.</p><a id="more"></a><p>一个搭建平台一般有后台(一般放在公司的管理系统域名下)和 M 站两部分, 所以这两部分接口需要分别指向不同的域名.</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><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="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="string">"/api/get-list"</span>: &#123;</span><br><span class="line">    target: mHost,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"/api/set-item"</span>: &#123;</span><br><span class="line">    target: mHost,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"/admin/get-list"</span>: &#123;</span><br><span class="line">    target: adminHost,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>首先想到的方法是正则提取, 但大家在代码里如何配置路由和参数不太可控, 可能出现提取错误, 也不容易判断哪个接口所属那个 api 下.</p><p>因此采用 AST 解析的方式, 更准确也更优雅的提取, 也对物料开发有更少的限制.</p><h2 id="依赖的工具"><a href="#依赖的工具" class="headerlink" title="依赖的工具"></a>依赖的工具</h2><p>babel 是一个前端工程中很常用的工具, 其作用就是用将使用未来新语法的代码解析成 AST (Abstract Syntax Tree 抽象语法树), 然后转换成已经被浏览器兼容的语法, 再将其生成代码.</p><p>而 babel 是由多个工具组成的, 本次实现这个功能用到了以下工具:</p><ul><li>parser (AST 解析器)</li><li>generator (代码生成器)</li><li>traverse (转换器)</li><li>types AST (节点类型)</li></ul><h2 id="解析"><a href="#解析" class="headerlink" title="解析"></a>解析</h2><p>将代码解析成 AST 树, 很简单:</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 class="keyword">const</span> parser = <span class="built_in">require</span>(<span class="string">"@babel/parser"</span>);</span><br><span class="line"><span class="keyword">const</span> codeString = fs.readFileSync(apiFilePath, <span class="string">"utf-8"</span>);</span><br><span class="line"><span class="keyword">const</span> ast = parser.parse(codeString, &#123;</span><br><span class="line">  ecmaVersion: <span class="number">2020</span>,</span><br><span class="line">  sourceType: <span class="string">"module"</span>,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>遍历 AST, 找到配置 ajax 请求 url 的地方, 将存储到对应的数组中</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> traverse = <span class="built_in">require</span>(<span class="string">"@babel/traverse"</span>).default;</span><br><span class="line"><span class="keyword">let</span> parentChain = []; <span class="comment">// 在深度优先遍历中记录所有祖先node</span></span><br><span class="line"><span class="keyword">let</span> mApiList = []; <span class="comment">// 存储 mApi 的 URL 地址</span></span><br><span class="line"><span class="keyword">let</span> adminApiList = []; <span class="comment">// 存储 adminApi 的 URL 地址</span></span><br><span class="line"><span class="keyword">let</span> unkownApiList = [];</span><br><span class="line"><span class="comment">// 遍历提取</span></span><br><span class="line">traverse(ast, &#123;</span><br><span class="line">  enter: <span class="function"><span class="keyword">function</span> (<span class="params">path</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; node, parent &#125; = path;</span><br><span class="line">    parentChain.push(node);</span><br><span class="line">    <span class="comment">// 适用于 ajax.get('xx') ajax.post('xx')</span></span><br><span class="line">    <span class="keyword">if</span> (node.type === <span class="string">"StringLiteral"</span> &amp;&amp; parent.type === <span class="string">"CallExpression"</span>) &#123;</span><br><span class="line">      getApiObjectName(parentChain).push(node.value);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 适用于 ajax(&#123;url: 'xx'&#125;) 写法</span></span><br><span class="line">    <span class="keyword">if</span> (node.type === <span class="string">"ObjectProperty"</span> &amp;&amp; node.key.name === <span class="string">"url"</span>) &#123;</span><br><span class="line">      getApiObjectName(parentChain).push(node.value.value);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  exit: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    parentChain.pop();</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 判断祖先是属于 mApi 还是 adminApi</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getApiObjectName</span>(<span class="params">parentChain</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (</span><br><span class="line">    parentChain.some(</span><br><span class="line">      (ancestorNode) =&gt;</span><br><span class="line">        ancestorNode.type === <span class="string">"VariableDeclarator"</span> &amp;&amp;</span><br><span class="line">        ancestorNode.id.name === <span class="string">"mApi"</span></span><br><span class="line">    )</span><br><span class="line">  ) &#123;</span><br><span class="line">    <span class="keyword">return</span> mApiList;</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (</span><br><span class="line">    parentChain.some(</span><br><span class="line">      (ancestorNode) =&gt;</span><br><span class="line">        ancestorNode.type === <span class="string">"VariableDeclarator"</span> &amp;&amp;</span><br><span class="line">        ancestorNode.id.name === <span class="string">"adminApi"</span></span><br><span class="line">    )</span><br><span class="line">  ) &#123;</span><br><span class="line">    <span class="keyword">return</span> adminApiList;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> unkownApiList;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里存在一个问题. <code>@babel/traverse</code> 的 enter 方法提供的回调参数里只能拿到 当前 node 和 parent node, 因此无法直接得知它属于哪个 api 对象.</p><p>为了做出判断, 维护一个 <code>parentChain</code> 栈, 记录深度优先遍历过程中的所有父级节点, 在判断时就可以根据这个栈找到它的祖先节点.</p><h2 id="创建代码"><a href="#创建代码" class="headerlink" title="创建代码"></a>创建代码</h2><p>拿到 <code>mApiList</code> 和 <code>adminApiList</code> 数组后, 就可以生成配置了.</p><p>这一步拼接字符串也可以实现, 但为了更好的理解 AST, 就遍历数组再次创建一个 AST, 使用 <code>@babel/generator</code> 生成 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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> generator = <span class="built_in">require</span>(<span class="string">"@babel/generator"</span>).default;</span><br><span class="line"><span class="comment">// 根据配置列表依次生成代理列表的 ast node</span></span><br><span class="line"><span class="keyword">const</span> code = generator(</span><br><span class="line">  t.program([</span><br><span class="line">    <span class="comment">// 导入全局配置(定义代理域名的js)</span></span><br><span class="line">    t.variableDeclaration(<span class="string">"const"</span>, [</span><br><span class="line">      t.variableDeclarator(</span><br><span class="line">        t.objectPattern([</span><br><span class="line">          t.objectProperty(</span><br><span class="line">            t.identifier(<span class="string">"mHost"</span>),</span><br><span class="line">            t.identifier(<span class="string">"mHost"</span>),</span><br><span class="line">            <span class="literal">false</span>,</span><br><span class="line">            <span class="literal">true</span></span><br><span class="line">          ),</span><br><span class="line">          t.objectProperty(</span><br><span class="line">            t.identifier(<span class="string">"adminHost"</span>),</span><br><span class="line">            t.identifier(<span class="string">"adminHost"</span>),</span><br><span class="line">            <span class="literal">false</span>,</span><br><span class="line">            <span class="literal">true</span></span><br><span class="line">          ),</span><br><span class="line">        ]),</span><br><span class="line">        t.callExpression(t.identifier(<span class="string">"require"</span>), [</span><br><span class="line">          t.stringLiteral(<span class="string">"./dev-host"</span>),</span><br><span class="line">        ])</span><br><span class="line">      ),</span><br><span class="line">    ]),</span><br><span class="line">    <span class="comment">// 导出生成的代理列表</span></span><br><span class="line">    t.expressionStatement(</span><br><span class="line">      t.assignmentExpression(</span><br><span class="line">        <span class="string">"="</span>,</span><br><span class="line">        t.memberExpression(t.identifier(<span class="string">"module"</span>), t.identifier(<span class="string">"exports"</span>)),</span><br><span class="line">        t.objectExpression([</span><br><span class="line">          t.objectProperty(</span><br><span class="line">            t.identifier(<span class="string">"proxy"</span>),</span><br><span class="line">            t.objectExpression(</span><br><span class="line">              list.map(<span class="function">(<span class="params">item</span>) =&gt;</span> createAstNodeOfProxyItem(...item))</span><br><span class="line">            )</span><br><span class="line">          ),</span><br><span class="line">        ])</span><br><span class="line">      )</span><br><span class="line">    ),</span><br><span class="line">  ]),</span><br><span class="line">  &#123;</span><br><span class="line">    jsescOption: &#123; <span class="attr">quotes</span>: <span class="string">"single"</span> &#125;, <span class="comment">// generate options</span></span><br><span class="line">  &#125;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建每一个代理配置的 ast node</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createAstNodeOfProxyItem</span>(<span class="params">api, target, cookie</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> t.objectProperty(</span><br><span class="line">    t.stringLiteral(api),</span><br><span class="line">    t.objectExpression([</span><br><span class="line">      t.objectProperty(t.identifier(<span class="string">"target"</span>), t.identifier(target)),</span><br><span class="line">    ])</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line">fs.writeFileSync(</span><br><span class="line">  path.resolve(config.localRepoPath, <span class="string">"proxy-list-auto.js"</span>),</span><br><span class="line">  proxyListResultCode,</span><br><span class="line">  <span class="string">"utf-8"</span></span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>这样就得到了一个 export 开头提到的代理配置列表 js 文件, 将其导入到 webpack 的 proxy 配置即可.</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;p&gt;在开发物料平台的过程中, 为了提升物料开发的效率, 对 api 接口做了约定, 将物料用到的接口都配置到同一个 js 文件内.按照变量名划分.&lt;/p&gt;
&lt;figure class=&quot;highlight js&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; mApi = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  getList: &lt;span class=&quot;function&quot;&gt;(&lt;span class=&quot;params&quot;&gt;params&lt;/span&gt;) =&amp;gt;&lt;/span&gt; axios.get(&lt;span class=&quot;string&quot;&gt;&quot;/api/get-list&quot;&lt;/span&gt;, params),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  setItem: &lt;span class=&quot;function&quot;&gt;(&lt;span class=&quot;params&quot;&gt;params&lt;/span&gt;) =&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    axios(&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      method: &lt;span class=&quot;string&quot;&gt;&quot;post&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      url: &lt;span class=&quot;string&quot;&gt;&quot;/api/set-item&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; adminApi = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  getList: &lt;span class=&quot;function&quot;&gt;(&lt;span class=&quot;params&quot;&gt;params&lt;/span&gt;) =&amp;gt;&lt;/span&gt; axios.get(&lt;span class=&quot;string&quot;&gt;&quot;/admin-api/get-list&quot;&lt;/span&gt;, params),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;export&lt;/span&gt; &amp;#123; mApi, adminApi &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;为了减少操作, 打算根据这个文件自动配置代理.&lt;/p&gt;
    
    </summary>
    
    
      <category term="前端" scheme="https://blog.wzdxy.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
      <category term="Javascript" scheme="https://blog.wzdxy.com/tags/Javascript/"/>
    
      <category term="AST" scheme="https://blog.wzdxy.com/tags/AST/"/>
    
  </entry>
  
  <entry>
    <title>Typescript入坑指南</title>
    <link href="https://blog.wzdxy.com/2019/12/ts-start/"/>
    <id>https://blog.wzdxy.com/2019/12/ts-start/</id>
    <published>2019-12-22T00:03:06.000Z</published>
    <updated>2020-12-30T08:53:57.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="用命令行编译-ts-文件"><a href="#用命令行编译-ts-文件" class="headerlink" title="用命令行编译 ts 文件"></a>用命令行编译 ts 文件</h2><figure class="highlight shell"><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="meta">#</span><span class="bash"> 安装</span></span><br><span class="line">npm i typescript -g</span><br><span class="line"><span class="meta">#</span><span class="bash"> 编译</span></span><br><span class="line">tsc hello.ts</span><br></pre></td></tr></table></figure><h2 id="在-VSCode-中直接调试-TS-文件"><a href="#在-VSCode-中直接调试-TS-文件" class="headerlink" title="在 VSCode 中直接调试 TS 文件"></a>在 VSCode 中直接调试 TS 文件</h2><a id="more"></a><h3 id="1-在根目录创建-tsconfig-json"><a href="#1-在根目录创建-tsconfig-json" class="headerlink" title="1. 在根目录创建 tsconfig.json"></a>1. 在根目录创建 <code>tsconfig.json</code></h3><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><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"compilerOptions"</span>: &#123;</span><br><span class="line">    <span class="attr">"target"</span>: <span class="string">"es5"</span>,</span><br><span class="line">    <span class="attr">"module"</span>: <span class="string">"commonjs"</span>,</span><br><span class="line">    <span class="attr">"outDir"</span>: <span class="string">"out"</span>,</span><br><span class="line">    <span class="attr">"sourceMap"</span>: <span class="literal">true</span> // 用于断点调试</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2-在-VSCode-的命令窗格-Ctrl-Command-Shift-P-中执行-Run-Task-tsc-watch-tsconfig-json"><a href="#2-在-VSCode-的命令窗格-Ctrl-Command-Shift-P-中执行-Run-Task-tsc-watch-tsconfig-json" class="headerlink" title="2. 在 VSCode 的命令窗格(Ctrl/Command + Shift + P)中执行 Run Task - tsc:watch - tsconfig.json"></a>2. 在 VSCode 的命令窗格(Ctrl/Command + Shift + P)中执行 <code>Run Task</code> - <code>tsc:watch - tsconfig.json</code></h3><p>这个操作将会启动一条任务, 功能是监听 ts 文件变化, 并实时按照 <code>tsconfig.json</code> 的配置编译成 js 文件</p><h3 id="3-创建一个调试配置-launch-json"><a href="#3-创建一个调试配置-launch-json" class="headerlink" title="3. 创建一个调试配置 launch.json"></a>3. 创建一个调试配置 <code>launch.json</code></h3><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><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">&#123;</span><br><span class="line">  <span class="attr">"version"</span>: <span class="string">"0.2.0"</span>,</span><br><span class="line">  <span class="attr">"configurations"</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">"type"</span>: <span class="string">"node"</span>,</span><br><span class="line">      <span class="attr">"request"</span>: <span class="string">"launch"</span>,</span><br><span class="line">      <span class="attr">"name"</span>: <span class="string">"Launch Program"</span>,</span><br><span class="line">      <span class="attr">"program"</span>: <span class="string">"$&#123;file&#125;"</span>,</span><br><span class="line">      <span class="attr">"outFiles"</span>: [</span><br><span class="line">        <span class="string">"$&#123;workspaceFolder&#125;/out/**/*.js"</span></span><br><span class="line">      ]</span><br><span class="line">    &#125;</span><br><span class="line">  ]</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><p>切到要调试的 ts 文件, 按下F5即可运行当前文件, 支持打断点调试</p><p>因为 Task 已经实时做了编译, 也不需要每次写完 ts 再用 tsc 手动编译了</p><p>一键即可快速运行</p><p><img src="https://static.wzdxy.com/img/20191222001544.png" alt=""></p>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;用命令行编译-ts-文件&quot;&gt;&lt;a href=&quot;#用命令行编译-ts-文件&quot; class=&quot;headerlink&quot; title=&quot;用命令行编译 ts 文件&quot;&gt;&lt;/a&gt;用命令行编译 ts 文件&lt;/h2&gt;&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; 安装&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;npm i typescript -g&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; 编译&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;tsc hello.ts&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h2 id=&quot;在-VSCode-中直接调试-TS-文件&quot;&gt;&lt;a href=&quot;#在-VSCode-中直接调试-TS-文件&quot; class=&quot;headerlink&quot; title=&quot;在 VSCode 中直接调试 TS 文件&quot;&gt;&lt;/a&gt;在 VSCode 中直接调试 TS 文件&lt;/h2&gt;
    
    </summary>
    
    
      <category term="Javascript" scheme="https://blog.wzdxy.com/tags/Javascript/"/>
    
      <category term="Typescript" scheme="https://blog.wzdxy.com/tags/Typescript/"/>
    
  </entry>
  
  <entry>
    <title>electron踩坑记录之一:开发环境搭建</title>
    <link href="https://blog.wzdxy.com/2019/12/electron-start-1/"/>
    <id>https://blog.wzdxy.com/2019/12/electron-start-1/</id>
    <published>2019-12-16T21:05:44.000Z</published>
    <updated>2020-12-30T08:53:57.869Z</updated>
    
    <content type="html"><![CDATA[<h2 id="环境要求"><a href="#环境要求" class="headerlink" title="环境要求"></a>环境要求</h2><ul><li>Node.js</li><li>VSCode (建议)</li></ul><h2 id="新建项目-安装依赖"><a href="#新建项目-安装依赖" class="headerlink" title="新建项目, 安装依赖"></a>新建项目, 安装依赖</h2><figure class="highlight shell"><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">npm init # 在空文件夹中初始化项目</span><br><span class="line">npm i electron -D # 安装 electron 依赖, 注意需要安装为 devDependencies</span><br></pre></td></tr></table></figure><a id="more"></a><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; app, BrowserWindow &#125; = <span class="built_in">require</span>(<span class="string">'electron'</span>)</span><br><span class="line"><span class="keyword">let</span> win</span><br><span class="line">app.on(<span class="string">'ready'</span>, () =&gt; &#123;</span><br><span class="line">  <span class="comment">// 创建一个新窗口</span></span><br><span class="line">  win = <span class="keyword">new</span> BrowserWindow(&#123;</span><br><span class="line">    webPreferences: &#123;</span><br><span class="line">      nodeIntegration: <span class="literal">true</span> <span class="comment">// 在这个窗口(渲染进程)中启用Node</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">  win.loadFile(<span class="string">'index.html'</span>) <span class="comment">// 加载一个 html</span></span><br><span class="line">&#125;)</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></pre></td><td class="code"><pre><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> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line"></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>Document<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><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">p</span>&gt;</span>Hello Electron<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">pre</span>&gt;</span><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">const</span> fs = <span class="built_in">require</span>(<span class="string">'fs'</span>)</span></span><br><span class="line"><span class="javascript">    <span class="built_in">document</span>.write(fs.readFileSync(<span class="string">'package.json'</span>))</span></span><br><span class="line"><span class="undefined">  </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span><span class="tag">&lt;/<span class="name">pre</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><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>项目结构</li></ul><p><img src="https://static.wzdxy.com/img/20191216222720.png" alt=""></p><h2 id="运行项目"><a href="#运行项目" class="headerlink" title="运行项目"></a>运行项目</h2><ul><li>编辑 <code>package.json</code>, 添加一条 <code>script</code><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"start": "electron .",</span><br></pre></td></tr></table></figure></li></ul><p><img src="https://static.wzdxy.com/img/20191216225351.png" alt=""></p><h2 id="调试代码"><a href="#调试代码" class="headerlink" title="调试代码"></a>调试代码</h2><h3 id="调试主进程-main-js"><a href="#调试主进程-main-js" class="headerlink" title="调试主进程(main.js)"></a>调试主进程(main.js)</h3><ul><li>使用VSCode调试, 创建以下配置文件, 按F5即可在编辑器中打断点调试<br><img src="https://static.wzdxy.com/img/20191216232113.png" alt=""><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><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">&#123;</span><br><span class="line">  <span class="attr">"version"</span>: <span class="string">"0.2.0"</span>,</span><br><span class="line">  <span class="attr">"configurations"</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">"name"</span>: <span class="string">"Debug Main Process"</span>,</span><br><span class="line">      <span class="attr">"type"</span>: <span class="string">"node"</span>,</span><br><span class="line">      <span class="attr">"request"</span>: <span class="string">"launch"</span>,</span><br><span class="line">      <span class="attr">"cwd"</span>: <span class="string">"$&#123;workspaceFolder&#125;"</span>,</span><br><span class="line">      <span class="attr">"runtimeExecutable"</span>: <span class="string">"$&#123;workspaceFolder&#125;/node_modules/.bin/electron"</span>,</span><br><span class="line">      <span class="attr">"windows"</span>: &#123;</span><br><span class="line">        <span class="attr">"runtimeExecutable"</span>: <span class="string">"$&#123;workspaceFolder&#125;/node_modules/.bin/electron.cmd"</span></span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">"args"</span> : [<span class="string">"."</span>],</span><br><span class="line">      <span class="attr">"outputCapture"</span>: <span class="string">"std"</span></span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><h3 id="调试渲染进程"><a href="#调试渲染进程" class="headerlink" title="调试渲染进程"></a>调试渲染进程</h3><ul><li><strong>调试普通页面</strong>: 在窗口中按快捷键 <code>Ctrl/Command + Shift + I</code> 启动 Chrome Dev Tools, 即可像在Chrome中一样调试</li><li><strong>使用框架的Devtools调试Vue/React</strong>: Electron支持加载常用前端框架的调试扩展, 如 <a href="https://github.com/vuejs/vue-devtools" target="_blank" rel="noopener">vue-devtools</a>, 可以按照<a href="https://electronjs.org/docs/tutorial/devtools-extension" target="_blank" rel="noopener">官网提供的方法</a>加载, (要求电脑上的 Chrome 安装这个扩展)</li></ul>]]></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;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;VSCode (建议)&lt;/li&gt;
&lt;/ul&gt;
&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;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;npm init # 在空文件夹中初始化项目&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;npm i electron -D # 安装 electron 依赖, 注意需要安装为 devDependencies&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="electron" scheme="https://blog.wzdxy.com/tags/electron/"/>
    
      <category term="node" scheme="https://blog.wzdxy.com/tags/node/"/>
    
  </entry>
  
  <entry>
    <title>Flutter Alignment 属性总结和应用(雪碧图)</title>
    <link href="https://blog.wzdxy.com/2019/09/flutter-alignment/"/>
    <id>https://blog.wzdxy.com/2019/09/flutter-alignment/</id>
    <published>2019-09-28T22:44:42.000Z</published>
    <updated>2020-12-30T08:53:57.873Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Flutter-Alignment-属性总结和应用-雪碧图"><a href="#Flutter-Alignment-属性总结和应用-雪碧图" class="headerlink" title="Flutter Alignment 属性总结和应用(雪碧图)"></a>Flutter Alignment 属性总结和应用(雪碧图)</h1><h2 id="一-需求分析"><a href="#一-需求分析" class="headerlink" title="一. 需求分析"></a>一. 需求分析</h2><p>实现一个等级标识组件</p><p><img src="https://static.wzdxy.com/img/20200318000032.png" alt="20200318000032.png"></p><p>提供的图片是一张水平方向的雪碧图<br><img src="https://static.wzdxy.com/img/20200318000113.png" alt="20200318000113.png"></p><h2 id="二-Alignment-属性"><a href="#二-Alignment-属性" class="headerlink" title="二. Alignment 属性"></a>二. Alignment 属性</h2><p>这个属性可以让图片的显示位置偏移, 功能类似 css 中的 background-position<br><strong>调用: Alignment(x, y) , x y 分别表示水平和垂直方向的偏移 , 初始值均为 0</strong><br><strong>-1 表示图片最左侧 , 1表示图片最右侧</strong><br><strong>虽然实际上容器是不动的 , 偏移的是图片, 但为了便于理解, 可以认为图片静止, 容器是一个移动的选区 , 确定位置后”抠”出图来显示到界面, 如下图 (虚线框代表容器) :</strong><br><a id="more"></a><br><img src="https://static.wzdxy.com/img/20200318000124.png" alt="20200318000124.png"></p><p><a href="https://api.flutter.dev/flutter/painting/Alignment-class.html" target="_blank" rel="noopener">官方文档</a></p><h3 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h3><p><img src="https://static.wzdxy.com/img/20200318000140.png" alt="20200318000140.png"><br><strong>先用这张规则的图片做一些尝试</strong><br>首先设定图片的宽高<br><figure class="highlight dart"><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="built_in">String</span> imageUrl = <span class="string">'https://static.soyoung.com/sy-pre/2-1569589803824.png'</span>;</span><br><span class="line"><span class="built_in">double</span> width = <span class="number">400</span>;</span><br><span class="line"><span class="built_in">double</span> height = <span class="number">40</span>;</span><br></pre></td></tr></table></figure></p><p>配置 Container 的 decoration 属性 , 用 BoxDecoration 和 DecorationImage 组件实现.<br>如下代码, 会将图片完全渲染<br><figure class="highlight dart"><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">Container(</span><br><span class="line">  width: width,</span><br><span class="line">  height: height,</span><br><span class="line">  decoration: <span class="keyword">new</span> BoxDecoration(</span><br><span class="line">    image: DecorationImage(</span><br><span class="line">      image: NetworkImage(imageUrl),</span><br><span class="line">      fit: BoxFit.fitHeight,</span><br><span class="line">      alignment: Alignment(<span class="number">0</span>, <span class="number">0</span>),</span><br><span class="line">  )),</span><br></pre></td></tr></table></figure></p><p><img src="https://static.wzdxy.com/img/20200318000158.png" alt="20200318000158.png"></p><p><strong>控制宽度</strong><br><figure class="highlight dart"><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">Container(</span><br><span class="line">  width: width * <span class="number">0.2</span>, <span class="comment">// 修改容器宽度即可</span></span><br><span class="line">  height: height,</span><br><span class="line">  decoration: <span class="keyword">new</span> BoxDecoration(</span><br><span class="line">    image: DecorationImage(</span><br><span class="line">      image: NetworkImage(imageUrl),</span><br><span class="line">      fit: BoxFit.fitHeight,</span><br><span class="line">      alignment: Alignment(<span class="number">0</span>, <span class="number">0</span>)),</span><br><span class="line">  )),</span><br></pre></td></tr></table></figure></p><p><img src="https://static.wzdxy.com/img/20200318000211.png" alt="20200318000211.png"></p><figure class="highlight dart"><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">Container(</span><br><span class="line">  width: width * <span class="number">0.1</span>, <span class="comment">// 同上, 再次修改容器宽度</span></span><br><span class="line">  height: height,</span><br><span class="line">  decoration: <span class="keyword">new</span> BoxDecoration(</span><br><span class="line">    image: DecorationImage(</span><br><span class="line">      image: NetworkImage(imageUrl),</span><br><span class="line">      fit: BoxFit.fitHeight,</span><br><span class="line">      alignment: Alignment(<span class="number">0</span>, <span class="number">0</span>)),</span><br><span class="line">  )),</span><br></pre></td></tr></table></figure><p><img src="https://static.wzdxy.com/img/20200318000223.png" alt="20200318000223.png"></p><p><strong>增加简单的偏移</strong><br><figure class="highlight dart"><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">Container(</span><br><span class="line">  width: width * <span class="number">0.1</span>,</span><br><span class="line">  height: height,</span><br><span class="line">  decoration: <span class="keyword">new</span> BoxDecoration(</span><br><span class="line">    image: DecorationImage(</span><br><span class="line">      image: NetworkImage(imageUrl),</span><br><span class="line">      fit: BoxFit.fitHeight,</span><br><span class="line">      alignment: Alignment(<span class="number">-1</span>, <span class="number">0</span>)), <span class="comment">// (1, 0) 即可仅显示10</span></span><br><span class="line">  )),</span><br></pre></td></tr></table></figure></p><p><img src="https://static.wzdxy.com/img/20200318000236.png" alt="20200318000236.png"><br><img src="https://static.wzdxy.com/img/20200318000241.png" alt="20200318000241.png"></p><p>以上是简单的偏移,  这仅能控制左右对齐 , 想偏移到更多的位置, 就需要增加一点计算:<br><strong>显示5和6的位置</strong><br><figure class="highlight dart"><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="comment">// 5</span></span><br><span class="line">Container(</span><br><span class="line">  width: width * <span class="number">0.1</span>,</span><br><span class="line">  height: height,</span><br><span class="line">  decoration: <span class="keyword">new</span> BoxDecoration(</span><br><span class="line">    image: DecorationImage(</span><br><span class="line">      image: NetworkImage(imageUrl),</span><br><span class="line">      fit: BoxFit.fitHeight,</span><br><span class="line">      alignment:</span><br><span class="line">      Alignment( <span class="number">0.05</span>/<span class="number">0.45</span>, <span class="number">0</span>)),</span><br><span class="line">  )),</span><br><span class="line"><span class="comment">// 6</span></span><br><span class="line">Container(</span><br><span class="line">  width: width * <span class="number">0.1</span>,</span><br><span class="line">  height: height,</span><br><span class="line">  decoration: <span class="keyword">new</span> BoxDecoration(</span><br><span class="line">    image: DecorationImage(</span><br><span class="line">      image: NetworkImage(imageUrl),</span><br><span class="line">      fit: BoxFit.fitHeight,</span><br><span class="line">      alignment:</span><br><span class="line">      Alignment(<span class="number">-0.05</span>/<span class="number">0.45</span>, <span class="number">0</span>)),</span><br><span class="line">  )),</span><br></pre></td></tr></table></figure></p><p><img src="https://static.wzdxy.com/img/20200318000252.png" alt="20200318000252.png"><br><img src="https://static.wzdxy.com/img/20200318000258.png" alt="20200318000258.png"></p><p>此时传给 Alignment  的 x 值 , 是十分诡异的 ±0.05/0.45 ≈ ±0.111111<br>为什么这样算呢? x 值的获取可以总结为一个公式:<br><strong>x = d1/d2</strong><br>d1 = <strong>初始状态</strong>时<strong>图片左边界</strong>到<strong>容器左边界</strong>的距离<br>d2 = <strong>目标状态</strong>时图片的偏移量<br>初始状态 (未偏移时, 选框居中) 如下图 , d1 = width * 0.45<br><img src="https://static.wzdxy.com/img/20200318000308.png" alt="20200318000308.png"></p><p>目标状态 , 选框 (相对上图中的选框) 从中心往左移动了半个格, 则 d2 = width * -0.05</p><p><img src="https://static.wzdxy.com/img/20200318000316.png" alt="20200318000316.png"></p><p>同理 , 若要展示2 , d2 为 width * -0.35 , x = -0.35/0.45 ≈ -0.777777777777778<br><img src="https://static.wzdxy.com/img/20200318000321.png" alt="20200318000321.png"></p><p>同理,  若要展示8,  d2 为 width * 0.25 , x = 0.25/0.45 ≈  0.555555555555556<br><img src="https://static.wzdxy.com/img/20200318000328.png" alt="20200318000328.png"></p><h3 id="三-实际应用"><a href="#三-实际应用" class="headerlink" title="三. 实际应用"></a>三. 实际应用</h3><p>回到等级标识的问题 , 现在可以封装一个方法计算每个 level 的偏移量<br><figure class="highlight dart"><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 class="comment">// 考虑到不同等级的图片宽度是不同的, 还需要提供每个等级图片的宽度</span></span><br><span class="line"><span class="built_in">List</span>&lt;<span class="built_in">double</span>&gt; itemWidthList = [<span class="number">60</span>, <span class="number">60</span>, <span class="number">60</span>, <span class="number">60</span>, <span class="number">60</span>, <span class="number">60</span>, <span class="number">62</span>, <span class="number">62</span>, <span class="number">62</span>, <span class="number">62</span>, <span class="number">66</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>, <span class="number">70</span>]; <span class="comment">// 横向雪碧图中每个小图的宽度</span></span><br><span class="line"><span class="built_in">Map</span> getLevelStyle(<span class="built_in">int</span> level) &#123;</span><br><span class="line">    <span class="built_in">double</span> totalWidth = <span class="number">0</span>; <span class="comment">// 图片总宽度</span></span><br><span class="line">    <span class="built_in">double</span> positionX = <span class="number">0</span>; <span class="comment">// 图片左边的位置</span></span><br><span class="line">    <span class="built_in">double</span> width; <span class="comment">// 当前等级图片的宽度</span></span><br><span class="line">    <span class="built_in">int</span> i;</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; itemWidthList.length; i++) &#123;</span><br><span class="line">      <span class="keyword">if</span> (i &lt; level) positionX += itemWidthList[i];</span><br><span class="line">      <span class="keyword">if</span> (i == level) width = itemWidthList[i];</span><br><span class="line">      totalWidth += itemWidthList[i];</span><br><span class="line">    &#125;</span><br><span class="line">  <span class="comment">// 初始状态(图片和容器中心点重合) 图片左边界到容器左边界的距离, 即 d2</span></span><br><span class="line">    <span class="built_in">double</span> zeroPosition = totalWidth/<span class="number">2</span> - width / <span class="number">2</span>;</span><br><span class="line">  <span class="comment">// 目标状态时, 图片的偏移量, 即 d1</span></span><br><span class="line">    <span class="built_in">double</span> distanceToCenter = positionX - zeroPosition;</span><br><span class="line">  <span class="comment">// x = d1/d2</span></span><br><span class="line">    <span class="built_in">double</span> alignmentX = (distanceToCenter / zeroPosition);</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'level $level, $positionX, $distanceToCenter, $alignmentX, $totalWidth'</span>);</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="string">"x"</span>: alignmentX,</span><br><span class="line">      <span class="string">"width"</span>: width</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure></p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;Flutter-Alignment-属性总结和应用-雪碧图&quot;&gt;&lt;a href=&quot;#Flutter-Alignment-属性总结和应用-雪碧图&quot; class=&quot;headerlink&quot; title=&quot;Flutter Alignment 属性总结和应用(雪碧图)&quot;&gt;&lt;/a&gt;Flutter Alignment 属性总结和应用(雪碧图)&lt;/h1&gt;&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;p&gt;实现一个等级标识组件&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.wzdxy.com/img/20200318000032.png&quot; alt=&quot;20200318000032.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;提供的图片是一张水平方向的雪碧图&lt;br&gt;&lt;img src=&quot;https://static.wzdxy.com/img/20200318000113.png&quot; alt=&quot;20200318000113.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;二-Alignment-属性&quot;&gt;&lt;a href=&quot;#二-Alignment-属性&quot; class=&quot;headerlink&quot; title=&quot;二. Alignment 属性&quot;&gt;&lt;/a&gt;二. Alignment 属性&lt;/h2&gt;&lt;p&gt;这个属性可以让图片的显示位置偏移, 功能类似 css 中的 background-position&lt;br&gt;&lt;strong&gt;调用: Alignment(x, y) , x y 分别表示水平和垂直方向的偏移 , 初始值均为 0&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;-1 表示图片最左侧 , 1表示图片最右侧&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;虽然实际上容器是不动的 , 偏移的是图片, 但为了便于理解, 可以认为图片静止, 容器是一个移动的选区 , 确定位置后”抠”出图来显示到界面, 如下图 (虚线框代表容器) :&lt;/strong&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Flutter" scheme="https://blog.wzdxy.com/tags/Flutter/"/>
    
  </entry>
  
  <entry>
    <title>mac虚拟机中git clone(ssh)报错</title>
    <link href="https://blog.wzdxy.com/2019/07/mac%E8%99%9A%E6%8B%9F%E6%9C%BA%E4%B8%ADgit-clone-ssh-%E6%8A%A5%E9%94%99/"/>
    <id>https://blog.wzdxy.com/2019/07/mac虚拟机中git-clone-ssh-报错/</id>
    <published>2019-07-21T21:08:26.000Z</published>
    <updated>2020-12-30T08:53:57.873Z</updated>
    
    <content type="html"><![CDATA[<p>在 windows 上用 vmware workstations 安装了一个 macos 虚拟机, clone 代码的时候报错没有权限.<br><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">packet_write_wait: Connection to 13.229.188.59 port 22: Broken pipe</span><br></pre></td></tr></table></figure></p><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><p>创建 <code>~/.ssh/config</code> 文件:<br><figure class="highlight plain"><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">Host *</span><br><span class="line">    IPQoS lowdelay throughput</span><br></pre></td></tr></table></figure></p><p>或者执行:<br><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">sudo dnf downgrade openssh-clients-7.7p1</span><br></pre></td></tr></table></figure></p><h3 id="原issue链接"><a href="#原issue链接" class="headerlink" title="原issue链接"></a>原issue链接</h3><p><a href="https://github.com/vmware/open-vm-tools/issues/287#issuecomment-421347524" target="_blank" rel="noopener">OpenSSH 7.8 causes VMware Workstation and Player networking SSH bug on Linux VMs</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;在 windows 上用 vmware workstations 安装了一个 macos 虚拟机, clone 代码的时候报错没有权限.&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pr
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>flutter入门填坑记录</title>
    <link href="https://blog.wzdxy.com/2019/07/flutter%E5%85%A5%E9%97%A8%E5%A1%AB%E5%9D%91%E8%AE%B0%E5%BD%95/"/>
    <id>https://blog.wzdxy.com/2019/07/flutter入门填坑记录/</id>
    <published>2019-07-20T11:10:57.000Z</published>
    <updated>2020-12-30T08:53:57.873Z</updated>
    
    <content type="html"><![CDATA[<h3 id="配置国内Pub镜像"><a href="#配置国内Pub镜像" class="headerlink" title="配置国内Pub镜像"></a>配置国内Pub镜像</h3><p>参考官网的指南 [在中国使用Flutter]<a href="https://flutter.dev/community/china" target="_blank" rel="noopener">https://flutter.dev/community/china</a><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># Mac / Linux</span></span><br><span class="line"><span class="built_in">export</span> PUB_HOSTED_URL=https://pub.flutter-io.cn</span><br><span class="line"><span class="built_in">export</span> FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn</span><br><span class="line">git <span class="built_in">clone</span> -b dev https://github.com/flutter/flutter.git</span><br><span class="line"><span class="built_in">export</span> PATH=<span class="string">"<span class="variable">$PWD</span>/flutter/bin:<span class="variable">$PATH</span>"</span></span><br><span class="line"><span class="built_in">cd</span> ./flutter</span><br><span class="line">flutter doctor</span><br><span class="line"><span class="comment"># Windows</span></span><br><span class="line"><span class="built_in">set</span> PUB_HOSTED_URL=https://pub.flutter-io.cn</span><br><span class="line"><span class="built_in">set</span> FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn</span><br></pre></td></tr></table></figure></p><h3 id="Android-Studio-SDK下载失败-速度慢"><a href="#Android-Studio-SDK下载失败-速度慢" class="headerlink" title="Android Studio SDK下载失败/速度慢"></a>Android Studio SDK下载失败/速度慢</h3><p>在Android Studio 设置 - System Settings - HTTP Proxy 中配置代理, 指向本机的 SS (SS默认端口是 1080, 需设置为允许其他设备连入)<br><img src="https://static.wzdxy.com/img/20190725143530.png" alt="20190725143530.png"></p><h3 id="安卓release打包后不能访问网络"><a href="#安卓release打包后不能访问网络" class="headerlink" title="安卓release打包后不能访问网络"></a>安卓release打包后不能访问网络</h3><p>需要在 <code>android/app/src/main/AndroidManifest.xml</code> 中配置网络权限, iOS没试过, 应该也有类似的配置<br><figure class="highlight xml"><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="comment">&lt;!-- others --&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">application</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">"android.permission.INTERNET"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">manifest</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- others --&gt;</span></span><br></pre></td></tr></table></figure></p><h3 id="No-implementation-found-for-method-create-on-channel-flutter-io-videoPlayer"><a href="#No-implementation-found-for-method-create-on-channel-flutter-io-videoPlayer" class="headerlink" title="No implementation found for method create on channel flutter.io/videoPlayer"></a><code>No implementation found for method create on channel flutter.io/videoPlayer</code></h3><p>此报错出现于添加新插件(如视频播放组件)之后.<br>原因是对于带有特定平台代码的包, 热更新无法处理, 需要重启应用.<br><a href="https://flutter.dev/docs/development/packages-and-plugins/using-packages#adding-a-package-dependency-to-an-app" target="_blank" rel="noopener">Adding a package dependency to an app</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;配置国内Pub镜像&quot;&gt;&lt;a href=&quot;#配置国内Pub镜像&quot; class=&quot;headerlink&quot; title=&quot;配置国内Pub镜像&quot;&gt;&lt;/a&gt;配置国内Pub镜像&lt;/h3&gt;&lt;p&gt;参考官网的指南 [在中国使用Flutter]&lt;a href=&quot;https://flu
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>quicker调用imagemagick实现多屏壁纸</title>
    <link href="https://blog.wzdxy.com/2019/06/imagemagick-cross-wallpaper/"/>
    <id>https://blog.wzdxy.com/2019/06/imagemagick-cross-wallpaper/</id>
    <published>2019-06-12T00:40:02.000Z</published>
    <updated>2020-12-30T08:53:57.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="实现步骤"><a href="#实现步骤" class="headerlink" title="实现步骤"></a>实现步骤</h2><ul><li>如果未下载过 <code>imagemagick</code> 则先下载可执行文件</li><li>获取多屏幕的宽高<figure class="highlight powershell"><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="built_in">Add-Type</span> -AssemblyName System.Windows.Forms</span><br><span class="line">[System.Windows.Forms.Screen]::AllScreens</span><br><span class="line"></span><br><span class="line">BitsPerPixel : <span class="number">32</span></span><br><span class="line">Bounds       : &#123;X=<span class="number">2560</span>,Y=<span class="number">255</span>,Width=<span class="number">1920</span>,Height=<span class="number">1080</span>&#125;</span><br><span class="line">DeviceName   : \\.\DISPLAY1</span><br><span class="line">Primary      : False</span><br><span class="line">WorkingArea  : &#123;X=<span class="number">2560</span>,Y=<span class="number">255</span>,Width=<span class="number">1920</span>,Height=<span class="number">1040</span>&#125;</span><br><span class="line"></span><br><span class="line">BitsPerPixel : <span class="number">32</span></span><br><span class="line">Bounds       : &#123;X=<span class="number">0</span>,Y=<span class="number">0</span>,Width=<span class="number">2560</span>,Height=<span class="number">1440</span>&#125;</span><br><span class="line">DeviceName   : \\.\DISPLAY2</span><br><span class="line">Primary      : True</span><br><span class="line">WorkingArea  : &#123;X=<span class="number">0</span>,Y=<span class="number">0</span>,Width=<span class="number">2560</span>,Height=<span class="number">1400</span>&#125;</span><br></pre></td></tr></table></figure></li></ul><a id="more"></a><ul><li><p>调用 Powershell 执行 magick 命令, 将选中的2张图片合并为一张大图</p><figure class="highlight powershell"><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">magick.exe convert -size <span class="number">757</span>x388 -strip xc:none .\<span class="number">1</span>.jpg -geometry +<span class="number">0</span>+<span class="number">0</span>  -composite .\<span class="number">2</span>.jpg -geometry +<span class="number">369</span>+<span class="number">0</span> -composite  c2.jpg</span><br><span class="line"><span class="comment"># 总宽度 x 总高度     第一张图的起始位置 0 x 0     第二张图的起始位置  +x+y</span></span><br></pre></td></tr></table></figure></li><li><p>调用 .Net 设置桌面背景</p><figure class="highlight powershell"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> Set-Wallpaper</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">param</span>(</span><br><span class="line">        [Parameter(Mandatory=<span class="literal">$true</span>)]</span><br><span class="line">        <span class="variable">$Path</span>,</span><br><span class="line"></span><br><span class="line">        [ValidateSet(<span class="string">'Center'</span>, <span class="string">'Stretch'</span>, <span class="string">'Cross'</span>)]</span><br><span class="line">        <span class="variable">$Style</span> = <span class="string">'Stretch'</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    <span class="built_in">Add-Type</span> <span class="string">@"</span></span><br><span class="line"><span class="string">using System;</span></span><br><span class="line"><span class="string">using System.Runtime.InteropServices;</span></span><br><span class="line"><span class="string">using Microsoft.Win32;</span></span><br><span class="line"><span class="string">namespace Wallpaper</span></span><br><span class="line"><span class="string">&#123;</span></span><br><span class="line"><span class="string">public enum Style : int</span></span><br><span class="line"><span class="string">&#123;</span></span><br><span class="line"><span class="string">Center, Stretch, Cross</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">public class Setter &#123;</span></span><br><span class="line"><span class="string">public const int SetDesktopWallpaper = 20;</span></span><br><span class="line"><span class="string">public const int UpdateIniFile = 0x01;</span></span><br><span class="line"><span class="string">public const int SendWinIniChange = 0x02;</span></span><br><span class="line"><span class="string">[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]</span></span><br><span class="line"><span class="string">private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni);</span></span><br><span class="line"><span class="string">public static void SetWallpaper ( string path, Wallpaper.Style style ) &#123;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);</span></span><br><span class="line"><span class="string">// Console.WriteLine(style);</span></span><br><span class="line"><span class="string">switch( style )</span></span><br><span class="line"><span class="string">&#123;</span></span><br><span class="line"><span class="string">case Style.Stretch :</span></span><br><span class="line"><span class="string">key.SetValue(@"WallpaperStyle", "2") ;</span></span><br><span class="line"><span class="string">key.SetValue(@"TileWallpaper", "0") ;</span></span><br><span class="line"><span class="string">break;</span></span><br><span class="line"><span class="string">case Style.Center :</span></span><br><span class="line"><span class="string">key.SetValue(@"WallpaperStyle", "0") ;</span></span><br><span class="line"><span class="string">key.SetValue(@"TileWallpaper", "0") ;</span></span><br><span class="line"><span class="string">break;</span></span><br><span class="line"><span class="string">case Style.Cross :</span></span><br><span class="line"><span class="string">key.SetValue(@"WallpaperStyle", "22") ;</span></span><br><span class="line"><span class="string">key.SetValue(@"TileWallpaper", "0") ;</span></span><br><span class="line"><span class="string">break;</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">key.Close();</span></span><br><span class="line"><span class="string">SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">&#125;</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"></span><br><span class="line">    [Wallpaper.Setter]::SetWallpaper( <span class="variable">$Path</span>, <span class="variable">$Style</span> )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Set-Wallpaper -Path <span class="string">'C:\Users\zchi\Pictures\gg1.png'</span></span><br></pre></td></tr></table></figure></li></ul>]]></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;ul&gt;
&lt;li&gt;如果未下载过 &lt;code&gt;imagemagick&lt;/code&gt; 则先下载可执行文件&lt;/li&gt;
&lt;li&gt;获取多屏幕的宽高&lt;figure class=&quot;highlight powershell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;Add-Type&lt;/span&gt; -AssemblyName System.Windows.Forms&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;[System.Windows.Forms.Screen]::AllScreens&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;BitsPerPixel : &lt;span class=&quot;number&quot;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Bounds       : &amp;#123;X=&lt;span class=&quot;number&quot;&gt;2560&lt;/span&gt;,Y=&lt;span class=&quot;number&quot;&gt;255&lt;/span&gt;,Width=&lt;span class=&quot;number&quot;&gt;1920&lt;/span&gt;,Height=&lt;span class=&quot;number&quot;&gt;1080&lt;/span&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;DeviceName   : \\.\DISPLAY1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Primary      : False&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;WorkingArea  : &amp;#123;X=&lt;span class=&quot;number&quot;&gt;2560&lt;/span&gt;,Y=&lt;span class=&quot;number&quot;&gt;255&lt;/span&gt;,Width=&lt;span class=&quot;number&quot;&gt;1920&lt;/span&gt;,Height=&lt;span class=&quot;number&quot;&gt;1040&lt;/span&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;BitsPerPixel : &lt;span class=&quot;number&quot;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Bounds       : &amp;#123;X=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,Y=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,Width=&lt;span class=&quot;number&quot;&gt;2560&lt;/span&gt;,Height=&lt;span class=&quot;number&quot;&gt;1440&lt;/span&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;DeviceName   : \\.\DISPLAY2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Primary      : True&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;WorkingArea  : &amp;#123;X=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,Y=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,Width=&lt;span class=&quot;number&quot;&gt;2560&lt;/span&gt;,Height=&lt;span class=&quot;number&quot;&gt;1400&lt;/span&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>使用VSCode和Git写笔记</title>
    <link href="https://blog.wzdxy.com/2019/05/note-with-vscode-and-git/"/>
    <id>https://blog.wzdxy.com/2019/05/note-with-vscode-and-git/</id>
    <published>2019-05-25T10:44:34.000Z</published>
    <updated>2020-12-30T08:53:57.885Z</updated>
    
    <content type="html"><![CDATA[<h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>各种云笔记用来用去, 写Markdown体验最好的还是 VSCode, 所以决心折腾一下, 把 VSCode 打造成一款Markdown笔记工具.</p><h2 id="优势"><a href="#优势" class="headerlink" title="优势"></a>优势</h2><ul><li>VSCode 强大的编辑功能</li><li><p>Git 自带更完善的版本控制<br><img src="https://static.wzdxy.com/img/20190525113212.png" alt="20190525113212.png"></p></li><li><p>自建同步, 不受第三方控制</p></li><li>迁移方便</li></ul><h2 id="解决痛点"><a href="#解决痛点" class="headerlink" title="解决痛点"></a>解决痛点</h2><p>❓ 图片的插入, 代码编辑器不像云笔记软件, 可以方便的上传图片, 且无需关心存储.<br>❓ 分享和演示<br>❓ 笔记管理, 搜索, 标签, 归档等功能</p><a id="more"></a><p>✔ 图片插入的问题, 使用VS-Picgo插件解决.<br>✔ 使用 <code>vscode-reveal</code> 插件实现演示, 使用 <code>Marp</code> 插件实现导出PDF<br>✖ 暂未解决, 也许可以在 Tree View 的位置开发一个管理笔记的 VSCode 扩展</p><h2 id="图片插入"><a href="#图片插入" class="headerlink" title="图片插入"></a>图片插入</h2><p>PicGo 是一个专门上传图片的工具, 支持又拍云, 七牛云, 阿里云等私有云存储, 也支持 sm.ms 等免费图床. 很早就发布了桌面版本, 现在也推出了 VSCode 扩展.</p><h3 id="安装和配置"><a href="#安装和配置" class="headerlink" title="安装和配置"></a>安装和配置</h3><p>首先需要在 VSCode 扩展商店里安装 PicGo.<br><img src="https://static.wzdxy.com/img/20190525111915.png" alt="20190525111915.png"></p><p>如果你已经配置过 PicGo 的桌面版软件, 只需导入其配置文件文件即可开始使用.<br><img src="https://static.wzdxy.com/img/20190525112420.png" alt="20190525112420.png"><br>如果没有现成的配置文件, 就需要在 VSCode 的 <code>Settings</code> 里手动配置 (建议安装一个桌面版, 先在桌面版里配置, 这样两个平台就可以同步一份配置)</p><h3 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h3><p>PicGo 支持剪贴板上传, 文件上传, 路径上传, 以及自定义文件名, 十分方便<br><img src="https://static.wzdxy.com/img/20190525112620.png" alt="20190525112620.png"></p><h2 id="同步"><a href="#同步" class="headerlink" title="同步"></a>同步</h2><p>Github 最近推出了私有仓库, 可以用来同步笔记.<br>这个操作就很简单了, 直接创建私有仓库, clone 下来用 VSCode 打开即可随意创建文件.</p><p>按照 Git 的方式提交和同步即可.</p><h2 id="编写"><a href="#编写" class="headerlink" title="编写"></a>编写</h2><p>建议采用 Hexo 的规范, 每篇笔记定义 <code>Title</code>, <code>Tag</code>, <code>Data</code> 和等信息.<br>这种笔记方式也是受到了 Hexo 的启发, 后续的完善也会更多的借鉴 Hexo.<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></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: 使用VSCode和Git写笔记</span><br><span class="line">date: 2019-05-25 10:44:34</span><br><span class="line">tags:</span><br><span class="line">- VSCode</span><br><span class="line">- Git</span><br><span class="line">permalink: note-with-vscode-and-git</span><br><span class="line">---</span><br></pre></td></tr></table></figure></p><h2 id="演示"><a href="#演示" class="headerlink" title="演示"></a>演示</h2><p><code>Reveal.js</code> 是一个基于 HTML 技术的幻灯片工具, 可以用 HTML 或 Markdown 的语法创建幻灯片, <code>vscode-reveal</code> 是基于 <code>Reveal.js</code> 的VSCode 插件, 可以实现以幻灯片形式直接演示 Markdown 文件.</p><ul><li>安装插件<br><img src="https://static.wzdxy.com/img/20190525165728.png" alt="20190525165728.png"></li><li>根据<code>Reveal.js</code> 的语法, 用 <code>---</code> 给笔记分节, 每节在幻灯片中会展示为一页.</li><li><code>F1</code> 打开命令, 输入 Revealjs 可以看到所有命令<br><img src="https://static.wzdxy.com/img/20190525170152.png" alt="20190525170152.png"></li><li>选择 <code>Open presentation in browser</code> 即可启动一个服务, 并在浏览器中展示生成的幻灯片. 同时在 VSCode 的状态栏可以看到幻灯片和服务的状态, 也可以点击按钮停止服务.<br><img src="https://static.wzdxy.com/img/20190525170513.png" alt="20190525170513.png"></li></ul>]]></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;p&gt;各种云笔记用来用去, 写Markdown体验最好的还是 VSCode, 所以决心折腾一下, 把 VSCode 打造成一款Markdown笔记工具.&lt;/p&gt;
&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;ul&gt;
&lt;li&gt;VSCode 强大的编辑功能&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git 自带更完善的版本控制&lt;br&gt;&lt;img src=&quot;https://static.wzdxy.com/img/20190525113212.png&quot; alt=&quot;20190525113212.png&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;自建同步, 不受第三方控制&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;迁移方便&lt;/li&gt;
&lt;/ul&gt;
&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;p&gt;❓ 图片的插入, 代码编辑器不像云笔记软件, 可以方便的上传图片, 且无需关心存储.&lt;br&gt;❓ 分享和演示&lt;br&gt;❓ 笔记管理, 搜索, 标签, 归档等功能&lt;/p&gt;
    
    </summary>
    
    
      <category term="Git" scheme="https://blog.wzdxy.com/tags/Git/"/>
    
      <category term="VSCode" scheme="https://blog.wzdxy.com/tags/VSCode/"/>
    
  </entry>
  
  <entry>
    <title>ubuntu1804下hue的编译和安装</title>
    <link href="https://blog.wzdxy.com/2019/04/ubuntu1804%E4%B8%8Bhue%E7%9A%84%E7%BC%96%E8%AF%91%E5%92%8C%E5%AE%89%E8%A3%85/"/>
    <id>https://blog.wzdxy.com/2019/04/ubuntu1804下hue的编译和安装/</id>
    <published>2019-04-01T16:32:07.000Z</published>
    <updated>2020-12-30T08:53:57.877Z</updated>
    
    <content type="html"><![CDATA[<h2 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h2><ul><li><p>安装 Java (Open JDK 即可)</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">sudo apt-get update</span><br><span class="line">sudo apt-get install openjdk-8-jdk</span><br></pre></td></tr></table></figure></li><li><p>安装 Maven</p><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></pre></td><td class="code"><pre><span class="line">wget http://mirrors.shu.edu.cn/apache/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz</span><br><span class="line">tar xzvf apache-maven-3.6.0-bin.tar.gz</span><br><span class="line"><span class="comment">#设置环境变量 (替换成自己的解压目录)</span></span><br><span class="line"><span class="built_in">export</span> PATH=/home/zchi/apache-maven-3.6.0/bin:<span class="variable">$PATH</span></span><br><span class="line"><span class="comment">#查看版本</span></span><br><span class="line">mvn -v</span><br></pre></td></tr></table></figure></li><li><p>安装 Node.js<br><a href="/2018/07/install-node-in-ubuntu/">Ubuntu16.04安装新版本的Nodejs</a></p></li></ul><a id="more"></a><ul><li>其他依赖<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></pre></td><td class="code"><pre><span class="line">apt-get install python2.7-dev \</span><br><span class="line">make \</span><br><span class="line">libkrb5-dev \</span><br><span class="line">libxml2-dev \</span><br><span class="line">libffi-dev \</span><br><span class="line">libxslt-dev \</span><br><span class="line">libsqlite3-dev \</span><br><span class="line">libssl-dev \</span><br><span class="line">libldap2-dev \</span><br><span class="line">python-pip</span><br></pre></td></tr></table></figure></li></ul><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">sudo apt-get install ant gcc g++ libkrb5-dev libffi-dev libmysqlclient-dev libssl-dev libsasl2-dev libsasl2-modules-gssapi-mit libsqlite3-dev libtidy-0.99-0 libxml2-dev libxslt-dev make libldap2-dev maven python-dev python-setuptools libgmp3-dev</span><br><span class="line"><span class="comment"># 如果报错  Package 'libtidy-0.99-0' has no installation candidate , 执行:</span></span><br><span class="line"><span class="comment"># sudo apt-get install ant gcc g++ libkrb5-dev libffi-dev libmysqlclient-dev libssl-dev libsasl2-dev libsasl2-modules-gssapi-mit libsqlite3-dev libxml2-dev libxslt-dev make libldap2-dev maven python-dev python-setuptools libgmp3-dev</span></span><br></pre></td></tr></table></figure><ul><li>编译<figure class="highlight plain"><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">make apps</span><br></pre></td></tr></table></figure></li></ul>]]></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;ul&gt;
&lt;li&gt;&lt;p&gt;安装 Java (Open JDK 即可)&lt;/p&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo apt-get update&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sudo apt-get install openjdk-8-jdk&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;安装 Maven&lt;/p&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;wget http://mirrors.shu.edu.cn/apache/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;tar xzvf apache-maven-3.6.0-bin.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#设置环境变量 (替换成自己的解压目录)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;export&lt;/span&gt; PATH=/home/zchi/apache-maven-3.6.0/bin:&lt;span class=&quot;variable&quot;&gt;$PATH&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#查看版本&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mvn -v&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;安装 Node.js&lt;br&gt;&lt;a href=&quot;/2018/07/install-node-in-ubuntu/&quot;&gt;Ubuntu16.04安装新版本的Nodejs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>mongodb配置远程访问</title>
    <link href="https://blog.wzdxy.com/2019/03/mongo-db-start/"/>
    <id>https://blog.wzdxy.com/2019/03/mongo-db-start/</id>
    <published>2019-03-16T20:49:09.000Z</published>
    <updated>2020-12-30T08:53:57.873Z</updated>
    
    <content type="html"><![CDATA[<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>按照官方文档即可</p><h2 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h2><p>默认的配置是无验证但仅限本机IP (127.0.0.1) 访问<br><figure class="highlight yaml"><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="attr">net:</span></span><br><span class="line"><span class="attr">  bindIp:</span> <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span></span><br><span class="line"><span class="attr">security:</span></span><br><span class="line"><span class="attr">  auth:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure></p><a id="more"></a><h2 id="创建用户"><a href="#创建用户" class="headerlink" title="创建用户"></a>创建用户</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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建管理员用户</span></span><br><span class="line">&gt; db.createUser(&#123;user: <span class="string">'root'</span>, <span class="built_in">pwd</span>:<span class="string">'YOUR PASSWORD'</span>, roles:[<span class="string">'root'</span>]&#125;)</span><br><span class="line">Successfully added user: &#123; <span class="string">"user"</span> : <span class="string">"root"</span>, <span class="string">"roles"</span> : [ <span class="string">"root"</span> ] &#125;</span><br><span class="line"><span class="comment"># 验证测试</span></span><br><span class="line">&gt; db.auth(<span class="string">'root'</span>, <span class="string">'PASSWORD'</span>)</span><br><span class="line">1</span><br><span class="line"><span class="comment"># 创建数据库用户 ( 以 test 数据库为例)</span></span><br><span class="line">&gt; db.createUser(&#123;user:<span class="string">'rocket'</span>,<span class="built_in">pwd</span>:<span class="string">'YOUR ANOTHER PASSWORD'</span>,roles:[&#123;role:<span class="string">'readWrite'</span>,db:<span class="string">'test'</span>&#125;]&#125;)</span><br><span class="line">Successfully added user: &#123;</span><br><span class="line"><span class="string">"user"</span> : <span class="string">"rocket"</span>,</span><br><span class="line"><span class="string">"roles"</span> : [</span><br><span class="line">&#123;</span><br><span class="line"><span class="string">"role"</span> : <span class="string">"readWrite"</span>,</span><br><span class="line"><span class="string">"db"</span> : <span class="string">"test"</span></span><br><span class="line">&#125;</span><br><span class="line">]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="远程连接数据库"><a href="#远程连接数据库" class="headerlink" title="远程连接数据库"></a>远程连接数据库</h2><p>以 <code>MongoDB Compass</code> 为例<br><img src="https://static.wzdxy.com/img/20190316210520.png" alt=""></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;p&gt;按照官方文档即可&lt;/p&gt;
&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;p&gt;默认的配置是无验证但仅限本机IP (127.0.0.1) 访问&lt;br&gt;&lt;figure class=&quot;highlight yaml&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;attr&quot;&gt;net:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;attr&quot;&gt;  bindIp:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;.0&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;.0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;attr&quot;&gt;security:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;attr&quot;&gt;  auth:&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="Linux" scheme="https://blog.wzdxy.com/tags/Linux/"/>
    
      <category term="MongoDB" scheme="https://blog.wzdxy.com/tags/MongoDB/"/>
    
  </entry>
  
  <entry>
    <title>VGA连接显示器提示输入不支援的原因和解决方法</title>
    <link href="https://blog.wzdxy.com/2019/01/vga-display-error/"/>
    <id>https://blog.wzdxy.com/2019/01/vga-display-error/</id>
    <published>2019-01-08T21:39:53.000Z</published>
    <updated>2020-12-30T08:53:57.881Z</updated>
    
    <content type="html"><![CDATA[<p>笔记本用 <code>Dell DA200</code> type-c hub 转接的 VGA 连接到 HP 外置显示器时, 出现了<code>输入不支援</code>的提示<br>但设备管理器和显示设置中都已经发现了外接显示器, 这原因可能是电脑错误的输出了显示器不支持的分辨率和频率<br><img src="https://static.wzdxy.com/img/20190108215132.png" alt=""><br><a id="more"></a><br>win10 可以通过以下步骤来修复:</p><ol><li>在 <code>设置</code> - <code>显示</code> 底部, 点击 <code>高级显示设置</code> , 选择外接显示器的适配器属性<br><img src="https://static.wzdxy.com/img/20190108213418.png" alt=""><br><img src="https://static.wzdxy.com/img/20190108213626.png" alt=""></li><li><p>在弹出的菜单中点击 <code>列出所有模式</code>, 选择适合自己显示器的配置, 常见的刷新率是60Hz , 如果不确定, 就先选择最低的<br><img src="https://static.wzdxy.com/img/20190108213749.png" alt=""></p></li><li><p>如果配置正确, 外接显示器就可以正常工作了<br><img src="https://static.wzdxy.com/img/20190108215440.png" alt=""></p></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;笔记本用 &lt;code&gt;Dell DA200&lt;/code&gt; type-c hub 转接的 VGA 连接到 HP 外置显示器时, 出现了&lt;code&gt;输入不支援&lt;/code&gt;的提示&lt;br&gt;但设备管理器和显示设置中都已经发现了外接显示器, 这原因可能是电脑错误的输出了显示器不支持的分辨率和频率&lt;br&gt;&lt;img src=&quot;https://static.wzdxy.com/img/20190108215132.png&quot; alt=&quot;&quot;&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="windows" scheme="https://blog.wzdxy.com/tags/windows/"/>
    
      <category term="hardware" scheme="https://blog.wzdxy.com/tags/hardware/"/>
    
  </entry>
  
  <entry>
    <title>如何优雅的在windows下开发之 ---- powershell配置</title>
    <link href="https://blog.wzdxy.com/2018/12/windows-powershell-start/"/>
    <id>https://blog.wzdxy.com/2018/12/windows-powershell-start/</id>
    <published>2018-12-08T22:58:39.000Z</published>
    <updated>2020-12-30T08:53:57.889Z</updated>
    
    <content type="html"><![CDATA[<h2 id="安装更纱字体"><a href="#安装更纱字体" class="headerlink" title="安装更纱字体"></a>安装更纱字体</h2><p>更纱字体一个很适合终端/编程并且对中文和日文都支持很好的字体系列, 还支持 PowerLine 字体.</p><p>下载ttf 文件并选择喜欢的安装即可, 我使用的是 <code>&#39;Sarasa Term SC&#39;</code></p><p>安装后在 Powershell 标题右键属性即可配置</p><h2 id="安装终端增强的软件-需在管理员模式的-Powershell-窗口运行"><a href="#安装终端增强的软件-需在管理员模式的-Powershell-窗口运行" class="headerlink" title="安装终端增强的软件 (需在管理员模式的 Powershell 窗口运行)"></a>安装终端增强的软件 (需在管理员模式的 Powershell 窗口运行)</h2><ol><li><p><code>DirColors</code> 让 ls (Get-ChildItem) 像 Unix 系终端一样具有多彩色 </p> <figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Install-Module DirColors</span><br></pre></td></tr></table></figure></li><li><p><code>Post-Git</code> 和 <code>Git-Aliases</code> 可以实现类似 <code>oh-my-zsh</code> 一样的 Git 增强(命令别名和显示分支等信息)</p><a id="more"></a> <figure class="highlight powershell"><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">Install-Module posh-git</span><br><span class="line">Install-Module -Name git-aliases -RequiredVersion <span class="number">0.0</span>.<span class="number">1</span> -AllowClobber</span><br></pre></td></tr></table></figure></li><li><p><code>pshazz</code> (可选) </p><ul><li>一个软件可用代替前面两个, 实现 git 增强和别名</li><li>优点是解决了前者在 vscode 中光标容易错位的 bug</li><li>但UI不如前面好看</li><li>安装 (使用 scoop 安装, 如果没有, 需先安装 scoop)<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">scoop install pshazz</span><br></pre></td></tr></table></figure></li></ul></li><li><p>创建  Microsoft.PowerShell_profile.ps1</p> <figure class="highlight powershell"><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="variable">$PROFILE</span>    // 查看配置文件的全路径</span><br><span class="line">code <span class="variable">$PROFILE</span> // 使用 vscode 打开(或创建)配置文件, notepad 也可以</span><br></pre></td></tr></table></figure> <figure class="highlight powershell"><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"># 写入以下内容 , 保存后新开一个 Powershell 即可看到效果</span></span><br><span class="line"><span class="built_in">Import-Module</span> DirColors</span><br><span class="line"><span class="built_in">Import-Module</span> posh-git</span><br><span class="line"><span class="built_in">Import-Module</span> git-aliases -DisableNameChecking</span><br></pre></td></tr></table></figure></li></ol><h2 id="在-vscode-中调用"><a href="#在-vscode-中调用" class="headerlink" title="在 vscode 中调用"></a>在 vscode 中调用</h2><ol><li>设置默认终端<ul><li><code>F1</code> 调出命令窗口, <code>Terminal: select default shell</code>, 选择 <code>Powershell</code></li></ul></li><li>给终端设置字体<ul><li>在设置中找到 <code>Terminal › Integrated: Font Family</code></li><li>设置为 <code>&#39;Sarasa Term SC&#39;</code></li></ul></li></ol><h2 id="在终端中调用编辑器"><a href="#在终端中调用编辑器" class="headerlink" title="在终端中调用编辑器"></a>在终端中调用编辑器</h2><ol><li><strong>VS Code</strong>: <code>code</code> 即可新开 一个 vscode , 参数可以是文件(编辑文件) 或 路径 (打开为工作区).</li><li><strong>NotePad++</strong>: 将安装目录加入环境变量, <code>notepad++.exe</code> 即可, 想偷懒的话可以将 <code>notepad++.exe</code> 复制一个为 <code>npp.exe</code>, 就可以用 <code>npp</code> 调用了</li></ol><h2 id="使用VSCode调试-Powershell-脚本"><a href="#使用VSCode调试-Powershell-脚本" class="headerlink" title="使用VSCode调试 Powershell 脚本"></a>使用VSCode调试 Powershell 脚本</h2><ul><li><strong>安装扩展</strong> <code>PowerShell</code></li><li><p><strong>创建文件</strong> Powershell 脚本使用 <code>ps1</code> 作为文件后缀</p>  <figure class="highlight powershell"><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="comment"># 1.ps1</span></span><br><span class="line"><span class="string">"Hello PowerShell"</span></span><br><span class="line"><span class="string">"Now Is "</span>+(<span class="built_in">Get-Date</span>)</span><br></pre></td></tr></table></figure></li><li><p><strong>开始调试</strong><br>  按F5即可执行, 支持断点</p></li><li>如果无法重复调试, 在 VSCode 的设置中勾选 <code>Create Temporary Integrated Console</code></li></ul><h2 id="在-Powershell-中使用-SS-代理"><a href="#在-Powershell-中使用-SS-代理" class="headerlink" title="在 Powershell 中使用 SS 代理"></a>在 Powershell 中使用 SS 代理</h2><ol><li>在 ss 中允许局域网的连接/允许其他设备连入</li><li>在终端执行<pre><code class="powershell">netsh winhttp import proxy source=ie<span class="comment"># 如果成功会返回下面内容</span>当前的 WinHTTP 代理服务器设置:代理服务器:  <span class="number">127.0</span>.<span class="number">0.1</span>:<span class="number">1080</span>...</code></pre></li></ol><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><h3 id="TBC…"><a href="#TBC…" class="headerlink" title="TBC…"></a>TBC…</h3>]]></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;p&gt;更纱字体一个很适合终端/编程并且对中文和日文都支持很好的字体系列, 还支持 PowerLine 字体.&lt;/p&gt;
&lt;p&gt;下载ttf 文件并选择喜欢的安装即可, 我使用的是 &lt;code&gt;&amp;#39;Sarasa Term SC&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;安装后在 Powershell 标题右键属性即可配置&lt;/p&gt;
&lt;h2 id=&quot;安装终端增强的软件-需在管理员模式的-Powershell-窗口运行&quot;&gt;&lt;a href=&quot;#安装终端增强的软件-需在管理员模式的-Powershell-窗口运行&quot; class=&quot;headerlink&quot; title=&quot;安装终端增强的软件 (需在管理员模式的 Powershell 窗口运行)&quot;&gt;&lt;/a&gt;安装终端增强的软件 (需在管理员模式的 Powershell 窗口运行)&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;DirColors&lt;/code&gt; 让 ls (Get-ChildItem) 像 Unix 系终端一样具有多彩色 &lt;/p&gt;
 &lt;figure class=&quot;highlight powershell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Install-Module DirColors&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Post-Git&lt;/code&gt; 和 &lt;code&gt;Git-Aliases&lt;/code&gt; 可以实现类似 &lt;code&gt;oh-my-zsh&lt;/code&gt; 一样的 Git 增强(命令别名和显示分支等信息)&lt;/p&gt;
    
    </summary>
    
    
      <category term="windows" scheme="https://blog.wzdxy.com/tags/windows/"/>
    
      <category term="powershell" scheme="https://blog.wzdxy.com/tags/powershell/"/>
    
      <category term="notepad++" scheme="https://blog.wzdxy.com/tags/notepad/"/>
    
      <category term="vscode" scheme="https://blog.wzdxy.com/tags/vscode/"/>
    
  </entry>
  
  <entry>
    <title>解决 git 在 windows 终端下乱码</title>
    <link href="https://blog.wzdxy.com/2018/12/windows-git-encode/"/>
    <id>https://blog.wzdxy.com/2018/12/windows-git-encode/</id>
    <published>2018-12-08T18:30:33.000Z</published>
    <updated>2020-12-30T08:53:57.865Z</updated>
    
    <content type="html"><![CDATA[<h2 id="git-log-git-diff-乱码"><a href="#git-log-git-diff-乱码" class="headerlink" title="git log , git diff 乱码"></a>git log , git diff 乱码</h2><p>类似<br><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">&lt;E9&gt;&lt;85&gt;&lt;8D&gt;&lt;E7&gt;&lt;BD&gt;&lt;AE&gt;&lt;E6&gt;&lt;96&gt;&lt;87&gt;&lt;E4&gt;&lt;BB&gt;</span><br></pre></td></tr></table></figure></p><p>解决方法<br><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">setx LESSCHARSET &apos;utf-8&apos;</span><br></pre></td></tr></table></figure></p><h2 id="git-status-乱码"><a href="#git-status-乱码" class="headerlink" title="git status 乱码"></a>git status 乱码</h2><p>类似<br><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">\226\260\345\273\272\346</span><br></pre></td></tr></table></figure></p><p>解决方法<br><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">git config --global core.quotepath false</span><br></pre></td></tr></table></figure></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;git-log-git-diff-乱码&quot;&gt;&lt;a href=&quot;#git-log-git-diff-乱码&quot; class=&quot;headerlink&quot; title=&quot;git log , git diff 乱码&quot;&gt;&lt;/a&gt;git log , git diff 乱码&lt;/h2&gt;&lt;
      
    
    </summary>
    
    
      <category term="windows" scheme="https://blog.wzdxy.com/tags/windows/"/>
    
      <category term="git" scheme="https://blog.wzdxy.com/tags/git/"/>
    
      <category term="powershell" scheme="https://blog.wzdxy.com/tags/powershell/"/>
    
  </entry>
  
  <entry>
    <title>如何优雅的在 windows 下开发---Windows SubSystem Linux 踩坑记录</title>
    <link href="https://blog.wzdxy.com/2018/11/wsl-start/"/>
    <id>https://blog.wzdxy.com/2018/11/wsl-start/</id>
    <published>2018-11-03T10:08:15.000Z</published>
    <updated>2020-12-30T08:53:57.881Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>或为目前最好用的 Linux 发行版<br>更纯正的 Linux 命令行环境和<del>更</del>最好用的图形界面操作系统</p><h2 id="安装和启动"><a href="#安装和启动" class="headerlink" title="安装和启动"></a>安装和启动</h2><ol><li>准备工作: 在<code>启用或关闭 Windows 功能</code>中打开 <code>适用于 Linux 的 Windows 子系统</code><a id="more"></a><img src="https://static.wzdxy.com/img/Snipaste_2018-11-03_12-47-35.jpg" alt=""></li><li>应用商店搜索 <code>wsl</code>, 安装 <code>Ubuntu 16.04</code> 或其他 Linux 发行版<br><img src="https://static.wzdxy.com/img/Snipaste_2018-11-03_12-45-08.jpg" alt=""></li><li>在开始菜单中启动即可, 首次打开需要设置用户名和密码<br><img src="https://static.wzdxy.com/img/sc_2018-11-03_12-52-57.jpg" alt=""></li><li>在 cmd 或 Wox 启动</li></ol><h2 id="加入右键菜单"><a href="#加入右键菜单" class="headerlink" title="加入右键菜单"></a>加入右键菜单</h2><p><img src="https://static.wzdxy.com/img/sc_2018-11-03_15-41-04.jpg" alt=""></p><ol><li>找到注册表中 <code>\HKEY_CLASSES_ROOT\Directory\Background\shell\</code></li><li>右键<code>shell</code>新建一个项 (名称随意, 可以叫<code>WSL</code>), 双击其中的<code>默认</code>, 改为 <code>Bash here</code>(右键菜单要显示的名字)</li><li>在默认下面加一个<code>字符串值</code>, 名为<code>Icon</code>, 双击将它的值改为你想要的图标的地址,可以是.ico和.exe文件., 比如用 <a href="https://static.wzdxy.com/img/ubuntu.ico" target="_blank" rel="noopener">Ubuntu 的图标</a></li><li>在 <code>WSL</code> 下新建一个项,名为<code>command</code>, 将这个项中的 <code>默认</code> 改为 <code>&quot;C:\Windows\System32\bash.exe&quot;</code>, (带双引号)<br><img src="https://static.wzdxy.com/img/sc_2018-11-03_15-17-21.jpg" alt=""><br><img src="https://static.wzdxy.com/img/sc_2018-11-03_15-17-31.jpg" alt=""></li></ol><h2 id="访问-windows-下的文件"><a href="#访问-windows-下的文件" class="headerlink" title="访问 windows 下的文件"></a>访问 windows 下的文件</h2><ul><li><code>/mnt</code> 路径</li><li>软连接挂载常用目录 <code>ln -s /mnt/e e</code><br><img src="https://static.wzdxy.com/img/sc_2018-11-03_12-57-10.png" alt=""></li></ul><h2 id="让终端能走梯子"><a href="#让终端能走梯子" class="headerlink" title="让终端能走梯子"></a>让终端能走梯子</h2><ul><li>不需要在 linux 中安装 ss , 可以直接利用 windows 上 ss 的代理<figure class="highlight"><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="comment"># ~/.bashrc 或 ~/zshrc</span></span><br><span class="line">export http_proxy="http://127.0.0.1:1080"</span><br><span class="line">export https_proxy="http://127.0.0.1:1080"</span><br></pre></td></tr></table></figure></li></ul><h2 id="安装oh-my-zsh"><a href="#安装oh-my-zsh" class="headerlink" title="安装oh my zsh"></a>安装oh my zsh</h2><ol><li>安装 zsh , <code>sudo apt-get install zsh</code></li><li><p>安装 oh my zsh</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"</span><br></pre></td></tr></table></figure></li><li><p>设置为默认终端</p><figure class="highlight"><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="comment"># ~/.bash_profile (适用于 cmder , vscode)</span></span><br><span class="line">exec zshh</span><br><span class="line">source .zshrc</span><br></pre></td></tr></table></figure></li></ol><h2 id="配置开发环境"><a href="#配置开发环境" class="headerlink" title="配置开发环境"></a>配置开发环境</h2><h3 id="设为-vscode-默认终端"><a href="#设为-vscode-默认终端" class="headerlink" title="设为 vscode 默认终端"></a>设为 vscode 默认终端</h3><ol><li>设置 <code>&quot;terminal.integrated.shell.windows&quot;: &quot;C:\\Windows\\Sysnative\\bash.exe&quot;</code></li><li><code>Ctrl + `</code> 启动终端即可<br><img src="https://static.wzdxy.com/img/sc_2018-11-03_14-46-17.jpg" alt=""></li></ol><h2 id="命令行访问-windows-下的可执行文件"><a href="#命令行访问-windows-下的可执行文件" class="headerlink" title="命令行访问 windows 下的可执行文件"></a>命令行访问 windows 下的可执行文件</h2><ol><li><code>code .</code> 当前目录启动 vscode  (这个 vscode 是windows下的, 貌似仅支持在 <code>\mnt</code> 路径下的文件夹使用, 不支持 linux 路径)</li><li>执行全局 node 模块<br><a href="https://blog.wzdxy.com/2018/07/install-node-in-ubuntu/">安装 Node.js</a> 后, 在 Ubuntu 里可以直接运行 windows 下的 npm 包.<br><img src="https://static.wzdxy.com/img/sc_2018-11-03_14-16-52.jpg" alt=""><br>关于执行 Node 模块这一点真是让人困惑, 我在 windows 上安装的 node 版本是 10.x , Ubuntu 上安装的是 8.x.<br>从截图看出我在 Ubuntu 上只装了一个 gulp, 但我运行 <code>parcel</code>, <code>hexo</code> 等 windows 上安装的全局包时, 却可以正常运行, 而 hexo 的 info 显示使用的 Node 是 Linux 上的.<br>也就是说, 只要子系统安装了 node, 就可以在 Linux 环境直接调用 windows 下的 npm 包, 不需要单独安装, 不过还没测试过本地编译的包能不能用.<br>(我怎么感觉这是个环境变量混乱导致的 BUG, 还需要再了解一下 WSL 和 windows 交互的特性啊)</li></ol><h2 id="配置换行符为-LF"><a href="#配置换行符为-LF" class="headerlink" title="配置换行符为 LF"></a>配置换行符为 LF</h2><p>windows 下默认的换行方式是 <code>CRLF</code>, 而大家在协作时通用的代码换行方式是 Unix 系的 <code>LF</code> 换行, (Mac OS 从前使用 <code>CR</code>, 现已经改为 <code>LF</code>)<br>在 windows 系统中, VCS 通常采用 <code>autocrlf</code> 的办法来解决问题, 在检出代码时将 <code>LF</code> 替换为 <code>CRLF</code>, 提交时再替换回 <code>LF</code>, 以此保证提交的代码和使用 Linux/Mac 的小伙伴一致.<br>但是在 WSL 中, Linux 和 windows 的文件系统是互通的, 这就会导致问题, 尤其是使用WSL中的 git 时. 如果开启 autocrlf, 在 WSL 的 git 检出代码时, 会得到 windows 默认的 CRLF 换行, 在 windows 中这符合预期, 但如果我们在 Linux 使用 git 安装一些程序, 这些程序的代码就会出错 (因为 Linux 的文件系统不应该出现 CRLF 换行符), 所以我们在 windows 系统中也使用 <code>LF</code> 换行:</p><ol><li>关闭 windows 中 git 的自动转换 <code>git config --global core.autocrlf false</code> (避免 clone 的代码出现 CRLF)</li><li>配置编辑器的默认换行符为 <code>LF</code><ul><li><code>vscode</code> : `Text editor - Files - the default end of the line character</li><li><code>webstorm</code> : <code>Editor - Code Style - Line separator - Unix and OS X</code></li><li><code>Notepad++</code> : <code>首选项 - 新建 - 格式 - Unix</code></li></ul></li><li>杜绝使用 windows 自带的 <code>记事本</code></li></ol><h2 id="To-Be-Continue…"><a href="#To-Be-Continue…" class="headerlink" title="To Be Continue…"></a>To Be Continue…</h2>]]></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;p&gt;或为目前最好用的 Linux 发行版&lt;br&gt;更纯正的 Linux 命令行环境和&lt;del&gt;更&lt;/del&gt;最好用的图形界面操作系统&lt;/p&gt;
&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;ol&gt;
&lt;li&gt;准备工作: 在&lt;code&gt;启用或关闭 Windows 功能&lt;/code&gt;中打开 &lt;code&gt;适用于 Linux 的 Windows 子系统&lt;/code&gt;
    
    </summary>
    
    
      <category term="Linux" scheme="https://blog.wzdxy.com/tags/Linux/"/>
    
      <category term="WSL" scheme="https://blog.wzdxy.com/tags/WSL/"/>
    
  </entry>
  
</feed>
