requestAnimationFrame 筆記

在 Javascript 我們曾經只有一種方式來處理跟特定時間有關的循環事件: setInterval()。簡單說就是當你需要重複某些任務時(依據時間)。
您就會用到這個方法。對於動畫來說需要每秒 60 個 frames 人類才會覺得是順暢平滑的,因此我們可能會寫出像下面這樣的程式碼

繼續閱讀

CSS Grid 介紹

當我們要建置複雜的網站時 Grids 是非常重要的。其重要性我們可以從大量的 CSS 框架中窺知ㄧ二,因為幾乎所有的框架都有提供網格(Grids)系統來加速開發。
隨著 CSS Grid 規範的出現,將來我們將不需要額外的樣式就可以使用網格。另外的好處就是我們將不需要再依賴 inlinefloat 來完成那些佈局需求
在這篇文章我們將要介紹一些網格基本的用法,然後透過實作一個基本的部落格佈局來理解其用法。

繼續閱讀

[譯] Houdini: 你還沒聽說!這可能是 CSS 開發中最令人興奮的事!

其實…我想說這可能是最令我感到興奮..但又害怕頭痛的功能… - 原文連結

你曾經想要使用某個 CSS 的新功能,但是最後卻因為這個功能瀏覽器還未全面支援而放棄了嗎?甚至更糟糕的狀況,瀏覽器已經支援了但卻充滿問題。我敢打賭這些情況你肯定遇過了。如果上面這種情形你曾經遇過,那麼你是應該關心一下 Houdini

繼續閱讀

Cache 筆記

  • 瀏覽器 cache 是一種機制,透過特定狀態告知瀏覽器不需要重新下載檔案
  • cache 最早使用 Expires 和 Pragma,現今主要使用 Cache-Control 來控制
  • cache 大略流程,在實際下載檔案之前發生:
    1. cache 的實際處理機制存在瀏覽器中,也就是我們需要透過指令(cache-directives)告訴瀏覽器該怎麼處理
    2. 瀏覽器設定為不提供 cache ,完全忽略下面步驟直接請求資源
    3. 瀏覽器發送請求,此時可包含 cache-request-directive 這部分的資訊主要是拿來和 server 協商比對用的
    4. 伺服器判斷是否有更新並回傳通知 cache-response-directive
繼續閱讀

line-height 問題筆記

line-height 歸納

  • line-height 有五種屬性可用,預設是 normal 他會拿 font-size * 1.2
    • normal
    • number ex: 1.2, 1.8 => 倍數
    • unit ex: 18px, 2em, 3rem, etc…
    • percentage ex: 90%
    • inherit => line-height from parent
繼續閱讀

深入 css z-index 屬性

說來汗顏,一直以來對於 css 常常是不求勝解。直到自己需要打造自己的輪子才發現對 z-index 完全不熟悉。
關於 z-index 的問題其實非常少人完全明白它到底是怎麼運作的。事實上這並不複雜,不過如果你不曾花些時間閱讀規範可能你不曾察覺一些重要的觀念。

繼續閱讀

關於 delete 變數詭異行為與解釋

問題

發生在當我們撰寫下面程式碼的時候所發現的奇怪行為。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var a = 1;
b = 2;

console.log(a); // 1
console.log(b); // 2

// 使用瀏覽器測試請使用 window 如果是用 node 的 REPL 環境那請改成 global
console.log(window.a); // 1
console.log(window.b); // 2

// 但接下來這麼操作

delete a; // false 不能刪
delete b; // true 可以刪

a; // 1
b; // undefined

解釋

首先根據ECMA-262 §10.3,的定義 Variable environment 是一種特定
型別的 Lexical environment,我們沒辦法透過任何方式直接存取。

一個 Lexical environment 用來記錄執行環境的資訊,可以把它想成是一個物件,我們會把在一個執行環境 Context的變數,函數都存在這個物件的屬性上
針對函數那些定義的參數(Parameter)也會被記錄,舉例來說 function foo (a, b)() 中的 ab 就會被記在 foo 的執行環境資訊中。

一個 Lexical environment 也有一個連結可以連結到外在的 Lexical environment 就是所謂的 scope chain
這個機制可以協助我們取得目前執行環境以外的變數,舉例來說就是 function 裡面可以拿到 global 的變數。

一個 Variable environment 就只是 Lexical environment 的一部份,本質上就是透過 var 宣告在執行環境中的變數或函數。

使用了 var

上面的 a 使用了 var 根據 ECMAScript 定義會被記錄在 Variable environment 根據定義 Variable environment 是不能手動刪除的。
也就是說除非用了 eavl,否則是不能被 delete 的。

1
2
3
4
5
6
7
var a = 1;
delete a; // false
console.log(a); // 1

// 記得清除整個環境
eval('var a = 1; delete a; console.log(a)'); // undefined

沒使用 var

當我們賦值卻沒有用 var,Javascript 會嘗試在 Lexical environment 尋找同名的參考。
最大的不同是 Lexical environment 是嵌套的,就是它可以關聯到外面其他的 Lexical environment
當在本地找不到的時候就會往上層去找,換句話說每個 Lexical environment 都有個爸爸,而最外層的就是 global
所以當我們不使用 var 而宣告一個變數時會開始在各個 scope 尋找同名變數,最終 Javascript 會拿一個 window(global) 的屬性來當作參考。
而物件的屬性是可以刪除的。

結論就是第一個 var 的變數被放在 Variable environment 是不能 delete 的而第二個沒有 var 的變數它是 global 的屬性。

然後你就會問我,那為什麼第一個 a 可以用 window.a 取得,因為全域的 variable object 就是 global(window) 本身。
但誰是屬性誰放在variable environment是有差的,因為程式碼看起來沒差所以會搞死人啊。

Vue.js in Slim 語法的小問題 Slim::Parser::SyntaxError

當我們使用 Vue.js 搭配 slim 時(事實上 Angular 應該也有相同的問題)時

1
2
3
4
5
6
7
8
9
10
div id="app"
p {{message}}

javascript:
new Vue({
el: '#app',
data: {
message: "Hello, Vue.js"
}
})

立馬收到Slim::Parser::SyntaxError的錯誤訊息。

但是改成這樣卻又正常

1
div id="app" {{ message }}

好啦!答案很明顯了就是我們有地方寫錯,讓 slim engine 誤會了。

這邊紀錄一下解法:

補上屬性

第一個最簡單的方式就是幫 p 補上隨意一個屬性

1
2
3
4
5
6
7
8
9
10
div id="app"
p class="" {{ message }}

javascript:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js',
}
})

加上 [], (), {} 任何一種

1
2
3
4
5
6
7
8
9
10
div id="app"
p () {{ message }}

javascript:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js',
}
})

使用 |

1
2
3
4
5
6
7
8
9
10
11
div id="app"
p
| {{ message }}

javascript:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js',
}
})

修改設定

上面的解法都是因為 slim 預設會把 {} () [] 和 tag 後面接的 property=value 當作屬性(attributes)來解析。
所以我們只要把 {} 拿掉就正常了。

新增或修改 config/initializers/slim.rb 加入

1
Slim::Engine.set_options :attr_list_delims => {'(' => ')', '[' => ']'}