-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
227 lines (134 loc) · 145 KB
/
search.xml
File metadata and controls
227 lines (134 loc) · 145 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Fish Shell 製作 terminal custom greeting</title>
<link href="/2018/06/30/shell/fish-shell-random-quote/"/>
<url>/2018/06/30/shell/fish-shell-random-quote/</url>
<content type="html"><![CDATA[<h1 id="Fish-Shell-製作-terminal-custom-greeting"><a href="#Fish-Shell-製作-terminal-custom-greeting" class="headerlink" title="Fish Shell 製作 terminal custom greeting"></a>Fish Shell 製作 terminal custom greeting</h1><h2 id="User-Story"><a href="#User-Story" class="headerlink" title="User Story"></a>User Story</h2><p>每次打開 terminal 都可以看到隨機的勵志語錄在上方</p><p><img src="https://i.imgur.com/lnI3G9O.png" alt=""></p><h2 id="清除預設-greeting"><a href="#清除預設-greeting" class="headerlink" title="清除預設 greeting"></a>清除預設 greeting</h2><p>預設打開 fish shell 會看到</p><blockquote><p>Welcome to fish, the friendly interactive shell<br>Type help for instructions on how to use fish</p></blockquote><p>如果要更換文字的話可以到 <code>~/.config/fish/config.fish</code> 檔案內加上<br><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">set fish_greeting "Welcome"</span><br></pre></td></tr></table></figure></p><p>這時候再重新打開 fish shell 會看到 <code>Welcome</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">Welcome to fish, the friendly interactive shell</span><br><span class="line">Type help for instructions on how to use fish</span><br></pre></td></tr></table></figure></p><p><img src="https://i.imgur.com/K0lvX8Q.png" alt=""></p><p>註:如果沒有 config.fish 就自己手動創建一份</p><h2 id="Shell-Script"><a href="#Shell-Script" class="headerlink" title="Shell Script"></a>Shell Script</h2><h3 id="echo"><a href="#echo" class="headerlink" title="echo"></a>echo</h3><p>如果在 <code>set fish_greeting "Welcome"</code> 下面加上</p><figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo <span class="symbol">'Hello</span> <span class="type">World</span>'</span><br></pre></td></tr></table></figure><p>重開終端機就會看到</p><p><img src="https://i.imgur.com/otFF7Bj.png" alt=""></p><h3 id="set"><a href="#set" class="headerlink" title="set"></a>set</h3><p>set 可以設定變數為某個值,並在 <code>echo</code> 時候加上 <code>$</code> 取出來</p><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">set a 'this is a'</span><br><span class="line">echo $a</span><br><span class="line"></span><br><span class="line">//result</span><br><span class="line">//this is a</span><br></pre></td></tr></table></figure><p>因此可以開始設定語錄變數</p><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">set 0 擁有夢想只是一種智力,實現夢想才是一種能力。</span><br><span class="line">set 1 人生只有走出來的美麗,沒有等出來的輝煌。</span><br><span class="line">set 2 人生就像騎腳踏車,想保持平衡就得往前走。</span><br><span class="line"></span><br><span class="line">echo $0</span><br></pre></td></tr></table></figure><p>但我希望每次可以隨機挑遠一筆,就可使用 random 配上陣列</p><h3 id="Random-choice-And-Array"><a href="#Random-choice-And-Array" class="headerlink" title="Random choice And Array"></a>Random choice And Array</h3><p>先設定 quotes 變數為一組陣列<br><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">set quotes 'a' 'b' 'c'</span><br></pre></td></tr></table></figure></p><p>並使用 random choice 在裡面隨機取一筆資料出來</p><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">set quote (random choice $quotes)</span><br><span class="line"></span><br><span class="line">//result</span><br><span class="line">//a or b or c</span><br></pre></td></tr></table></figure><p>再換回我們原本的勵志語錄就會是這樣</p><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><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">set 0 擁有夢想只是一種智力,實現夢想才是一種能力。</span><br><span class="line">set 1 人生只有走出來的美麗,沒有等出來的輝煌。</span><br><span class="line">set 2 人生就像騎腳踏車,想保持平衡就得往前走。</span><br><span class="line"></span><br><span class="line">set quotes $0 $1 $2</span><br><span class="line">set quote (random choice $quotes)</span><br><span class="line">echo $quote</span><br></pre></td></tr></table></figure><h2 id="網路上爬語錄"><a href="#網路上爬語錄" class="headerlink" title="網路上爬語錄"></a>網路上爬語錄</h2><p>如果想抓網路上的語錄,但是很多筆該怎麼辦?</p><p>像是這個網站:<a href="http://mingyanjiaju.org/juzi/jingdianduanju/2014/1011/847.html" target="_blank" rel="noopener">http://mingyanjiaju.org/juzi/jingdianduanju/2014/1011/847.html</a></p><p>可以觀察 fish shell 的程式碼都有固定的 pattern,因此我使用 Node.js 來將這些複製下來的語錄轉成 fish shell 程式碼樣子</p><h3 id="複製文章內容並貼到-data-txt-檔"><a href="#複製文章內容並貼到-data-txt-檔" class="headerlink" title="複製文章內容並貼到 data.txt 檔"></a>複製文章內容並貼到 data.txt 檔</h3><p><img src="https://i.imgur.com/Bci2bgi.png" alt=""></p><h3 id="Node-js-讀取檔案並格式化樣式"><a href="#Node-js-讀取檔案並格式化樣式" class="headerlink" title="Node.js 讀取檔案並格式化樣式"></a>Node.js 讀取檔案並格式化樣式</h3><p>創立 index.js 並加入以下內容<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> fs = <span class="built_in">require</span>(<span class="string">'fs'</span>);</span><br><span class="line"></span><br><span class="line">fs.readFile(<span class="string">'data.txt'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">err, data</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (err) <span class="keyword">throw</span> err;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> array = data.toString().split(<span class="string">"\n"</span>);</span><br><span class="line"> <span class="keyword">let</span> str = <span class="string">'set xxx'</span></span><br><span class="line"> <span class="keyword">for</span>(i <span class="keyword">in</span> array) {</span><br><span class="line"> <span class="keyword">if</span>(array[i]){</span><br><span class="line"> <span class="keyword">if</span>(i < <span class="number">18</span>){</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`set <span class="subst">${i}</span> <span class="subst">${array[i].slice(<span class="number">2</span>)}</span>`</span>);</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(i < <span class="number">198</span>){</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`set <span class="subst">${i}</span> <span class="subst">${array[i].slice(<span class="number">3</span>)}</span>`</span>);</span><br><span class="line"> }<span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`set <span class="subst">${i}</span> <span class="subst">${array[i].slice(<span class="number">4</span>)}</span>`</span>);</span><br><span class="line"> }</span><br><span class="line"> str = <span class="string">`<span class="subst">${str}</span> $<span class="subst">${i}</span>`</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">console</span>.log(str);</span><br><span class="line">});</span><br></pre></td></tr></table></figure></p><p>在 terminal 執行 <code>node index.js</code> 可看到<br><img src="https://i.imgur.com/AQ4xPMJ.png" alt=""></p><p>我們就可以直接將它貼到 <code>~/.config/fish/config.fish</code> 裡面</p><h2 id="結果"><a href="#結果" class="headerlink" title="結果"></a>結果</h2><p><img src="https://media.giphy.com/media/BMPTpk1o0e5b0wPph0/giphy.gif" alt=""></p>]]></content>
<tags>
<tag> Shell </tag>
</tags>
</entry>
<entry>
<title>Fish Shell 起手式</title>
<link href="/2018/06/29/shell/fish-shell-startup/"/>
<url>/2018/06/29/shell/fish-shell-startup/</url>
<content type="html"><![CDATA[<h1 id="Fish-Shell-起手式"><a href="#Fish-Shell-起手式" class="headerlink" title="Fish Shell 起手式"></a>Fish Shell 起手式</h1><h2 id="查看shell"><a href="#查看shell" class="headerlink" title="查看shell"></a>查看shell</h2><p>先使用指令看自己用哪個 <code>shell</code><br><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">echo $SHELL</span><br></pre></td></tr></table></figure></p><p><img src="https://i.imgur.com/vau74Hz.png" alt=""></p><p>可以看到目前我使用 zsh<br>那麽就來安裝 fish 吧!!</p><h2 id="Install"><a href="#Install" class="headerlink" title="Install"></a>Install</h2><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">brew install fish</span><br></pre></td></tr></table></figure><p>灌好之後就可以在 terminal 執行 fish 將 <code>zsh shell</code> 轉成 <code>fish shell</code></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">fish</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/9YQP9xZ.png" alt=""></p><p>可以看到成功的轉成 fish</p><h2 id="Set-Default"><a href="#Set-Default" class="headerlink" title="Set Default"></a>Set Default</h2><p>我不想要每次打開都執行一次 <code>fish</code> 所以我們來將他設定成 default</p><p>使用 <code>chsh -s <shell 路徑></code></p><p>在這之前我們先看看 <code>fish</code> 的路徑在哪裡</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">which fish</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/lJMvNUE.png" alt=""></p><p>知道之後就來設定了</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">chsh -s /usr/local/bin/fish</span><br></pre></td></tr></table></figure><p>其實可以有更方便方法</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">chsh -s `which fish`</span><br></pre></td></tr></table></figure><p>有可能會發生</p><h3 id="non-standard-shell"><a href="#non-standard-shell" class="headerlink" title="non-standard shell"></a><code>non-standard shell</code></h3><p><img src="https://i.imgur.com/djUctIo.png" alt=""></p><p>這時候你要去 <code>/etc</code> 底下的 shells 設定(記得使用sudo,避免 shells 檔沒有 write 權限)</p><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">cd /etc</span><br><span class="line">sudo vim shells</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/Zp2KOxn.png" alt=""></p><p>加上 <code>/usr/local/bin/fish</code> 這行之後重開 <code>terminal</code></p><h3 id="no-changes-made"><a href="#no-changes-made" class="headerlink" title="no changes made"></a><code>no changes made</code></h3><p>可參考這篇 <a href="https://apple.stackexchange.com/questions/88278/change-default-shell-from-bash-to-zsh" target="_blank" rel="noopener">change default shell</a></p><h3 id="當上述兩個問題解決後在使用"><a href="#當上述兩個問題解決後在使用" class="headerlink" title="當上述兩個問題解決後在使用"></a>當上述兩個問題解決後在使用</h3><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">chsh -s `which fish`</span><br></pre></td></tr></table></figure><p>之後打開 <code>terminal</code> 預設就會使用 <code>fish shell</code> 了</p><h2 id="fisherman"><a href="#fisherman" class="headerlink" title="fisherman"></a>fisherman</h2><blockquote><p>The fish-shell plugin manager</p></blockquote><p>fisherman 是 fish-shell plugin的管理者</p><p>你可能發現我的 fish-shell 也有著漂亮的箭頭,是因為使用 fisherman 來設定了 agnoster 主題 (原本的 zsh 也有這個主題設定)</p><h3 id="安裝-fisherman"><a href="#安裝-fisherman" class="headerlink" title="安裝 fisherman"></a>安裝 fisherman</h3><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">curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs https://git.io/fisher</span><br></pre></td></tr></table></figure><h3 id="安裝主題"><a href="#安裝主題" class="headerlink" title="安裝主題"></a>安裝主題</h3><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">fisher install hauleth/agnoster</span><br></pre></td></tr></table></figure><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">agnoster powerline</span><br></pre></td></tr></table></figure><h2 id="參考資源"><a href="#參考資源" class="headerlink" title="參考資源"></a>參考資源</h2><p><a href="https://apple.stackexchange.com/questions/88278/change-default-shell-from-bash-to-zsh" target="_blank" rel="noopener">login shell</a></p><p><a href="https://stackoverflow.com/questions/28444740/how-to-use-vi-mode-in-fish-shell" target="_blank" rel="noopener">fish vim mode</a></p><p><a href="https://askubuntu.com/questions/26439/how-do-i-set-fish-as-the-default-shell" target="_blank" rel="noopener">set default shell</a></p><p><a href="https://github.com/fisherman/fisherman" target="_blank" rel="noopener">fisherman</a></p><p><a href="https://github.com/hauleth/agnoster" target="_blank" rel="noopener">fisherman agnoster</a></p>]]></content>
<tags>
<tag> Shell </tag>
</tags>
</entry>
<entry>
<title>Payload 的故事</title>
<link href="/2018/06/23/mix/pyload-story/"/>
<url>/2018/06/23/mix/pyload-story/</url>
<content type="html"><![CDATA[<h1 id="Payload-的故事"><a href="#Payload-的故事" class="headerlink" title="Payload 的故事"></a>Payload 的故事</h1><h2 id="Prerequisite"><a href="#Prerequisite" class="headerlink" title="Prerequisite"></a>Prerequisite</h2><p>通常在一段訊息中區分為:</p><ol><li>使用者感興趣的部分</li><li>輔助支持的部分</li></ol><h2 id="origin"><a href="#origin" class="headerlink" title="origin"></a>origin</h2><p>Payload 一詞來自交通運輸行業,假如一台油罐車可以運二十桶的油(使用者感興趣的部分),但運輸途中駕駛、車子本身耗油、油罐、綁繩……等等都是成本(輔助支持的部分),但是通常客戶只關心那二十桶油並且只想付那二十桶錢</p><p>payload 後來就泛指使用者感興趣部分</p><h2 id="Web-Service-例子"><a href="#Web-Service-例子" class="headerlink" title="Web Service 例子"></a>Web Service 例子</h2><p>從一個 Web Server Call Api 可能會拿到以下的訊息<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"status"</span>:<span class="string">"OK"</span>,<span class="comment">//(輔助支持的部分)</span></span><br><span class="line"> <span class="string">"data"</span>:</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"message"</span>:<span class="string">"Hello, world!"</span> <span class="comment">//(使用者感興趣的部分)</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>我們真正“有興趣的部分”是:<code>message:"Hello, world!"</code></p><h2 id="變數命名"><a href="#變數命名" class="headerlink" title="變數命名"></a>變數命名</h2><p>因此當發送 POST PUT …… 等 API 時,常會有人將要帶入 <code>body</code> 的資料變數命名為 <code>payload</code></p><p>打開 Browser dev Tool 的 Network 查看,也會發現瀏覽器也將他們稱作 Payload</p><p><img src="https://i.imgur.com/xUmq4Am.png" alt=""></p><h2 id="資料來源"><a href="#資料來源" class="headerlink" title="資料來源"></a>資料來源</h2><p><a href="https://softwareengineering.stackexchange.com/questions/158603/what-does-the-term-payload-mean-in-programming" target="_blank" rel="noopener">https://softwareengineering.stackexchange.com/questions/158603/what-does-the-term-payload-mean-in-programming</a></p>]]></content>
<tags>
<tag> trivia </tag>
</tags>
</entry>
<entry>
<title>Mobile 端與 Window 端開發的差別</title>
<link href="/2018/06/07/mix/mobile-window-develop-different/"/>
<url>/2018/06/07/mix/mobile-window-develop-different/</url>
<content type="html"><![CDATA[<h1 id="Mobile-端與-Window-端開發的差別"><a href="#Mobile-端與-Window-端開發的差別" class="headerlink" title="Mobile 端與 Window 端開發的差別"></a>Mobile 端與 Window 端開發的差別</h1><h2 id="1-Web-In-App"><a href="#1-Web-In-App" class="headerlink" title="1. Web In App"></a>1. Web In App</h2><ul><li>Window 端:需考慮不同瀏覽器可能會有不同的使用效果,因為個別使用了不同的 Rendering Engine</li><li>Mobile 端:除了不同瀏覽器之外,要注意網站開啟的方式是不是使用 WebView (Web In App),WebView 根據 Rendering Engine 來打造的一個模擬瀏覽器環境,因此不能保證所有功能都有實作上去,最常見的就是從 Line 開網頁,網頁就壞了</li></ul><h2 id="2-事件處理"><a href="#2-事件處理" class="headerlink" title="2. 事件處理"></a>2. 事件處理</h2><ul><li>window 端:因為是滑鼠操作關係所以會用 hover 來控制事件發生後的反應</li><li>Mobile 端:沒有滑鼠則是使用手指觸碰,因此需考慮 touch event</li></ul><h2 id="3-內容組織"><a href="#3-內容組織" class="headerlink" title="3. 內容組織"></a>3. 內容組織</h2><p>我們都知道手機與桌機一次能呈現的畫面大小不同,因此在設計內容及動線時,需考慮到客戶的使用情況,而非將頁面都塞得滿滿。</p><p>通常桌機會以水平排列為主,手機端則會是垂直排列</p><h2 id="4-效能網路速度考量"><a href="#4-效能網路速度考量" class="headerlink" title="4. 效能網路速度考量"></a>4. 效能網路速度考量</h2><p>手機端效能及網路速度差異較大,在設計mobile端時,考量到使用者等待資源載入及畫面反應時間,需做些效能優化或是移除非必要但負載較大的功能。</p>]]></content>
<tags>
<tag> HTML </tag>
<tag> JS </tag>
</tags>
</entry>
<entry>
<title>Wooden Puzzle Block 遊戲實作</title>
<link href="/2018/06/05/mix/wooden-puzzle-block/"/>
<url>/2018/06/05/mix/wooden-puzzle-block/</url>
<content type="html"><![CDATA[<h1 id="Wooden-Puzzle-Block-遊戲實作"><a href="#Wooden-Puzzle-Block-遊戲實作" class="headerlink" title="Wooden Puzzle Block 遊戲實作"></a>Wooden Puzzle Block 遊戲實作</h1><h2 id="遊戲介紹"><a href="#遊戲介紹" class="headerlink" title="遊戲介紹"></a>遊戲介紹</h2><p><a href="https://www.youtube.com/watch?v=bpSTRpy9qYo&t=649s" target="_blank" rel="noopener">Youtube</a></p><h2 id="開發過程"><a href="#開發過程" class="headerlink" title="開發過程"></a>開發過程</h2><h3 id="1-畫出遊戲的版面"><a href="#1-畫出遊戲的版面" class="headerlink" title="1. 畫出遊戲的版面"></a>1. 畫出遊戲的版面</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><div class="frame"></span><br><span class="line"> <div class="row"></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> <div class="col"></div></span><br><span class="line"> </div></span><br><span class="line"> ....總共有10個row 100個col</span><br><span class="line"></div></span><br></pre></td></tr></table></figure><p>套上CSS</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.frame</span>{</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">2em</span> auto;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.row</span>{</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">50px</span>;</span><br><span class="line"> <span class="attribute">display</span>: flex;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.col</span>{</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">50px</span>;</span><br><span class="line"> <span class="attribute">outline</span>: <span class="number">1px</span> solid red;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>畫面效果<br><img src="https://i.imgur.com/8qItSTs.png" alt=""></p><h3 id="2-創建table"><a href="#2-創建table" class="headerlink" title="2. 創建table"></a>2. 創建table</h3><p>雖然畫出畫面,不過到時候我們會需要有個二維陣列,用來記錄每個格子的狀態,像是:狀態0畫出白色,狀態1畫出藍色</p><figure class="highlight javascript"><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">let</span> table = []</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> y = <span class="number">0</span> ; y < <span class="number">10</span> ; y++){</span><br><span class="line"> table[y] = []</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> x = <span class="number">0</span> ; x < <span class="number">10</span> ; x++){</span><br><span class="line"> table[y][x] = <span class="number">0</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我們來 <code>console.table(table)</code> 看看結果<br><img src="https://i.imgur.com/WMJcPk8.png" alt=""></p><h3 id="3-宣告各種方塊的資料,並且畫在畫面上"><a href="#3-宣告各種方塊的資料,並且畫在畫面上" class="headerlink" title="3. 宣告各種方塊的資料,並且畫在畫面上"></a>3. 宣告各種方塊的資料,並且畫在畫面上</h3><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> shape = [</span><br><span class="line"> [</span><br><span class="line"> [<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>]</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>]</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>]</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>]</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> [<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>]</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>]</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>],</span><br><span class="line"> [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>]</span><br><span class="line"> ]</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>做好資料後我們就可以畫在瀏覽器上,首先在html加上<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><div class="pendingBox"></span><br><span class="line"> <div class="pendingOne"></span><br><span class="line"></span><br><span class="line"> </div></span><br><span class="line"> <div class="pendingTwo"></span><br><span class="line"></span><br><span class="line"> </div></span><br><span class="line"> <div class="pendingThree"></span><br><span class="line"></span><br><span class="line"> </div></span><br><span class="line"></div></span><br></pre></td></tr></table></figure></p><p>CSS 加上<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.pendingBox</span>{</span><br><span class="line"> <span class="attribute">position</span>: relative;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.pendingOne</span>{</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">left</span>:<span class="number">0px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.pendingTwo</span>{</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">left</span>: <span class="number">300px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.pendingThree</span>{</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">left</span>: <span class="number">600px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">/* 填滿的style */</span></span><br><span class="line"><span class="selector-class">.blue</span>{</span><br><span class="line"> <span class="attribute">background-color</span>: blue;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>pendingBox是個容器負責放那三個準備被使用者拖動的方塊<br>pedningOne~Three負責當作方塊節點,讓我們將資料配合DOM製作上去<br>創一個負責繪製Box的function<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//三個方塊的對照表,我們要知道 one two three分別產生了哪種 shpae</span></span><br><span class="line"><span class="keyword">var</span> pendingBoxComparisonTable = {}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createPendingBox</span>(<span class="params">pendingBox</span>) </span>{</span><br><span class="line"> <span class="comment">//隨機產生 shape 的編號</span></span><br><span class="line"> <span class="keyword">let</span> randNum = <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * (shape.length<span class="number">-1</span> - <span class="number">0</span> + <span class="number">1</span>)) + <span class="number">0</span>;</span><br><span class="line"> <span class="comment">// 放.row</span></span><br><span class="line"> <span class="keyword">let</span> nodeY</span><br><span class="line"> <span class="comment">// 放.row 底下的.col</span></span><br><span class="line"> <span class="keyword">let</span> nodeX</span><br><span class="line"> shape[randNum].some(<span class="function">(<span class="params">row, y</span>) =></span> {</span><br><span class="line"> nodeY = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> nodeY.classList.add(<span class="string">'row'</span>)</span><br><span class="line"> row.some(<span class="function">(<span class="params">value, x</span>) =></span> {</span><br><span class="line"> nodeX = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> nodeX.classList.add(<span class="string">'col'</span>)</span><br><span class="line"> <span class="keyword">if</span>(value){nodeX.classList.add(<span class="string">'blue'</span>)}</span><br><span class="line"> nodeY.appendChild(nodeX)</span><br><span class="line"></span><br><span class="line"> <span class="built_in">document</span>.querySelector(<span class="string">`.<span class="subst">${pendingBox}</span>`</span>).appendChild(nodeY)</span><br><span class="line"> })</span><br><span class="line"> })</span><br><span class="line"> pendingBoxComparisonTable[pendingBox] = shape[randNum]</span><br><span class="line">}</span><br><span class="line">createPendingBox(<span class="string">'pendingOne'</span>)</span><br><span class="line">createPendingBox(<span class="string">'pendingTwo'</span>)</span><br><span class="line">createPendingBox(<span class="string">'pendingThree'</span>)</span><br></pre></td></tr></table></figure></p><h4 id="畫面效果"><a href="#畫面效果" class="headerlink" title="畫面效果"></a>畫面效果</h4><p><img src="https://i.imgur.com/fHFrUou.png" alt=""><br>下面多了三個隨機方塊</p><h3 id="4-處理拖動事件"><a href="#4-處理拖動事件" class="headerlink" title="4. 處理拖動事件"></a>4. 處理拖動事件</h3><p>我們要讓Box自由自在的拖動,並且畫到表格上方</p><h4 id="滑鼠按下去"><a href="#滑鼠按下去" class="headerlink" title="滑鼠按下去"></a>滑鼠按下去</h4><p>三個 Box 分別監聽 <code>mousedown event</code> ,當按下去時記下他們起始位置,並且設定 <code>selectedBox</code> 讓等等的 mousemove 事件知道該移動哪個 BOX 的 <code>top</code> <code>left</code></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> pendingOne = <span class="built_in">document</span>.querySelector(<span class="string">'.pendingOne'</span>)</span><br><span class="line"><span class="keyword">var</span> pendingTwo = <span class="built_in">document</span>.querySelector(<span class="string">'.pendingTwo'</span>)</span><br><span class="line"><span class="keyword">var</span> pendingThree = <span class="built_in">document</span>.querySelector(<span class="string">'.pendingThree'</span>)</span><br><span class="line"><span class="comment">// 設定滑鼠正在點下去的狀態(還沒放開)</span></span><br><span class="line"><span class="keyword">var</span> isMouseDown = <span class="literal">false</span></span><br><span class="line"><span class="keyword">var</span> startX = <span class="number">0</span>, startY = <span class="number">0</span>, endX = <span class="number">0</span>, endY = <span class="number">0</span></span><br><span class="line"><span class="keyword">var</span> selectedBox = <span class="string">''</span></span><br><span class="line">pendingOne.addEventListener(<span class="string">'mousedown'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> isMouseDown = <span class="literal">true</span></span><br><span class="line"> startX = e.clientX</span><br><span class="line"> startY = e.clientY</span><br><span class="line"> selectedBox = <span class="string">'pendingOne'</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">pendingTwo.addEventListener(<span class="string">'mousedown'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> isMouseDown = <span class="literal">true</span></span><br><span class="line"> startX = e.clientX</span><br><span class="line"> startY = e.clientY</span><br><span class="line"> selectedBox = <span class="string">'pendingTwo'</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">pendingThree.addEventListener(<span class="string">'mousedown'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> isMouseDown = <span class="literal">true</span></span><br><span class="line"> startX = e.clientX</span><br><span class="line"> startY = e.clientY</span><br><span class="line"> selectedBox = <span class="string">'pendingThree'</span></span><br><span class="line">})</span><br></pre></td></tr></table></figure><h4 id="滑鼠拖動"><a href="#滑鼠拖動" class="headerlink" title="滑鼠拖動"></a>滑鼠拖動</h4><p>滑鼠移動時根據他<code>移動時的終點</code>,扣掉一開始按下去的距離就是我們所要設定的<code>left</code> <code>top</code></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">document</span>.addEventListener(<span class="string">'mousemove'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span>(isMouseDown){</span><br><span class="line"> endX = e.clientX</span><br><span class="line"> endY = e.clientY</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> offsetX = endX - startX</span><br><span class="line"> <span class="keyword">let</span> offsetY = endY - startY</span><br><span class="line"> <span class="keyword">let</span> pendingBox = <span class="built_in">document</span>.querySelector(<span class="string">`.<span class="subst">${selectedBox}</span>`</span>);</span><br><span class="line"> <span class="keyword">switch</span> (selectedBox) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'pendingOne'</span>:</span><br><span class="line"> offsetX += <span class="number">0</span></span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'pendingTwo'</span>:</span><br><span class="line"> offsetX += <span class="number">300</span></span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'pendingThree'</span>:</span><br><span class="line"> offsetX += <span class="number">600</span></span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> pendingBox.style.left = offsetX + <span class="string">"px"</span></span><br><span class="line"> pendingBox.style.top = offsetY + <span class="string">"px"</span></span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h4 id="畫面效果-1"><a href="#畫面效果-1" class="headerlink" title="畫面效果"></a>畫面效果</h4><p><img src="https://media.giphy.com/media/BCg5D6bDs3h48AhqaT/giphy.gif" alt=""></p><h4 id="滑鼠放下瞬間"><a href="#滑鼠放下瞬間" class="headerlink" title="滑鼠放下瞬間"></a>滑鼠放下瞬間</h4><p>這部分的邏輯會很多,首先我會想知道 Box 最後是在哪個座標被放下來的,並且對應到 table 在哪</p><p>下圖中有 A B 兩點,我只要 B 的 x y 扣掉 A 的 x y 就可以知道方塊被拖進來會相應到什麼位置</p><p><img src="https://scontent.fkhh1-2.fna.fbcdn.net/v/t1.15752-9/s2048x2048/34474996_1785874701495978_2263218512522641408_n.jpg?_nc_cat=0&oh=4df5d3c6a44b17fc4026f41c010404b7&oe=5BBEBA0C" alt=""></p><p>因為我的表格中的每一格都是50px,因此假設最後 Bx - Ax && By - Bx 算出來是 75 55 ,將他們個別除以 50 就知道他們墜落在表格中哪個部分,不過我會再加上25作為緩衝區域,我們來看下面的圖</p><p><img src="https://scontent.fkhh1-2.fna.fbcdn.net/v/t1.15752-9/34529458_1785880891495359_451174563414278144_n.jpg?_nc_cat=0&oh=d2750ca88ca124f29d56ff0c631bf763&oe=5B7BA46D" alt=""></p><p>雖然他的左上角靠在表格(0,0),不過事實上他更靠近中間,應該要算在中間</p><figure class="highlight javascript"><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="built_in">document</span>.addEventListener(<span class="string">'mouseup'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span>(isMouseDown){</span><br><span class="line"> isMouseDown = <span class="literal">false</span></span><br><span class="line"> <span class="keyword">let</span> pendingBox = <span class="built_in">document</span>.querySelector(<span class="string">`.<span class="subst">${selectedBox}</span>`</span>);</span><br><span class="line"> <span class="keyword">let</span> posX = <span class="built_in">Math</span>.floor(((pendingBox.getBoundingClientRect().left - frameX) + <span class="number">25</span>) / <span class="number">50</span>)</span><br><span class="line"> <span class="keyword">let</span> posY = <span class="built_in">Math</span>.floor(((pendingBox.getBoundingClientRect().top - frameY) + <span class="number">25</span>) / <span class="number">50</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>取到該放的位置之後就可以將他畫上去了</p><p>話的時候必須注意</p><ul><li>有沒有超過邊界</li><li>位置上是否已經有東西</li></ul><p>最後如果話成功就回傳 success<br><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> result = fillTable(pendingBoxComparisonTable[selectedBox],{<span class="attr">x</span>:posX,<span class="attr">y</span>:posY})</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fillTable</span>(<span class="params">box,point</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> fillGridList = []</span><br><span class="line"> <span class="keyword">let</span> outOfBound = <span class="literal">false</span></span><br><span class="line"> <span class="keyword">let</span> boxFillEmpty = <span class="literal">true</span></span><br><span class="line"> box.some(<span class="function">(<span class="params">row, y</span>) =></span> {</span><br><span class="line"> row.some(<span class="function">(<span class="params">value, x</span>) =></span> {</span><br><span class="line"> <span class="keyword">if</span>(value === <span class="number">1</span>){</span><br><span class="line"> <span class="keyword">if</span>((y+point.y) >= <span class="number">0</span> && (x+point.x) >= <span class="number">0</span> &&</span><br><span class="line"> (y+point.y) < <span class="number">10</span> && ((x+point.x) < <span class="number">10</span>)){</span><br><span class="line"> <span class="keyword">if</span>(checkGridEmpty(x+point.x,y+point.y)){</span><br><span class="line"> <span class="keyword">let</span> count = (y+point.y)*<span class="number">10</span> + (x+point.x)</span><br><span class="line"> grid = {</span><br><span class="line"> x:x+point.x,</span><br><span class="line"> y:y+point.y,</span><br><span class="line"> count:count</span><br><span class="line"> }</span><br><span class="line"> fillGridList.push(grid)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> boxFillEmpty = <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> outOfBound = <span class="literal">true</span></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 class="keyword">if</span>(!outOfBound){</span><br><span class="line"> <span class="keyword">if</span>(boxFillEmpty){</span><br><span class="line"> fillGridList.some(<span class="function">(<span class="params">grid</span>)=></span>{</span><br><span class="line"> cols[grid.count].classList.add(<span class="string">'blue'</span>)</span><br><span class="line"> table[grid.y][grid.x] = <span class="number">1</span></span><br><span class="line"> })</span><br><span class="line"> <span class="keyword">return</span> <span class="string">'success'</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>如果回傳success我們需要先把畫成功的dom先砍了(因為他只是畫面效果),接者檢查是否有直行或橫列填滿一條了</p><p>getFullLine() 會找到 x y 軸有哪些是滿的,結果像是這樣<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{<span class="attr">x</span>:[<span class="number">2</span>,<span class="number">5</span>,<span class="number">6</span>] y:[<span class="number">1</span>,<span class="number">3</span>,<span class="number">7</span>]}</span><br></pre></td></tr></table></figure></p><p>接著再根據這些index去把他們的狀態都改成0並且讓他的style取消blue<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(result === <span class="string">'success'</span>){</span><br><span class="line"> removePendingBoxDom(selectedBox)</span><br><span class="line"> <span class="comment">// createPendingBox(selectedBox)</span></span><br><span class="line"> clearFullLine(getFullLine())</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">removePendingBoxDom</span>(<span class="params">selectedBox</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> removeDom = <span class="built_in">document</span>.querySelector(<span class="string">`.<span class="subst">${selectedBox}</span>`</span>)</span><br><span class="line"> <span class="keyword">while</span>(removeDom.hasChildNodes()){</span><br><span class="line"> removeDom.removeChild(removeDom.lastChild)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">clearFullLine</span>(<span class="params">fullLine</span>) </span>{</span><br><span class="line"> fullLine.xFullLine.some(<span class="function">(<span class="params">x</span>)=></span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span> ; i < <span class="number">10</span> ; i++){</span><br><span class="line"> table[x][i] = <span class="number">0</span></span><br><span class="line"> cols[x*<span class="number">10</span>+i].classList.remove(<span class="string">'blue'</span>)</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line"> fullLine.yFullLine.some(<span class="function">(<span class="params">y</span>)=></span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span> ; i < <span class="number">10</span> ; i++){</span><br><span class="line"> table[i][y] = <span class="number">0</span></span><br><span class="line"> cols[y+i*<span class="number">10</span>].classList.remove(<span class="string">'blue'</span>)</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>最後若是 pendingOne~three 都成功填滿了(代表也都被移除節點了),則要另外再加入新的三個 Box</p><figure class="highlight javascript"><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>(pendingOne.childElementCount === <span class="number">0</span> &&</span><br><span class="line"> pendingTwo.childElementCount === <span class="number">0</span> &&</span><br><span class="line"> pendingThree.childElementCount === <span class="number">0</span>){</span><br><span class="line"> createPendingBox(<span class="string">'pendingOne'</span>)</span><br><span class="line"> createPendingBox(<span class="string">'pendingTwo'</span>)</span><br><span class="line"> createPendingBox(<span class="string">'pendingThree'</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="最終畫面"><a href="#最終畫面" class="headerlink" title="最終畫面"></a>最終畫面</h2><p><img src="https://media.giphy.com/media/kPCaLOf9w5znh21dK2/giphy.gif" alt=""></p><h2 id="實作結果"><a href="#實作結果" class="headerlink" title="實作結果"></a>實作結果</h2><p><a href="https://curt6815463.github.io/woodenPuzzleBlock/">https://curt6815463.github.io/woodenPuzzleBlock/</a></p>]]></content>
<tags>
<tag> HTML </tag>
<tag> CSS </tag>
<tag> JS </tag>
</tags>
</entry>
<entry>
<title>前端路由</title>
<link href="/2018/06/01/mix/frontend-route/"/>
<url>/2018/06/01/mix/frontend-route/</url>
<content type="html"><![CDATA[<h1 id="前端路由"><a href="#前端路由" class="headerlink" title="前端路由"></a>前端路由</h1><h2 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h2><blockquote><p>在網頁中,路由代表了網址( url )與頁面呈現之間的關係。</p></blockquote><p>例如:在網址列輸入</p><ul><li><a href="https://curt6815463.github.io/">https://curt6815463.github.io/</a></li><li><a href="https://curt6815463.github.io/tags/">https://curt6815463.github.io/tags/</a></li></ul><p>會看到不同的畫面,因此可以說</p><ul><li>路由為<code>/</code>時,顯示文章列表畫面</li><li>路由為<code>/tags</code>時,顯示有tag分類的文章列表</li></ul><h2 id="前端後端?"><a href="#前端後端?" class="headerlink" title="前端後端?"></a>前端後端?</h2><p>在講前端路由之前,瑞凡你知道<code>前後端</code>是什麼東西嗎?</p><p>在 <code>ajax</code> 發明之前,事實上網頁沒有前後端之分,當使用者要瀏覽網頁時,都是從後端吐一份被整理好的檔案( html ),這裡所謂整理好意思是:我想要呈現在瀏覽器畫面的資料,已經在後端直接跟資料庫溝通,並且渲染上去</p><p>圖解來說大概是這樣:<br><img src="https://i.imgur.com/IMxhNhG.png" alt=""></p><h3 id="問題點"><a href="#問題點" class="headerlink" title="問題點"></a>問題點</h3><ul><li>使用者每次只要想換頁面,就必須跟後端再發一次請求,然後頁面就會整個重新整理並且吃到新的HTML/CSS,</li><li>後端要負責 1.跟資料庫溝通 2.處理商業邏輯 3.畫面渲染邏輯</li></ul><h3 id="AJAX"><a href="#AJAX" class="headerlink" title="AJAX"></a>AJAX</h3><p>AJAX是JavaScript的網頁非同步請求技術,簡單來說我發出去的請求,只跟後端拿必要的資料,並且也不會讓網頁重新整理</p><h3 id="分離吧!!"><a href="#分離吧!!" class="headerlink" title="分離吧!!"></a>分離吧!!</h3><p>在AJAX出來之後,就有人開始思考把處理資料的部分切一邊,處理畫面的切一邊,也就是現在所謂前端,那麼需要串接畫面邏輯的資料就靠AJAX去達成,後端負責出資料就好</p><h3 id="前後端的架構好處"><a href="#前後端的架構好處" class="headerlink" title="前後端的架構好處"></a>前後端的架構好處</h3><ul><li>以前的後端就不用處理太多東西</li><li>前端使用AJAX可以讓畫面不必重整,增加使用者體驗</li><li>每次只取需要的資料,可減少 server 的 loading</li></ul><p>圖畫起來會像是:</p><p><img src="https://i.imgur.com/tmCoFMi.png" alt=""></p><h2 id="回到前端路由"><a href="#回到前端路由" class="headerlink" title="回到前端路由"></a>回到前端路由</h2><p>由上敘述可以得知,如果今天使用後端路由,每當我更換 route 那勢必整個頁面都會重新載入,那麼當在前端使用路由技術配上ajax,就可製造出:<code>沒有整理頁面但是頁面資料卻有變換的效果</code>,對使用者體驗來說是大大加分</p><h2 id="如何實作前端路由?"><a href="#如何實作前端路由?" class="headerlink" title="如何實作前端路由?"></a>如何實作前端路由?</h2><p>要在前端更換網址卻又不啟動重新整理的方式有兩個</p><h3 id="1-使用hash"><a href="#1-使用hash" class="headerlink" title="1. 使用hash #"></a>1. 使用<code>hash #</code></h3><p>可在url加上符號<code>#</code>,像是在 <code>https://curt6815463.github.io/</code> 加上 <code>#123</code> 變成<br><code>https://curt6815463.github.io/#123</code> 並不會讓頁面重新整理,而我們可以使用 <code>hashchange</code> 去監聽事件,並在裡面做出畫面改變</p><figure class="highlight javascript"><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">window</span>.addEventListener(<span class="string">"hashchange"</span>, () => {</span><br><span class="line"> 改變畫面</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>可使用兩種方式控制url</p><ol><li><p>使用 HTML tag <code><a></code></p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><a href="#123">to 123</a></span><br></pre></td></tr></table></figure></li><li><p>使用location.hash</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">location.hash=<span class="string">"#123"</span></span><br></pre></td></tr></table></figure></li></ol><h3 id="2-使用history-pushState-history-replaceState"><a href="#2-使用history-pushState-history-replaceState" class="headerlink" title="2. 使用history.pushState history.replaceState"></a>2. 使用<code>history.pushState</code> <code>history.replaceState</code></h3><p>HTML5在 <code>history</code> 中新增了兩個功能 <code>history.pushState</code> <code>history.replaceState</code>,它可以讓我們加入或修改歷史,但不會真的發出資源的請求</p><p>他們同樣都帶入三個參數(state object, title, URL),不過今天我們只要專注在第三個參數<code>URL</code>,另外兩個細節有興趣可參考<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState" target="_blank" rel="noopener">MDN</a></p><figure class="highlight javascript"><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">history.pushState(<span class="literal">null</span>,<span class="literal">null</span>,<span class="string">"a.html"</span>)</span><br><span class="line"></span><br><span class="line">history.replaceState(<span class="literal">null</span>,<span class="literal">null</span>,<span class="string">"b.html"</span>)</span><br></pre></td></tr></table></figure><p>所以當你改變畫面呈現方式時,就可以 call <code>pushState</code> or <code>replaceState</code>,造成使用者覺得好像有切換頁面的效果,不過他們兩個差別是什麼?</p><p>實測結果如下</p><p><img src="https://media.giphy.com/media/3Z1ppTua0q9wVIbCd8/giphy.gif" alt=""></p><p>可以發現點了四次 pushState 需要按四次上一頁才能會到 localhost:3333,但是如果 replaceState 點四次按一次上一頁就回到最原本頁面</p><p>replaceState 是修改目前的歷史紀錄,並不會像pushState創造一個新的</p><h2 id="參考資料"><a href="#參考資料" class="headerlink" title="參考資料"></a>參考資料</h2><ul><li><a href="https://developer.mozilla.org/zh-TW/docs/Web/API/History_API" target="_blank" rel="noopener">MDN</a></li><li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState" target="_blank" rel="noopener">MDN</a></li><li><a href="https://github.com/kaola-fed/blog/issues/137" target="_blank" rel="noopener">淺談前端路由</a></li></ul>]]></content>
<tags>
<tag> JS </tag>
</tags>
</entry>
<entry>
<title>關於瀏覽器的字型</title>
<link href="/2018/05/30/mix/about-browser-font/"/>
<url>/2018/05/30/mix/about-browser-font/</url>
<content type="html"><![CDATA[<h1 id="關於瀏覽器的字型"><a href="#關於瀏覽器的字型" class="headerlink" title="關於瀏覽器的字型"></a>關於瀏覽器的字型</h1><h2 id="在網頁中的應該使用奇數還是偶數的字體?為什麽呢?"><a href="#在網頁中的應該使用奇數還是偶數的字體?為什麽呢?" class="headerlink" title="在網頁中的應該使用奇數還是偶數的字體?為什麽呢?"></a>在網頁中的應該使用奇數還是偶數的字體?為什麽呢?</h2><p>通常在網頁上看到的字體大小都是偶數,像是12px 14px 16px,為什麼大家不喜歡用奇數的大小呢?</p><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><ul><li>字體渲染的時候可能會不對稱,像是<code>中</code>這個字,中間一條線畫下來平分兩邊,勢必有一邊會大點或小點</li><li>在過去window內建的宋體,一開始也只提供12px、14px、16px……等字型</li><li>通常設計師設計圖樣時會使用偶數字,所以到前端也是自然用偶數切版</li><li>偶數可以方便用相對的方式來改變字型大小,例如預設字體通常會用 16px,因為 16 可以除很多次 2 後還是整數</li></ul><h2 id="chrome-瀏覽器限制"><a href="#chrome-瀏覽器限制" class="headerlink" title="chrome 瀏覽器限制"></a>chrome 瀏覽器限制</h2><p>在 chrome 瀏覽器中, font-size 最小限制在12px,如果設定12以下都會被自動轉成12px,如果今天有這種需求話該如何解決?</p><h3 id="1-webkit-text-size-adjust-none"><a href="#1-webkit-text-size-adjust-none" class="headerlink" title="1. -webkit-text-size-adjust: none"></a>1. -webkit-text-size-adjust: none</h3><p>可以在 CSS 中設定<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">-webkit-text-size-adjust</span>: <span class="selector-tag">none</span></span><br></pre></td></tr></table></figure></p><p>不過這個屬性在 27.0 版之前才會 work</p><h3 id="2-transform-scale-0-7"><a href="#2-transform-scale-0-7" class="headerlink" title="2. transform:scale(0.7)"></a>2. transform:scale(0.7)</h3><p>使用CSS3的屬性 transform:scale()<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">transform</span><span class="selector-pseudo">:scale(0.7)</span>;</span><br></pre></td></tr></table></figure></p><p>不過他會以<code>區塊</code>為單位放大縮小,因此切版上需做些改變</p><h3 id="冷知識"><a href="#冷知識" class="headerlink" title="冷知識"></a>冷知識</h3><p>chrome的字體確實最小只能調到12px,不過嚴格說起來應該是:<code>最小只能呈現出畫面 100% 時 12px 的像素大小</code></p><p>圖中是畫面縮放100%時,文章列表字體為12px<br><img src="https://i.imgur.com/KRMPrWC.png" alt=""><br>如果使用<code>cmd +</code>將畫面放大到200%,把字體調成6px是會更小的!!!<br><img src="https://i.imgur.com/Zqi6y2p.png" alt=""></p><h2 id="瀏覽器字體單位"><a href="#瀏覽器字體單位" class="headerlink" title="瀏覽器字體單位"></a>瀏覽器字體單位</h2><p>瀏覽器字體的單位除了 px 還有 pt、em、rem,那麼 em 與 rem 差別是什麼呢?</p><h3 id="em"><a href="#em" class="headerlink" title="em"></a>em</h3><p>em 是依照父層的字體大小為基準,做等比例放大,例如</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><div class='father'></span><br><span class="line"> 父</span><br><span class="line"> <div class='children'></span><br><span class="line"> 子</span><br><span class="line"> </div></span><br><span class="line"></div></span><br></pre></td></tr></table></figure><figure class="highlight css"><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="selector-class">.father</span>{</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.children</span>{</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">1em</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>這時子層的實際大小就是 14px</p><h3 id="rem"><a href="#rem" class="headerlink" title="rem"></a>rem</h3><p>rem 則是不管在哪一層都會依照 <code>html tag</code> 為基準(應該說 root 層)做等比例放大,例如:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><html></span><br><span class="line"> <head></span><br><span class="line"> </head></span><br><span class="line"> <body></span><br><span class="line"> <div class='father'></span><br><span class="line"> 父</span><br><span class="line"> <div class='children'></span><br><span class="line"> 子</span><br><span class="line"> </div></span><br><span class="line"> </div></span><br><span class="line"> </body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">html</span>{</span><br><span class="line"><span class="attribute">font-size</span>: <span class="number">16px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.father</span>{</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.children</span>{</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">1em</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>子層會以root為基準,所以實際字型大小會是 16px</p><h2 id="參考資料"><a href="#參考資料" class="headerlink" title="參考資料"></a>參考資料</h2><p><a href="http://www.hexschool.com/2016/01/02/2016-08-08-em-vs-rem/" target="_blank" rel="noopener">六角</a></p><p><a href="https://blog.csdn.net/jian_xi/article/details/79346477" target="_blank" rel="noopener">jmin_coming</a></p>]]></content>
<tags>
<tag> HTML </tag>
<tag> CSS </tag>
</tags>
</entry>
<entry>
<title>Sinon.js 測試套件與測試替身(中)</title>
<link href="/2018/05/24/testing/sinon-beginner-2/"/>
<url>/2018/05/24/testing/sinon-beginner-2/</url>
<content type="html"><![CDATA[<h1 id="接續Sinon-js-測試套件與測試替身(中)"><a href="#接續Sinon-js-測試套件與測試替身(中)" class="headerlink" title="接續Sinon.js 測試套件與測試替身(中)"></a>接續Sinon.js 測試套件與測試替身(中)</h1><p>此篇 <code>接續Sinon.js 測試套件與測試替身(上)</code></p><h4 id="Stub"><a href="#Stub" class="headerlink" title="Stub"></a>Stub</h4><p>可以避免某些功能被呼叫,像是 ajax call,並且能控制 function 走向特定流程(EX:拋出錯誤)</p><h4 id="sinon文件上的-anonymous-function-示範"><a href="#sinon文件上的-anonymous-function-示範" class="headerlink" title="sinon文件上的 anonymous function 示範"></a>sinon文件上的 anonymous function 示範</h4><p><strong>withArgs</strong></p><p>設定stub要帶入的參數,搭配其後續動作<br><figure class="highlight javascript"><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">var</span> callback = sinon.stub();</span><br><span class="line">callback.withArgs(<span class="number">42</span>).returns(<span class="number">1</span>);</span><br><span class="line">callback.withArgs(<span class="number">1</span>).throws(<span class="string">"name"</span>);</span><br><span class="line"></span><br><span class="line">callback(); <span class="comment">// No return value, no exception</span></span><br><span class="line">callback(<span class="number">42</span>); <span class="comment">// Returns 1</span></span><br><span class="line">callback(<span class="number">1</span>); <span class="comment">// Throws Error("name")</span></span><br></pre></td></tr></table></figure></p><p>透過 <code>withArgs</code> 設定傳入的參數,並且決定他要傳出的結果為 <code>1</code> 或是 <code>error case</code></p><p> <strong>onCall</strong><br><figure class="highlight javascript"><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="keyword">var</span> callback = sinon.stub();</span><br><span class="line"> callback.onCall(<span class="number">0</span>).returns(<span class="number">1</span>);</span><br><span class="line"> callback.onCall(<span class="number">1</span>).returns(<span class="number">2</span>);</span><br><span class="line"> callback.returns(<span class="number">3</span>);</span><br><span class="line"></span><br><span class="line"> callback(); <span class="comment">// Returns 1</span></span><br><span class="line"> callback(); <span class="comment">// Returns 2</span></span><br><span class="line"> callback(); <span class="comment">// All following calls return 3</span></span><br></pre></td></tr></table></figure></p><p>透過 <code>onCall</code> 設定 function 被 call 幾次後會有什麼回傳,像是第一次 call 回傳 1,第二次為2</p><h4 id="已存在函示示範"><a href="#已存在函示示範" class="headerlink" title="已存在函示示範"></a>已存在函示示範</h4><p><strong>yields</strong> <code>stub.yields([arg1, arg2, ...])</code></p><p>如果stub有收到callback參數,用yields會直接call第一個callback函式</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">var myfun = {</span><br><span class="line"> fun1: function () {</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">function cb(data) {</span><br><span class="line"> console.log(data);</span><br><span class="line">}</span><br><span class="line">sinon.stub(myfun, "fun1").yields('callback arg1')</span><br><span class="line">myfun.fun1(cb) //印出'callback arg1'</span><br></pre></td></tr></table></figure><p>可以發現即使myfun裡的fun1沒有任何參數,還是可以通過,代表stub不會真的去call那個function</p><p><strong>yieldTo</strong> <code>stub.yieldsTo(property, [arg1, arg2, ...])</code></p><p>如果呼叫funtion時傳入一個object,可透過 <code>yeildsTo</code> 指定invoke某個function<br><figure class="highlight javascript"><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">sinon.stub(myfun, <span class="string">"fun1"</span>).yieldsTo(<span class="string">'shit'</span>,<span class="string">'shit arg'</span>)</span><br><span class="line">myfun.fun1({<span class="attr">shit</span>:<span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>{ <span class="comment">//印出shit arg</span></span><br><span class="line"> <span class="built_in">console</span>.log(data);</span><br><span class="line">}})</span><br></pre></td></tr></table></figure></p><p>到這邊都只是在瞭解語法,那我們來阻止 ajax call 真正的發生吧!!<br><strong>來stub jQuery 的 ajax call</strong></p><figure class="highlight javascript"><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">sinon.stub(jQuery, <span class="string">"ajax"</span>).yieldsTo(<span class="string">"success"</span>, <span class="string">"ajax arg"</span>);</span><br><span class="line"></span><br><span class="line"> jQuery.ajax({</span><br><span class="line"> success: <span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(data)</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line"> <span class="comment">//最後印出ajax arg</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>但是我幾乎都用promise方式來接成功或失敗呀!那就使用usingPromise</p><p><strong>usingPromise</strong> <code>stub.usingPromise(promiseLibrary)`</code></p><figure class="highlight javascript"><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">sinon.stub($,<span class="string">'ajax'</span>).usingPromise($.Deferred()).resolves(<span class="string">"baz"</span>)</span><br><span class="line">$.ajax(<span class="string">'123'</span>)</span><br><span class="line"> .done(<span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(data); <span class="comment">//baz</span></span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>如果測試要接上promise,首先我們必須知道它所使用的 Promise Library,查了一下 jQuery 才知道說原來他使用 defeered (使用.done連接)</p><p>只要使用jQuery.Deferred() 可以取得deferred object,所以就將它丟進usingPromise funtion 當參數</p><p>假如今天是使用預設的Promise,也就是使用 <code>.then</code> 串接,那<code>promiseLibrary</code>則要傳入 <code>Promise</code></p><p><strong>來把 .done 改成 .then</strong></p><figure class="highlight javascript"><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">sinon.stub($,<span class="string">'ajax'</span>).usingPromise(<span class="built_in">Promise</span>).resolves(<span class="string">"87"</span>)</span><br><span class="line">$.ajax(<span class="string">'123'</span>) <span class="comment">//印出87</span></span><br><span class="line"> .then(<span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(data);</span><br><span class="line"> })</span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> Testing </tag>
</tags>
</entry>
<entry>
<title>Sinon.js 測試套件與測試替身(上)</title>
<link href="/2018/05/22/testing/sinon-beginner-1/"/>
<url>/2018/05/22/testing/sinon-beginner-1/</url>
<content type="html"><![CDATA[<h1 id="Sinon-js-測試套件與測試替身(上)"><a href="#Sinon-js-測試套件與測試替身(上)" class="headerlink" title="Sinon.js 測試套件與測試替身(上)"></a>Sinon.js 測試套件與測試替身(上)</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Sinon.js 是一套提供給JavaScipt使用的Testing Plugins,如果有先前有看過JavaScript 中的測試工具怎麼分類?文章,那你會大概瞭解測試套件在測試中扮演什麼角色</p><h2 id="Test-Doubles"><a href="#Test-Doubles" class="headerlink" title="Test Doubles"></a>Test Doubles</h2><p>首先必須先知道 − Test Double (測試替身),它可以在測試中代替那些會造成我們不便的 funciton</p><blockquote><p>Test Double類似於電影中一些危險動作,導演們會請專業替身代替影星們去執行這些事情。</p></blockquote><h3 id="Test-Doubles-目的"><a href="#Test-Doubles-目的" class="headerlink" title="Test Doubles 目的"></a>Test Doubles 目的</h3><h4 id="註"><a href="#註" class="headerlink" title="註"></a>註</h4><ul><li>SUT = System under test 你要測的東西</li><li>DOC = Depended On Component SUT 所依賴的東西(function or package)</li></ul><ol><li>讓我可以只測SUT而不必去管DOC狀況</li></ol><p>例如:前端接完 API 後的畫面邏輯已經寫好了並想要測試它,可是瑞凡你後端的 API 還沒開好,這時 ajax 發出的 request 就可以使用 Test Doubles 跳過去</p><ol start="2"><li>模擬狀況</li></ol><p>可以控制流程的走向,像Call 登入 API 的時候,讓他走到Error Case</p><ol start="3"><li>加速開發,不用等其他人</li></ol><h3 id="Test-Doubles種類"><a href="#Test-Doubles種類" class="headerlink" title="Test Doubles種類"></a>Test Doubles種類</h3><ol><li>Spy</li><li>Stub</li><li>Mock</li><li>Fake</li><li>Dummy</li></ol><p>Sinon.js提供 Spy, Stub, Mock, Fake四種實作方式,因此Dummy不另外介紹</p><h3 id="Spy"><a href="#Spy" class="headerlink" title="Spy"></a>Spy</h3><p>spy是間諜的意思,如字面上它可以監測某個function,並取得她的資訊,像是:function被call了幾次、被call的時候帶了哪些參數、回傳值是什麼……等</p><p>使用 sinon 的 anonymous function 示範<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> spy = sinon.spy()</span><br><span class="line">spy(<span class="string">'a'</span>,<span class="string">'b'</span>)</span><br><span class="line"><span class="built_in">console</span>.log(spy.firstCall.args) <span class="comment">//['a', 'b']</span></span><br></pre></td></tr></table></figure></p><p>第四行看到使用<code>spy.firstCall.args</code>可取得function被呼叫時所帶入的參數</p><p>接著換作一個已存在的函式 isExpire 作為範例</p><p>註:isExpire用來判斷傳入的參數是否過期<br><figure class="highlight javascript"><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">var</span> product = {</span><br><span class="line"> isExpire:<span class="function"><span class="keyword">function</span>(<span class="params">expireDate</span>)</span>{</span><br><span class="line"> <span class="keyword">let</span> now = (<span class="keyword">new</span> <span class="built_in">Date</span>()).getTime()</span><br><span class="line"> <span class="keyword">let</span> expire = <span class="built_in">Date</span>.parse(expireDate)</span><br><span class="line"> <span class="keyword">return</span> (now > expire) ? <span class="literal">true</span> : <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> spy = sinon.spy(product,<span class="string">'isExpire'</span>)</span><br><span class="line">product.isExpire(<span class="string">'1995/2/3'</span>)</span><br><span class="line"><span class="built_in">console</span>.log(spy.calledOnce) <span class="comment">//結果為1</span></span><br></pre></td></tr></table></figure></p><p>11行指定要 spy product 上的 isExpire function,在確認其呼叫次數為1</p>]]></content>
<tags>
<tag> Testing </tag>
</tags>
</entry>
<entry>
<title>Docker - Container 篇</title>
<link href="/2018/05/22/docker/docker-container/"/>
<url>/2018/05/22/docker/docker-container/</url>
<content type="html"><![CDATA[<h1 id="Docker---Container-篇"><a href="#Docker---Container-篇" class="headerlink" title="Docker - Container 篇"></a>Docker - Container 篇</h1><h2 id="container-容器)"><a href="#container-容器)" class="headerlink" title="container(容器)"></a>container(容器)</h2><p>其實就是image跑在記憶體中的樣子(實例),是一個輕量級的沙箱,彼此之間都是獨立的。</p><h2 id="建立容器"><a href="#建立容器" class="headerlink" title="建立容器"></a>建立容器</h2><p>使用docker create創建容器,此時的容器狀態是stopped狀態,在使用docker start 啟動它。其實可直接使用docker run</p><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></pre></td><td class="code"><pre><span class="line">sudo docker run -i -t ubuntu /bin/bash</span><br><span class="line">//這樣會打開後直接執行 echo hello world並關掉容器</span><br><span class="line">sudo docker run -i -t ubuntu /bin/echo 'Hello World'</span><br></pre></td></tr></table></figure><h2 id="取得映像檔"><a href="#取得映像檔" class="headerlink" title="取得映像檔"></a>取得映像檔</h2><p>可使用 docker pull 指令下載某個倉庫的映像檔,若沒有指定tag,則會預設使用 latest標籤(最新)</p><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">// latest</span><br><span class="line">docker pull ubuntu</span><br><span class="line">// 14 version</span><br><span class="line">docker pull ubuntu:14.04</span><br></pre></td></tr></table></figure><p>-i : 讓容器的標準保持打開<br>-t : 分配一個虛擬終端機綁到指定容易</p><p>基本上以後開docker就是加-t -i就對了顆顆</p><h2 id="背景狀態執行"><a href="#背景狀態執行" class="headerlink" title="背景狀態執行"></a>背景狀態執行</h2><p>有時候只會希望docker run在背景,此時就可使用 -d</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">docker run -d ubuntu /bin/sh -c "while true: do echo hello world; stop 1; done"</span><br></pre></td></tr></table></figure><h2 id="停止容器"><a href="#停止容器" class="headerlink" title="停止容器"></a>停止容器</h2><p>如果要停止一個執行中的容器可使用docker stop</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">docker stop <container ID></span><br></pre></td></tr></table></figure><p>停止後使用docker ps -a -q可看到處於停止狀態的容器,處於停止狀態的容器可使用docker start來重啟。<br>docker restart可以將執行中容器關閉並重啟</p><h2 id="進入容器"><a href="#進入容器" class="headerlink" title="進入容器"></a>進入容器</h2><p>如果使用-d讓docker在背景執行,但有時卻又需要透過指令操作可使用attach 來進入容器的command line</p><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">docker run -idt ubuntu</span><br><span class="line">docker attach <name></span><br></pre></td></tr></table></figure><h2 id="刪除容器"><a href="#刪除容器" class="headerlink" title="刪除容器"></a>刪除容器</h2><p>如果要刪除不要的容器可使用docker rm</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">docker rm <Id></span><br></pre></td></tr></table></figure><p>記得要先將容器給終止(docker stop),如果要直接刪除運作中容器可加上-f</p><h2 id="匯入匯出容器"><a href="#匯入匯出容器" class="headerlink" title="匯入匯出容器"></a>匯入匯出容器</h2><p>可以將一個已建立的容器(不管是否運行狀態),在本機上匯成一個檔案</p><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><br><span class="line">docker ps -a</span><br><span class="line">//匯出成10d2.tar</span><br><span class="line">docker export 102d > 10d2.tar</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/gnEWnk4.png" alt=""></p><p>匯入的話則可使用docker import搭配bash 的cat + pipe(將結果丟到下一個指令),成為映像檔</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">cat 10d2.tar | docker import - 10d2.tar/ubunut</span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> Docker </tag>
</tags>
</entry>
<entry>
<title>Docker - Image 篇</title>
<link href="/2018/05/21/docker/docker-image/"/>
<url>/2018/05/21/docker/docker-image/</url>
<content type="html"><![CDATA[<h1 id="Docker-Image篇"><a href="#Docker-Image篇" class="headerlink" title="Docker-Image篇"></a>Docker-Image篇</h1><h2 id="image(映像檔)"><a href="#image(映像檔)" class="headerlink" title="image(映像檔)"></a>image(映像檔)</h2><p>docker 的唯獨模板,例如:一個映像檔可以包涵完整的 ubuntu系統,就叫他 ubuntu映像檔,當然這個映像檔也可以裝上 apache,以及其他東西,就被稱作XXX映像檔。</p><h2 id="取得映像檔"><a href="#取得映像檔" class="headerlink" title="取得映像檔"></a>取得映像檔</h2><p>可使用 docker pull 指令下載某個倉庫的映像檔,若沒有指定tag,則會預設使用 latest標籤(最新)</p><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">// latest</span><br><span class="line">docker pull ubuntu</span><br><span class="line">// 14 version</span><br><span class="line">docker pull ubuntu:14.04</span><br></pre></td></tr></table></figure><p>事實上都是從預設的註冊伺服器下載(docker hub),相當於</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">docker pull registry.hub.docker.com/ubuntu:XXX</span><br></pre></td></tr></table></figure><p>當然也可以從其他register抓取資源,像是docker pool。</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">docker pull dl.dockerpool.com:5000/ubuntu</span><br></pre></td></tr></table></figure><p>下載好後即可利用這個image 建出container(實例),並且執行bash</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">docker run -t -i ubuntu /bin/bash</span><br></pre></td></tr></table></figure><h2 id="查看映像檔"><a href="#查看映像檔" class="headerlink" title="查看映像檔"></a>查看映像檔</h2><p>使用 <code>docker images</code> 查看本機上已存在的映像檔</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">docker images</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/usGN02N.png" alt=""></p><p>TAG 資訊用於標記來自同一個倉庫(ubuntu) 不同的映像檔, docker tag 則可為本機上映像檔添增新標籤 (repository欄位名稱),這兩者不一樣。</p><p>docker tag 產生的新映像檔實際上指向了同一個映像檔,所以他們 IMAGE ID 相同</p><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">docker tag ubuntu:latest xxxx</span><br><span class="line">docker tag <ID> xxxx</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/LtVv2RY.png" alt=""></p><p>若要查看映像檔詳細資訊可使用</p><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></pre></td><td class="code"><pre><span class="line">docker inspect <ID></span><br><span class="line">//可使用-f查詢特定參數</span><br><span class="line">docker inspect -f {{".Architecture"}} <ID></span><br></pre></td></tr></table></figure><h2 id="搜尋映像檔"><a href="#搜尋映像檔" class="headerlink" title="搜尋映像檔"></a>搜尋映像檔</h2><p>使用 docker search <key term=""> 搜尋遠端倉庫中的映像檔,預設搜尋 Docker Hub</key></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">docker search mysql</span><br></pre></td></tr></table></figure><h2 id="刪除映像檔"><a href="#刪除映像檔" class="headerlink" title="刪除映像檔"></a>刪除映像檔</h2><p>使用 docker rmi <id or="" tag=""> 刪除映像檔</id></p><p>使用 tag 刪除: 假設有多個 Tag 指向同個 ID,則刪除某個 image(使用 docker images 看到的 image) 時不會真的刪掉真實的 image,只是刪除他的標籤。如果最後只剩一個,則真實 image就會被刪除。</p><p>使用 ID 刪除:如果有多個 tag 指到同個 ID (使用 docker tag),則無法刪除必須使用 tag,它不會讓你直接刪除真實 image,除非只剩一個 tag 指到 image ID</p><h2 id="建立映像檔"><a href="#建立映像檔" class="headerlink" title="建立映像檔"></a>建立映像檔</h2><ul><li>基於現有映像檔的容器建立</li></ul><p>啟動一個本來就有的映像檔,然後在上面進行修改並新增一個檔後退出</p><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">docker run -ti ubuntu /bin/bash</span><br><span class="line">docker commit -m "xxxxx" -a "xxxx" <container ID> <tag Name></span><br><span class="line">ex:</span><br><span class="line">docker commit -m "added a new file" -a "docker newbee" a925cb40b3fo test</span><br></pre></td></tr></table></figure><p>此時使用docker images就會發現有新的image</p><ul><li>基於Linux 容器(LXC)範例匯入</li></ul><p>有空補上</p><ul><li>Dockerfile</li></ul><p>有空補上</p><h2 id="儲存和載入映像檔"><a href="#儲存和載入映像檔" class="headerlink" title="儲存和載入映像檔"></a>儲存和載入映像檔</h2><p>如果要將image存成壓縮檔可使用docker save</p><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></pre></td><td class="code"><pre><span class="line">docker save -o ubuntu_latest.tar ubuntu</span><br><span class="line">//這比較常見</span><br><span class="line">docker save ubuntu > xxx.tar</span><br></pre></td></tr></table></figure><p>反之則可使用docker load把壓縮檔載入本機映像檔</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">docker load < xxx.tar</span><br></pre></td></tr></table></figure><h2 id="上傳映像檔"><a href="#上傳映像檔" class="headerlink" title="上傳映像檔"></a>上傳映像檔</h2><p>首先,你必須先去 Docker Hub 辦帳號,並且創一個 repo 取名為 uploadtest (隨意),接著可以使用 docker push 上傳(根本就 github)。</p><p>以下需注意,假設 tag 為 ubuntu,則需要先用 docker tag 將其新增一個 tag,名稱必須是 Docker Hub ID/Docker hub上 repo<br>name,在使用push就可直接推到遠端。記得要先用docker login登入,不然就耍智障了</p><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">1. docker login</span><br><span class="line">//curt6815463是我docker hub上ID, uploadtest是我在上面創的repo名字</span><br><span class="line">2. docker tag ubuntu curt6815463/uploadtest</span><br><span class="line">3. docker push curt6815463/uploadtest</span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> Docker </tag>
</tags>
</entry>
<entry>
<title>JavaScript中的測試工具怎麼分類?</title>
<link href="/2018/05/20/testing/testing-classify/"/>
<url>/2018/05/20/testing/testing-classify/</url>
<content type="html"><![CDATA[<h1 id="測試的工具怎麼分類?"><a href="#測試的工具怎麼分類?" class="headerlink" title="測試的工具怎麼分類?"></a>測試的工具怎麼分類?</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>開始練習寫測試的時候,再學會語法之前常常就被一堆的工具搞混,像是Jest、Mocha、Karma……等,這篇文章來簡單聊聊這些工具的功用及分類</p><h2 id="隨意說說Unit-Test"><a href="#隨意說說Unit-Test" class="headerlink" title="隨意說說Unit Test"></a>隨意說說Unit Test</h2><blockquote><p>單元測試專注在單一區塊程式碼,可能是function、Object、Module,在JS中主要以function為主,透過傳入的參數或設定外部變數來確認這個function的回傳為預期的結果</p></blockquote><p>舉個例子:假如今天在電商網站中,實作一個確認商品沒有過期的Function</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">isExpire</span>(<span class="params">expireDate</span>)</span>{</span><br><span class="line"> <span class="keyword">let</span> now = (<span class="keyword">new</span> <span class="built_in">Date</span>()).getTime()</span><br><span class="line"> <span class="keyword">let</span> expire = <span class="built_in">Date</span>.parse(expireDate)</span><br><span class="line"> <span class="keyword">return</span> (now > expire) ? <span class="literal">true</span> : <span class="literal">false</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>當傳入的expireDate參數比今天日期小時,代表商品已經過期必須要回傳false,因此測試可能寫成這樣</p><figure class="highlight javascript"><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">if</span> (isExpire(<span class="string">'3000/4/4'</span>)){</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'OK pass'</span>)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="string">'expire function error'</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>但是這樣寫不但需要自己管理測試程式,呈現的結果也很糟糕,這時候就可以使用一些測試工具摟</p><!-- 補充:除了Unit Test,還有End-To-Ent Testing呢!! --><h2 id="工具分類"><a href="#工具分類" class="headerlink" title="工具分類"></a>工具分類</h2><p>測試工具通常可以分為四類,這不是絕對!不過可以思考這樣分類的意義</p><ol><li>Test Runner</li><li>Testing Framework</li><li>Assertion Libraries</li><li>Testing Plugins</li></ol><h3 id="Test-Runner"><a href="#Test-Runner" class="headerlink" title="Test Runner"></a>Test Runner</h3><p>提供環境給測試工具在其中運行,並且將處理結果輸出到Log、File、Console……等</p><p>Karma是個標準的Test Runner,他會產生一個網頁伺服器,針對不同瀏覽器跑你寫的Unit Test,並將結果輸出到console,告訴你哪些測試是pass哪些是fail</p><p>當你要測的程式碼<code>本身需要跑在瀏覽器時</code>,像是操作網頁的DOM或是測試一些前端framework的畫面邏輯,你就可以使用<code>Karma</code>,因為通常Unit Test會寫在.js檔並用Node.js去跑,而Node.js只是一個跑在伺服器端環境的JavaScript,所以想要在伺服器端運行瀏覽器端的程式碼就得靠它了</p><p>註:這邊指的伺服器端只是代表<code>他沒有在browser端</code>,並不是一定要開個Http Server才能寫Node.js</p><h3 id="Testing-Framework"><a href="#Testing-Framework" class="headerlink" title="Testing Framework"></a>Testing Framework</h3><p>提供一個寫測試的規則,讓你照著那個準則就可以很方便的撰寫及管理測試程式碼(根本只是在講framwork是什麼東西吧),那我們來舉個實例</p><p>如果使用了mocha剛剛的範例就會如下</p><figure class="highlight javascript"><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">describe(<span class="string">'isExpier'</span>, () => {</span><br><span class="line"> it(<span class="string">'check the date whether is expier'</span>, () => {</span><br><span class="line"> <span class="keyword">if</span> (isExpier(<span class="string">"2000/04/04"</span>)) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">'the date should be expire'</span>)</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>可以看到多了describe及it,這就是mocha提供的規則,讓我們能比較方便對Unit Test 進行分類,對於Test Runner執行後的結果也能整理成漂亮的報表來呈現</p><p>但是依舊要寫If-Else好煩啊!!還要寫那麼長,這時候Assertion Libraries(斷言庫)就可以派上用場拉!</p><h3 id="Assertion-Libraries"><a href="#Assertion-Libraries" class="headerlink" title="Assertion Libraries"></a>Assertion Libraries</h3><p>斷言可以替Unit Test省下冗長的If-Else,除此之外還可以增加程式碼的可讀性</p><p>我們使用Chai再將剛剛的例子修改一下</p><figure class="highlight javascript"><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">describe(<span class="string">'isExpire'</span>, () => {</span><br><span class="line"> it(<span class="string">'check the date whether is expier'</span>, () => {</span><br><span class="line"> expect(isExpire(<span class="string">'2000/04/04'</span>).to.equal(<span class="literal">false</span>))</span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>是不是就簡單多了?</p><p>註:斷言寫法有分為TDD style, BDD style,上面範例為BDD style,這又可追溯到開發原理TDD與BDD,不過本篇暫時不討論</p><h3 id="Testing-Plugins"><a href="#Testing-Plugins" class="headerlink" title="Testing Plugins"></a>Testing Plugins</h3><p>基本上使用Test Runner、Test Framework、Assertion Libaraies就可以寫好測試了,不過試想有時為了測試某個功能,而特地開了API、Server、Database……等,是不是太麻煩了?或是為了測試異步的function,而使得測試過程為了等待回應而降低了測試的效益,像是Ajax Call,這時就可以使用一些Plugins,來幫助我們解決類似問題。</p><h2 id="結論"><a href="#結論" class="headerlink" title="結論"></a>結論</h2><ul><li>Karma是Test Runner</li><li>Mocha是Testing Framework</li><li>Chai是Assertion Libaraies</li><li>Sinon主要是Testing Plugins,並自帶Aserrtion Libaraies</li><li>Jest主要是Testing Framework,並且有Assertion Libaraies + Testing Plugins<blockquote><p>Jest好棒棒</p></blockquote></li></ul><h2 id="資料來源"><a href="#資料來源" class="headerlink" title="資料來源"></a>資料來源</h2><p><a href="http://amzotti.github.io/testing/2015/03/16/what-is-the-difference-between-a-test-runner-testing-framework-assertion-library-and-a-testing-plugin/" target="_blank" rel="noopener">http://amzotti.github.io/testing/2015/03/16/what-is-the-difference-between-a-test-runner-testing-framework-assertion-library-and-a-testing-plugin/</a></p><p>本篇文章的工具四種分類為參考amzotti想法,並加上自己的觀點</p>]]></content>
<tags>
<tag> Testing </tag>
</tags>
</entry>
<entry>
<title>設定overflow後scroll時,不能平滑滾動的問題怎麽處理?</title>
<link href="/2018/05/20/mix/overflow-not-scroll-smooth/"/>
<url>/2018/05/20/mix/overflow-not-scroll-smooth/</url>
<content type="html"><![CDATA[<h1 id="overflow-scroll-時不能平滑滾動的問題怎麽處理?"><a href="#overflow-scroll-時不能平滑滾動的問題怎麽處理?" class="headerlink" title="overflow: scroll 時不能平滑滾動的問題怎麽處理?"></a>overflow: scroll 時不能平滑滾動的問題怎麽處理?</h1><h2 id="情境"><a href="#情境" class="headerlink" title="情境"></a>情境</h2><blockquote><p>在div設定 overflow:scroll後,從IOS手機打開瀏覽器會發現,滾動畫面的時候很卡,手一離開畫面就立即停止繼續滑動</p></blockquote><h2 id="解法"><a href="#解法" class="headerlink" title="解法"></a>解法</h2><p>使用<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">-webkit-overflow-scrolling</span>: <span class="selector-tag">touch</span>;</span><br></pre></td></tr></table></figure></p><p>這行會讓IOS啟動硬件加速,因此可解決卡頓的問題<br>不過這也是WebKit 108400版本左右才支持<br>因此iOS Safari需要5.0以上,Android4.0以上才有效</p><h2 id="探討前綴字元"><a href="#探討前綴字元" class="headerlink" title="探討前綴字元"></a>探討前綴字元</h2><h4 id="首先要知道不同的瀏覽器,會使用不同的引擎去實作"><a href="#首先要知道不同的瀏覽器,會使用不同的引擎去實作" class="headerlink" title="首先要知道不同的瀏覽器,會使用不同的引擎去實作"></a>首先要知道不同的瀏覽器,會使用不同的引擎去實作</h4><ul><li>OperaGoogle、Safari:Webkit</li><li>Firefox:Gecko</li></ul><p>註:<br>Opera以前是Presto後來改為Webkit<br>Firefox在mobile中也有部分使用Webkit實作</p><h4 id="因此在某些情況,瀏覽器會選擇使用前綴字眼表示某些CSS"><a href="#因此在某些情況,瀏覽器會選擇使用前綴字眼表示某些CSS" class="headerlink" title="因此在某些情況,瀏覽器會選擇使用前綴字眼表示某些CSS"></a>因此在某些情況,瀏覽器會選擇使用前綴字眼表示某些CSS</h4><h4 id="EX"><a href="#EX" class="headerlink" title="EX:"></a>EX:</h4><ol><li>試驗一些還未成為標準的的CSS屬性——也許永遠不會成為標準</li><li>對新出現的標準的CSS3屬性特徵做實驗性的實現</li><li>對CSS3中一些新屬性做等效語義的個性實現</li></ol><blockquote><p>主要就是讓瀏覽器來測試或試驗新的CSS標準</p></blockquote><h4 id="前綴字眼"><a href="#前綴字眼" class="headerlink" title="前綴字眼"></a>前綴字眼</h4><ol><li>-ms-:Trident(IE)</li><li>-moz-:Gecko(Firefox)</li><li>-o-:Presto(Opera)</li><li>-webkit-:Webkit(Chrome、Safari)</li></ol><h2 id="談談Web-open-in-mobile-app"><a href="#談談Web-open-in-mobile-app" class="headerlink" title="談談Web open in mobile app"></a>談談Web open in mobile app</h2><blockquote><p>常常開發的網頁在Line或Messenger,甚至是其他應用程式中打開居然就壞了!!明明自己寫跟測試的時候都正常啊?</p></blockquote><p>首先我們要理解,在手機應用程式內開啟的瀏覽器,與我們一般打開的browser有所出入,事實上俗稱<strong>Webview</strong>(以Chrome、Safari為主)</p><h3 id="Webview-In-App-Web"><a href="#Webview-In-App-Web" class="headerlink" title="Webview (In App Web)"></a>Webview (In App Web)</h3><p>根據Webkit引擎實作的手機內核瀏覽器,只是為了簡單的展示網頁,因此有些功能很可能沒有實作上去,像是Webview所打開的Safari就沒有cookie功能</p><h2 id="回到源頭:萬一這些In-app-web沒有實作這些CSS?"><a href="#回到源頭:萬一這些In-app-web沒有實作這些CSS?" class="headerlink" title="回到源頭:萬一這些In app web沒有實作這些CSS?"></a>回到源頭:萬一這些In app web沒有實作這些CSS?</h2><p>這時或許只好從JS的角度來解決問題</p><p>以這次的範例來思考,是不是可以再滾動的末尾在偷偷給加上一些數值?讓他假裝滑順(先不考慮它的加速度狀況)</p><p>首先我會直覺想到Dom的<strong>scroll event</strong>、<strong>wheel event</strong><br>註:scroll偵測scrollbar的變動,wheel偵測滑鼠滾輪滾動</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><div id="wrap"></span><br><span class="line"> <ul></span><br><span class="line"> <li>...</li></span><br><span class="line"> ....無限多</span><br><span class="line"> </ul></span><br><span class="line"></div></span><br></pre></td></tr></table></figure><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> el = <span class="built_in">document</span>.querySelector(<span class="string">'#wrap'</span>)</span><br><span class="line">el.addEventListener(<span class="string">'scroll'</span>,(event)=>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'正在scroll'</span>); </span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>可以偵測到每次地滾動,不過我要的應該是最後一個scroll的事件而不是每一個都給它加上數值,可以使用<strong>setTimeout</strong></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> el = <span class="built_in">document</span>.querySelector(<span class="string">'#wrap'</span>)</span><br><span class="line"><span class="keyword">let</span> timer = <span class="literal">null</span></span><br><span class="line">el.addEventListener(<span class="string">'scroll'</span>,(event) => {</span><br><span class="line"> <span class="keyword">if</span>(timer !== <span class="literal">null</span>) {</span><br><span class="line"> clearTimeout(timer);</span><br><span class="line"> }</span><br><span class="line"> timer = setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'這次scroll最後一個event'</span>);</span><br><span class="line"> }, <span class="number">100</span>);</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>但是做到這開始思考,大部分容易出這個狀況的應該是在mobile,那麼滑螢幕滾動時有按下去的瞬間以及釋放的瞬間,是不是使用<strong>touch event</strong>更加合適?</p><h3 id="touch-event"><a href="#touch-event" class="headerlink" title="touch event"></a>touch event</h3><p>共有四組</p><ul><li>touchstart</li><li>touchend</li><li>touchcancel</li><li>touchmove</li></ul><p>目前狀況看起來可使用touchend事件,來讓滑動的最後加上一些數值</p><figure class="highlight javascript"><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">let</span> el = <span class="built_in">document</span>.querySelector(<span class="string">'#wrap'</span>)</span><br><span class="line">el.addEventListener(<span class="string">'touchend'</span>,(event)=>{</span><br><span class="line"> setTimeout(<span class="function"><span class="params">()</span>=></span>{</span><br><span class="line"> el.scrollTop = el.scrollTop + <span class="number">20</span></span><br><span class="line"> },<span class="number">1000</span>)</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><p>當手離開時(touchend),把scrollTop偷偷加20模擬smooth的感覺<br>不過這樣會頓一下,因為是直接加上20所以會直接跳到那個位置<br>如果要有點smooth的feel我們可以用setInterval</p><figure class="highlight javascript"><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">let</span> el = <span class="built_in">document</span>.querySelector(<span class="string">'#wrap'</span>)</span><br><span class="line">el.addEventListener(<span class="string">'touchend'</span>,(event)=>{</span><br><span class="line"> setTimeout(<span class="function"><span class="params">()</span>=></span>{</span><br><span class="line"> <span class="keyword">var</span> final = el.scrollTop + <span class="number">20</span></span><br><span class="line"> scrollInterval = setInterval(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">if</span> (el.scrollTop < final) {</span><br><span class="line"> el.scrollTop = el.scrollTop + <span class="number">5</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> clearInterval(scrollInterval);</span><br><span class="line"> },<span class="number">15</span>);</span><br><span class="line"> },<span class="number">100</span>)</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><p>當手離開時,每0.015秒scrollTop加上5直到加滿20<br>這樣下來就稍微有模擬smooth的樣子<br>當然了,如果要讓它非常的滑順,則需要有良好計算及演算</p><p>PS:若想要使用手機debug,除了Chrome Dev Tool之外可使用<br><a href="https://console.re/" target="_blank" rel="noopener">https://console.re/</a></p>]]></content>
<tags>
<tag> CSS </tag>
<tag> JS </tag>
</tags>
</entry>
<entry>
<title>為什麼vue可以寫在.vue檔裡面?</title>
<link href="/2018/05/19/vue/why-vue-loader/"/>
<url>/2018/05/19/vue/why-vue-loader/</url>
<content type="html"><![CDATA[<h1 id="為什麼vue可以寫在-vue檔裡面?"><a href="#為什麼vue可以寫在-vue檔裡面?" class="headerlink" title="為什麼vue可以寫在.vue檔裡面?"></a>為什麼vue可以寫在.vue檔裡面?</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>想要寫一個vue應用你可以引入他的CDN,接著new出一個vue instance並開始寫裡面的邏輯,但除此之外Vue提供了別的方式來撰寫,那就是<code>vue-loader</code></p><h3 id="沒有使用vue-loader範例"><a href="#沒有使用vue-loader範例" class="headerlink" title="沒有使用vue-loader範例"></a>沒有使用vue-loader範例</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE html></span></span><br><span class="line"><span class="tag"><<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"viewport"</span> <span class="attr">content</span>=<span class="string">"width=device-width, initial-scale=1.0"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"X-UA-Compatible"</span> <span class="attr">content</span>=<span class="string">"ie=edge"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>Document<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://unpkg.com/vue/dist/vue.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"counter"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">vue-button</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">vue-button</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">script</span>></span><span class="undefined"></span></span><br><span class="line"><span class="javascript"> Vue.component(<span class="string">'vue-button'</span>, {</span></span><br><span class="line"><span class="undefined"> template: `</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="undefined"> {{count}}</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">button</span> <span class="attr">v-on:click</span>=<span class="string">'increment'</span>></span>click me<span class="tag"></<span class="name">button</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="undefined"> `,</span></span><br><span class="line"><span class="javascript"> data: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> {</span></span><br><span class="line"><span class="undefined"> count: 0</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> },</span></span><br><span class="line"><span class="undefined"> methods: {</span></span><br><span class="line"><span class="javascript"> increment: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span></span><br><span class="line"><span class="javascript"> <span class="keyword">this</span>.count += <span class="number">1</span></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> },</span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="javascript"> <span class="keyword">new</span> Vue({</span></span><br><span class="line"><span class="javascript"> el: <span class="string">'#counter'</span></span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="undefined"> </span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><h3 id="畫面效果"><a href="#畫面效果" class="headerlink" title="畫面效果"></a>畫面效果</h3><p><img src="https://i.imgur.com/tyjfMlA.png" alt=""></p><h3 id="問題點"><a href="#問題點" class="headerlink" title="問題點"></a>問題點</h3><p>當今天畫面邏輯變大時候,肯定要拆分不同的檔案不可能全部都寫在<code>html</code>裡面<br>而在html裡面我們也只能透過script tag引入不同js file來拆分檔案<br>如果有個方式來幫我們處理<code>分檔問題</code>是再好不過</p><h2 id="來使用vue-loader吧!!"><a href="#來使用vue-loader吧!!" class="headerlink" title="來使用vue-loader吧!!"></a>來使用vue-loader吧!!</h2><h3 id="使用概念"><a href="#使用概念" class="headerlink" title="使用概念"></a>使用概念</h3><p>將<code>Vue</code>程式直接寫在副檔名為.vue的file裡面,可是這些file始終要放到瀏覽器執行,因此需要有人幫他轉譯成.js檔案,那就是使用Webpack配上vue-loader</p><p>Webpack是一個前端打包工具,可以將各種資源通過一些規則(loader),將其都打包成.js(或是.css .jpg……),像是:</p><ul><li>sass-loader把.scss編譯成css</li><li>json-loader把 .json編譯成js (Webpack 二版後可以直接使用import引入json file)</li><li>vue-loader把.vue編譯成js</li></ul><p>題外話:webpack本身會解析ES6 module,將import關鍵字包裝成立即執行函數,裡面就放著要import的file程式碼</p><p>事實上這些設定是比較困難也複雜的,最快的方法可以透過<code>vue-cli</code>來產生vue project的模板,裡面已經幫我們做好vue-loader的配置</p><h3 id="vue-cli指令"><a href="#vue-cli指令" class="headerlink" title="vue-cli指令"></a>vue-cli指令</h3><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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">// 安裝全域vue-cli</span><br><span class="line"><span class="meta">$</span> npm install -g vue-cli</span><br><span class="line"></span><br><span class="line">// 初始化vue project</span><br><span class="line">// 格式:vue init <template-name> <project-name></span><br><span class="line"><span class="meta">$</span> vue init webpack my-project</span><br></pre></td></tr></table></figure><p>進入my-project資料夾內的build/webpack.base.conf.js可以看到vue-loader的設定<br><img src="https://i.imgur.com/b8FfO9L.png" alt=""></p><h3 id="vue-loader-file說明"><a href="#vue-loader-file說明" class="headerlink" title="vue-loader file說明"></a>vue-loader file說明</h3><p>根據vue-loader官方文件說明,一個.vue檔基本上由<code>template</code>,<code>script</code>,<code>style</code>三個部份組成</p><ol><li><strong>template</strong>: 撰寫html以及渲染的邏輯指令,ex:v-show,v-model</li><li><strong>css</strong>: 可直接寫入html的css樣式(若再tag中加入scoped,則代表只有當前的.vue檔會生效)</li><li><strong>script</strong>:使用exprot default輸出這個component,意思就是說一個.vue檔可把他當作一個component</li></ol><h3 id="Example"><a href="#Example" class="headerlink" title="Example"></a>Example</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">//這是test.vue檔</span><br><span class="line"><span class="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"example"</span>></span>{{ msg }}<span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span><span class="undefined"></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"><span class="undefined"> data () {</span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> {</span></span><br><span class="line"><span class="javascript"> msg: <span class="string">'Hello world!'</span></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined">}</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span><span class="undefined"></span></span><br><span class="line"><span class="css"><span class="selector-class">.example</span> {</span></span><br><span class="line"><span class="undefined"> color: red;</span></span><br><span class="line"><span class="undefined">}</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">style</span>></span></span><br></pre></td></tr></table></figure><h3 id="不同Vue-file間引入"><a href="#不同Vue-file間引入" class="headerlink" title="不同Vue file間引入"></a>不同Vue file間引入</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"example"</span>></span>{{ msg }}</span><br><span class="line"> <span class="tag"><<span class="name">xxx</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">xxx</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span><span class="undefined"></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> xxx <span class="keyword">from</span> xxx.vue</span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"><span class="undefined"> components:{</span></span><br><span class="line"><span class="undefined"> xxx</span></span><br><span class="line"><span class="undefined"> },</span></span><br><span class="line"><span class="undefined"> data () {</span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> {</span></span><br><span class="line"><span class="javascript"> msg: <span class="string">'Hello world!'</span></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined">}</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span><span class="undefined"></span></span><br><span class="line"><span class="css"><span class="selector-class">.example</span> {</span></span><br><span class="line"><span class="undefined"> color: red;</span></span><br><span class="line"><span class="undefined">}</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">style</span>></span></span><br></pre></td></tr></table></figure><ul><li>使用import引入xxx.vue file(9行</li><li>並且在template中使用xxx組件(3 4行</li><li>注意!!記得要在components中掛上xxx(11行</li></ul>]]></content>
<tags>
<tag> Vue </tag>
</tags>
</entry>
</search>