Je code donc je suis là.

0%

new Date() 物件的時間處理

我們常需要在網頁上處理或顯示時間,例如文章是何時編輯的、購物時間或是在觀察程式碼的效能時也會需要時間的處理,JavaScript 是如何處理日期和時間的呢?

JavaScript 包含了一個處理時間的物件:new Date(),透過這個構造式裡的方法或參數,我們可以精準的計算任何形式的時間。在這個物件的時間計算單位為毫秒(1000 毫秒為一秒),所以處理時需要另外除以 1000 才能得到我們熟悉的秒數。

Date()物件是基於世界標準時間(UTC) 1970 年 1 月 1 日開始的毫秒數值來儲存時間的。要得到當下的時間是很容易的,這個當下時間來自於我們本身使用的電腦當下的時間,而電腦的時間,有可能是透過網路而得到電腦當下所在時區的時間。但如果我們想要「計算時間」就必須透過一些方式與計算,例如想要計算不是在同時需的時間,或是要對某個時間點做倒數。

我們先來看看Date - JavaScript | MDN 怎麼解釋。

構造函式 new Date()

因為是構造式,創建時間的物件須先以new Date()創建,所回傳的值是一個封裝好的物件,以這個構造式被執行的時間點為標記傳回時間。

1
2
let date = new Date();
console.log(date); // Sat Aug 08 2020 15:36:59 GMT+0200 (中歐夏令時間)

以上的範例傳回// Sat Aug 08 2020 15:36:59 GMT+0200 (中歐夏令時間)
如果我們沒有給Date()任何參數,回傳的會是依電腦系統的設定,產生當下時間的 Date 物件。

以參數的方式取得時間

Date()可接受多種格式參數,回傳一個該參數對應的時間。

  • 參數為字串:如果想指定我們所需要的特定日期(月/日/年)時間(時:分:秒),傳入一個表示時間的字串作為參數,回傳值則是我們指定的日期時間。
  • 參數為毫秒:參數為時間零點開始計算的毫秒數,回傳從 1970/1/1 00:00:00 開始算起的時間點。
  • 參數為多個整數值:參數為代表年、月、日、小時、分鐘、秒、毫秒,回傳對應的時間。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 參數為時間零點開始計算的毫秒數
let date1 = new Date(157821628600);
// Wed Jan 01 1975 16:20:28 GMT+0100 (中歐標準時間)
// 從 1970/1/1 00:00:00 開始算起的時間點

// 參數為字串的時間日期
let date2 = new Date('08/08/2020');
// Sat Aug 08 2020 00:00:00 GMT+0200 (中歐夏令時間)
let date3 = new Date('08/08/2020 12:42:24');
// Sat Aug 08 2020 12:42:24 GMT+0200 (中歐夏令時間)

// 參數為多個整數值: 年、月、日、小時、分鐘、秒、毫秒
let date4 = new Date(2020, 8, 8, 0, 0, 0, 0);
// Tue Sep 08 2020 00:00:00 GMT+0200 (中歐夏令時間)

只要是能被Date.parse()解析的字串,都可以當作是Date()的參數,所以不同的參數寫法都可以得到相同的時間。

1
2
3
4
5
6
7
8
9
new Date('2020/5/8');
new Date('2020-8-8');
new Date('05/8/2020');
new Date('2020-August-8');
new Date('August 8, 2020');
new Date('August, 8, 2020');
new Date('8, August, 2020');
new Date('8 August 2020');
// Sat Aug 08 2020 00:00:00 GMT+0200 (中歐夏令時間)

Date() 以物件的方法取得時間計算

Date()包含了許多的方法,透過呼叫這些方法,可以得到較為細節的時間,以下我們只介紹我們常用的方法。

get*() 得到特定的時間,並回傳整數

以 get 開頭的方法顧名思義是用來取得時間的,以字串為參數,直接指定時間,回傳的整數皆以 0 為起始,以星期來說,0 為週日、月份 0 為一月,以此類推。

1
2
3
let date = new Date('08/08/2020 12:42:24');
console.log(date); // Sat Aug 08 2020 12:42:24 GMT+0200 (中歐夏令時間)
let day = date.getDay(); // 回傳數字 6 ,表示 08/08/2020 這天是週六

以下為常用的get*()方法

  • getTime():回傳當下時間距離 1970 年 1 月 1 日 00:00:00 的毫秒數
  • getDate():回傳當下時間對應每個月的幾號(從 1 開始)。
  • getDay():回傳星期幾,星期日為 0,星期一為 1,以此類推。
  • getFullYear():回傳四位的年份。
  • getMonth():回傳月份(0 表示 1 月,11 表示 12 月)。
  • getHours():回傳小時(0-23)。
  • getMilliseconds():回傳毫秒(0-999)。
  • getMinutes():回傳分鐘(0-59)。
  • getSeconds():回傳秒(0-59)。
1
2
3
4
5
6
7
let date = new Date();
let time = date.getTime();
// 回傳的是從1970年到至今的時間
console.log(time / 1000 / 60 / 60 / 24 / 365);
// 得到的時間值除以毫秒單位/秒單位/分單位/時單位/日單位
// 50.63727990001903
// 從1970 到現在 08/08/2020 共經過了50.637年

如果把戳印時間減去現在時間,原本應該是得到 0,卻回傳-3600000,是因為時區不同的原因,

1
2
3
4
5
6
7
8
9
let testDate = new Date('1/1/1970 0:0:0');
console.log(testDate);
// Thu Jan 01 1970 00:00:00 GMT+0100 (中歐標準時間)
// 現在時間
let nowTime = testDate.getTime();
console.log(nowTime); // -3600000
// 和標準時間相差值
let differTime = nowTime / 1000 / 60 / 60;
console.log(differTime); // -1 差一小時

now()回傳當下的時間戳印

可利用now()方法得到當下的時間,利用時間的戳印特性來測試程式碼的執行效能

1
2
3
4
5
6
7
8
9
let start = Date.now();
console.log(start);

for (let i = 0; i < 1000; i++) {
// console.log(i);
}
let end = Date.now();
console.log(end);
console.log(`執行了${end - start}毫秒`);

取執行前和執行後的時間戳印相減,即可得執行時間

set*() 設置時間的方法

以 set 為開頭的方法,主要以設定時間為主,set*()來設定當下的時間點,常用的有:

  • setDate(date):設置當前時間對應的每個月的幾號(1-31),返回改變後時間(毫秒)。
  • setFullYear(year):設置四位數的年份。
  • setHours(hour):設置小時(0-23)。
  • setMilliseconds():設置毫秒(0-999)。
  • setMinutes(min):設置分鐘(0-59)。
  • setMonth(month):設置月份(0-11)。
  • setSeconds(sec):設置秒(0-59)。
  • setTime(milliseconds):設置毫秒時間。

Timer 設定定時的方法

使用定時的方法可以讓我們時做出不同的效果,另如定時器、倒數、重複時間循環。

setTimeout()

setTimeout()用來指定某個函數或某段 code 在多少毫秒之後執行。
此方法有兩個參數: setTimeout(function|code, delay);
setTimeout(將要延遲執行的函式或 code, 延遲執行的毫秒數),如果省略第二個參數,則默認為 0(也就沒有延遲的意義並馬上執行)。

clearTimeout()

取消` setTimeout()`設的定時器。

setInterval()

setTimeout()完全一致,差別在於setInterval()可以無限次的設置定時器的執行。
此方法有兩個參數:setInterval(function|code, delay);第一參數為執行的函式或程式、第二參數為延遲的毫秒數。

clearInterval()

取消setInterval()設的定時器。

實作電子時鐘

學習路上跌跌撞撞、過程總是零散,生活中總是被瑣事切割成碎片,如何把碎片時間拾揀與拼湊成可專心學習的塊狀已是一種考驗。

遇到六角舉辦的「JS 學徒特訓班」,給自己一次機會跟上進度,也要求自己要真的理解才寫,這需要時間,而語法的不熟悉仍然花時間,這樣一次、兩次、三次的記憶,希望能夠多留在腦中,很清楚知道自己忘的比記的還快,也在找尋且動自己對語法記憶的一把鑰匙。學習程式是非常全面性的,也因此看到自己在幾十年歲月裡看不到的盲點,雖然開始的非常慢,但總是比沒開始的好,那就透過寫程式當作一種自我的修煉吧。

這次的特訓班題目都很實用,尤其是對自己較不熟悉的 API 銜接、資料處理、資料圖形化的部分,覺得練習內容很受用,以此篇來記錄一下。

第二十九關,監聽切換排序功能

內容:以 Axios 讀取 API、使用表單元素 select 切換資料條件。
方式:

  • 抓取 DOM
  • 以 Axios 讀取 API 的資料
  • 監聽 select 切換
  • 處理資料
  • 渲染畫面

常常會忘記有些 JS 內建函式的參數是「函式」,然後常常用箭頭函式寫法忘記花括號…。

首先,需要先把 Axios 函式庫引進來

1
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>

接著是 html 的內容

1
2
3
4
5
6
<select class="choose">
<!-- <option value="">請選擇排序依據</option> -->
<option value="id">依照 id 編號排序(由1開始從上往下)</option>
<option value="process">依照完課率排序(由最高到最低)</option>
</select>
<ul class="list"></ul>

再來就是 JavaScript 的部分了:

抓取 DOM

把會用到的 DOM 和 裝載資料的變數先抓好

1
2
3
4
5
const list = document.querySelector('.list');
const selector = document.querySelector('.choose');
const url =
'https://raw.githubusercontent.com/hexschool/hexschoolNewbieJS/master/data.json';
let data = [];

讀取資料

以 Axios 讀取 API 的資料

1
2
3
4
axios.get(url).then((response) => {
data = response.data;
// console.log(data);
});

監聽 select 切換,取值

1
2
3
4
5
// 監聽事件綁定
selector.addEventListener('change', (event) => {
if (event.target.value == '') return;
getSortData(event.target.value);
});

處理資料

資料需要以 ID 或 完成率來做排序,所以這個函式負責排序資料的處理。當選單的值為id時,以id來排序,不然就是用完成率來排名。
而為了讓排序更精準,在使用sort()時,給函式當參數。記得最後要呼叫渲染畫面的函式render()

1
2
3
4
5
6
7
8
9
// 取得選單的value 並排序
function getSortData(choose) {
data.sort((a, b) => {
if (choose == 'id') return parseInt(a.id) - parseInt(b.id);
return parseInt(b.process) - parseInt(a.process);
});
// 排序完炫染畫面
render();
}

渲染畫面

forEach()把資料一一撈出來,放在要渲染頁面的元素裡。

1
2
3
4
5
6
7
8
9
// 渲染畫面
function render() {
let str = '';
data.forEach((item, index) => {
str += `<li>ID: ${item.id}${item.name},他的特訓班完成度是 ${item.process}</li>`;
// console.log(item);
});
list.innerHTML = str;
}

第三十關,第三十關 C3.js 圖表整合

內容:以 Axios 讀取 API、使用 D3js 顯示視覺畫圖表。
方式:

引進所需的函式庫

讀取 API 的 Axios
資料視覺畫的 D3js, C3js 以及 C3 所需的 CSS

1
2
3
4
5
6
7
<!-- 載入 CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.18/c3.css">

<!-- 載入 JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.18/c3.js"></script>

接著是 html 的內容

1
2
3
4
<section>
<h2>JavaScript 特訓班關卡進度</h2>
<div id="chart"></div>
</section>

定義所需變數

1
2
3
4
5
6
7
let data = []; //存放回傳資料用
// 宣告 columns 變數要放入完成率的資料。
let columns = ['完成率']; //data 對應名稱與存放數據資料用
// 宣告 category 變數要放入參賽者姓名資料。
let category = [];
let url =
'https://raw.githubusercontent.com/hexschool/hexschoolNewbieJS/master/data.json';

讀取 API 資料

使用 Axios 取出 API 的資料,並且以then()catch()觀察取出資料狀態。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 取資料
axios
.get(url)
.then((response) => {
data = response.data;
// console.log(data);
// renderRecord();
sortData();
renderLoad(columns, category);
})
.catch((err) => {
console.log(err);
});

資料處理

排序、將符合條件的資料取出並存入指定陣列中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 資料排序函式
function sortData() {
// 先排序
data.sort((a, b) => parseFloat(b.process) - parseFloat(a.process));
// 將資料撈出並推進陣列
data.forEach((item) => {
if (item.process !== '0%') {
// 只顯示有進度的
columns.push(parseInt(item.process));
category.push(item.name);
}
});
// console.log(columns, category);
}

資料圖形化並渲染畫面

使用 C3js 來渲染畫面,並細部設定資料呈現的方式。

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
// 資料圖形化+渲染函式
function renderLoad(columns, category) {
let chart = c3.generate({
bindto: '#chart',
data: {
columns: [[...columns]], //
axes: {
// 軸數
完成率: 'y2',
},
//自訂圖表類型
type: 'bar',
colors: { 完成率: '#9ccc65' },
},
// 控制圖表尺寸
size: {
height: category.length * 30, //調整圖表高度
},
// 控制軸線顯示
axis: {
// 軸
rotated: true, // 轉橫向
// X 軸
x: {
type: 'category', // 左側 X 軸顯示
categories: category, //參賽姓名資料
label: { text: 'X軸 參賽者姓名', position: 'outer-center' },
},
// Y 軸
y: {
show: true, //下方 Y 軸顯示
label: { text: 'Y軸 完成率', position: 'outer-middle' },
},
y2: {
show: true, //上方 Y 軸顯示
label: {
text: 'Y2軸 完成率完成率',
position: 'outer-middle', //名稱位置
},
},
},
});
}

C3js 的使用方式

進行前先說明一下使用 C3js 的方式:
除了先引進必須的樣式表和函式庫外,C3js 需要先透過 C3 的generate()的函式來產生圖表,並透過此函式內的物件參數,來控制圖表。
C3.js | D3-based reusable chart library

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
let chart = c3.generate({
bindto: '#chart', // 綁定 DOM
//控制、處理與資料、數據相關部分
data: {
columns: [
// 資料來源
['資料1', 10, 20, 30, 40, 50],
['資料2', 10, 20, 30, 40, 50],
],
axes: {
// 軸數

完成率: 'y2',
},
//自訂圖表類型
type: 'bar',
//圖表顏色
colors: { 完成率: '#9ccc65' },
},
// 控制尺寸
size: {},
// 控制圖表的 X,Y軸說明
axis: {
// 軸
rotated: true, // 轉橫向
// X 軸
x: {
type: 'category', // 左側 X 軸顯示
categories: category, //參賽姓名資料
label: { text: '參賽者姓名', position: 'outer-center' },
},
// Y 軸
y: {
show: true, //下方 Y 軸顯示
label: { text: '完成率', position: 'outer-middle' },
},
y2: {
show: true, //上方 Y 軸顯示
label: {
text: '完成率',
position: 'outer-middle', //名稱位置
},
},
},
});

在這份作業裡,我們可以把整份 C3js 的控制成一個函式,藉由帶參數的方式,將可重複使用。

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
function renderLoad(columns, category) {
let chart = c3.generate({
bindto: '#chart', // 綁定顯示位置 DOM
data: {
// 圖表的資料來源
columns: [[...columns]], // 要顯示的資料數據
axes: {
// 軸數
完成率: 'y2',
},
//自訂義圖表類型
type: 'bar',
colors: { 完成率: '#9ccc65' },
},
// 控制圖表尺寸
size: {
height: category.length * 30, //調整圖表高度
},
// 控制軸線顯示
axis: {
// 軸
rotated: true, // 轉橫向
// X 軸
x: {
type: 'category', // 左側 X 軸顯示
categories: category, //參賽姓名資料
label: { text: '參賽者姓名', position: 'outer-center' },
},
// Y 軸
y: {
show: true, //下方 Y 軸顯示
label: { text: '完成率', position: 'outer-middle' },
},
y2: {
show: true, //上方 Y 軸顯示
label: {
text: '完成率',
position: 'outer-middle', //名稱位置
},
},
},
});
}

想解決問題的慾望

大約是一週前,準備在因新冠疫情禁足的一個月之後,重啟一天發一篇文的挑戰。

因為每日練習英文打字,加上五十肩的疼痛,在無法讓肩膀適時休息之下,肩膀痛到不行,也因此學習之旅走鐘的頗嚴重,同時也清楚如果自己不持續下去,勢必有些學過的東西又會遺忘,所以決定每天就打一小小篇文就好。結果計畫又因一個zsh: command not found hexo的出現,又壞壞去了。

實在搞不清楚為什麼平常用得好好的指令突然就不能用了,在找問題出現在哪,且花了許多還是找不出來的狀況下,決定上「親愛的好想」的 slack 發問,在許多夥伴的幫助下,慢慢釐清可能的問題點,但由於自己的基本知識欠缺,而發生一知半解的狀況。

雖然一路下來花了很多時間在爬文,但由於是系統的設置,每個人都不太一樣,尤其是在上台電腦使用 sudo 最高權限操作,導致有許多問題產生,這些問題來自於網路上的求解,跟著指令做的解法也有許多風險,尤其是在自己不是很了解跟著做的指令,到底做了什麼、動到多少系統的基本配置,導致於最後有問題都不太能解決,所以新的電腦就決定盡量不要用 sudo 或是盡量安裝程式或套件時,安裝在需要用的專案裡就好。

ㄧ整個星期每次修都花好幾個小時,連做夢都夢到這件事,今天本來想說,好把,先把這個事情放掉,先用跛腳的卸掉zsh的方法上傳文章,因為hexo本身沒有壞,但是ㄧ手癢又開始試了,結果幾個小時過後,終於解決了!

知道要在zsh的設定檔.zshrc裡頭去設一個路徑變數,但是其實我連基本路徑變數語法都不知道,在解決的途中心裡一直想著,真的應該要去好好學學Linux的指令和系統架構,至少讓自己知道各個不同設定檔案應該會在哪些地方、放在哪裡、層級有什麼不同、全域變數應該是在哪裡可以找得到…等等。雖然會的指令可應付一般,但遇到問題仍然所知不足,所以解決後想說,那就開始學吧!

離題了,紀錄一下這次的處理:
狀況:出現zsh: command not found hexo的錯誤

  1. 字面上來看,是zsh認不出hexo指令
  2. zsh卸掉hexo指令就可以用,表示hexo沒壞
  3. /usr/local/bin/hexo做了hexo軟連結仍然沒用,表示沒找到hexo
  4. which hexowhereis hexo仍然沒找到hexo,於是開始一層層找,一層層試which hexo
  5. 找到hexo之後,將路徑寫成PATH放到.zshrc仍沒用
  6. 發現又被軟連結連到另一個地方,去哪裡試了which hexohexo -v成功,確認路徑
  7. PATH丟到~/.bash_profile沒成功
  8. 再將PATH丟到~/.zshrc成功!
  9. PATH的設定為export PATH=~/.npm-global/lib/node_modules/hexo-cli/bin:\$PATH並寫下註解# 把 hexo 指到指定位置
  10. 重啟zsh並試著更新文章:成功。

問題解決後,就開始學習那些以前的不足,還知識債的概念。

大部分的許多專案的開發,都是偏向 Cli 環境部署的方式開發,也就是常聽到的「腳手架」的方式,但為什麼是「腳手架」?還是這也代表「起手式」?也就是專案在開發,應該就把要開發與運行的環境架設好,到時要打包輸出相容個瀏覽器的語法就會變得簡單多了。

雖然剛開始設定有點繁複,但只要習慣了、工具都齊了,這樣開發起來在測試也會順手許多,所以開發基本功還是要學起來。

實際上以 Cli 的方式部署,也有許多優點,因為他不只會幫你部署,還把整個專案需要用的檔案與資料夾都自動生成,讓你一安裝完就可以寫「Hello World」,當然這些自動生成的檔案我們也需要去了解其作用與規則,不然檔案放錯位置也是會產生錯誤的。

需注意的是,每一個 Cli 的版本都會不太ㄧ樣,所以安裝時的選項也會依版本而略有不同。

安裝後產生的檔案包也可以稱為「開發模板」我們可以在 vue-cli 的 github官網上找到文件。

Vue Cli 3 的開發環境部署步驟

1.先確認本機是否裝了 Vue 的 cli 套件

vue -- version 或是 vue -V(大寫的 V)

如果沒有,先以以下兩個方式一個選裝好 cli
npm install -g @vue/cli
npm install -g @vue/cli-service-global
或是yarn global add @vue/cli
如果連npmyarn都跑不起來,表示你的電腦上沒安裝管理套件工具,請先去npmyarn的官方網站看看怎麼安裝囉。

2.至想創建專案的位置,執行並給予專案名稱(小寫)

官網解說

vue create [ProjectName]

3.進入設置專案選項(一律以上下移動與按空白鍵選取選項)

這時即進入開發部署的選項區,最好先了解一下,各個選項的作用,當然之後也可以修改,但比較麻煩,所以如果可以還是先想好自己要的開發環境,以及需要什麼工具,一次就把它安裝好。

==選擇套件工具==

1
2
3
? Please pick a preset: (Use arrow keys)
❯ default (babel, eslint) // 預設
Manually select features // 自選,有其他選項如sass

==進入選擇 list==
使用<space>選擇 | <a>全選或全不選 | <i> 相反,選了可取消

1
2
3
4
5
6
7
8
9
10
? Check the features needed for your project:
❯◉ Babel
◯ TypeScript
◯ Progressive Web App (PWA) Support
◯ Router
◯ Vuex
◯ CSS Pre-processors // 使用 sass
◉ Linter / Formatter
◯ Unit Testing
◯ E2E Testing

==進入各細項的選擇==
SASS

1
2
3
4
5
6
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supporte
d by default): (Use arrow keys)
❯ Sass/SCSS (with dart-sass)
Sass/SCSS (with node-sass) // Node
Less
Stylus

寫作風格與語法檢查

1
2
3
4
5
Pick a linter / formatter config: (Use arrow keys)
❯ ESLint with error prevention only
ESLint + Airbnb config
ESLint + Standard config
ESLint + Prettier

何時檢查語法寫作風格

1
2
3
? Pick additional lint features:
❯◉ Lint on save // 儲存時檢查
◯ Lint and fix on commit // git commit 時檢查

要將這些套件的設定值放哪裡?

1
2
3
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.?
In dedicated config files
❯ In package.json

要將這些預設值儲存起來以後用嗎?

1
? Save this as a preset for future projects? (y/N)

如果選 y 以後一開始的選項就可選擇。

4. 安裝完成啟動伺服器

1
2
3
4
5
6
7
8
9
10

⚓ Running completion hooks...

📄 Generating README.md...

🎉 Successfully created project test.
👉 Get started with the following commands:

$ cd test // 先進入專案檔案內
$ npm run serve // 啟動伺服器

啟動完畢會顯示本地和客戶端的位址:

1
2
3
4
5
6
7
8

App running at:
- Local: http://localhost:8080/
- Network: http://192.168.53.40:8080/

Note that the development build is not optimized.
To create a production build, run npm run build.
// 請注意,開發版本未進行優化。 要創建生產版本,請運行npm run build。

部署完成的檔案的結構

部署完成後,檔案的結構大致上長這樣,但會依安裝的套件不同而些許不ㄧ樣。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
hello-world/        (專案目錄)

├── dist/ (使用 npm run build 構建完成的檔案)

├── node_modules/ (依賴的模組)

├── public/ (公共資源檔案,不做任何編譯壓縮處理,使用絕對路徑指定的檔案)
│ │
│ ├── favicon.ico (icon 圖片)
│ └── index.html (網站入口)

├── src/ (Vue 與前端的原始檔案)
│ │
│ ├── assets/ (公共資源檔案,與 public 不同的是,assets 會經由 webpacd 構建處理,使用相對路徑指定的檔案,如 LOGO 圖片)
│ ├── components/ (Vue 公共組件)
│ ├── views/ (Vue Router 頁面組件)
│ ├── App.vue (項目入口)
│ ├── main.js (項目的核心)
│ ├── router.js (路由設定)
│ └── store.js (Vuex 狀態管理)

└── package.json (相當於對整個項目的解釋說明文件)

在現有的專案中安裝插件

使用 vue create 來創建一個新專案的時候,有些插件會根據你選擇的特性被預安裝好,如果想在一個已經被創建好的專案中安裝一個插件,可以使用。vue add 命令:
vue add @vue/eslint

其他指令

npm 快速安裝 bootstrap
npm install bootstrap --save

設定參考網站

MIS 腳印: Vue CLI 3 安裝與使用教學
使用 vue-cli 3 快速建立 Vue 專案及專案配置 Vue.config.js

這系列是由觀看法國這位求職教練 Yves Gautier 的 QuestionEntretien 這一系列的影片Parlez moi de vous, présentez-vous, exemples de réponses (coaching emploi)的筆記。

在法國找工作必須先進入「找工作」領域,也就是說,要先學習如何找工作。從如何寫履歷、寫動機信、得到面試機會,如何面試,都有種種的眉眉角角的地方要注意,而歐洲文化與東方的不同,也讓面試時所注重的點不同,這是文化上的差距,需要多聽聽法國的求職教練怎麼說,才能較為清楚與正確地在面試中表達自己。

在法國面試,一定會先請你口頭自我介紹,如何在幾分鐘內把自己的動機和特質介紹給對方,且讓對方對你有印象還真不是件容易的事,當對方請你做簡短的自我介紹,以下為建議。

請你談談你自己

  1. 為什麼自我介紹是必要的
  • 是面試的開端
  • 好的內容是給對方對的訊息
  • 讓對方聆聽
  1. 常犯的錯誤
  • 敘述履歷、太攏長、偏離主題
  1. 回答範例
  • 有主題的敘述自己的專長與特質,從技術面、工作經驗等等條例式的敘述。
  • 以目標來敘述自己,例如想成為開發者的,用關鍵字的方式說明自己的特質。
  • 如果得到這個職位後的計畫。

重新看了 Chris 的鐵人賽糙扣系列,在這一篇裡糙 code 與他們的產地 - if 的判斷式 看到了 Array 去重的部分,卻看不懂…先記下,看以後有沒有辦法看懂。

Array 去掉重複值

在處理 Array 元素重複問題時,常常會寫 if 並且走訪元素找重複。
好一點的,會使用 Array.prototype.includes

1
2
3
4
5
6
7
8
var arr = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
var arr2 = [];
arr.forEach(item => {
if (!arr2.includes(item)) {
arr2.push(item);
}
});
arr2; // [1, 2, 3, 4, 5]

但是,這很糙!!! <– Chris 大大說的。
其實,只要換容器,就可以輕鬆做到這件事。

1
2
var arr = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
var arr2 = [...new Set(arr)]; // [1, 2, 3, 4, 5]

你看!沒有任何的 if 這樣的品味才對。<– 也是 Chris 大大說的。

待續….

常常聽到 JavaScript 的語法作用域和其它語言有些不同,主要是 JavaScript 是屬於使用「靜態作用域」的語言,那什麼又是「靜態作用域」呢?

簡單來說,「靜態作用域」就是變數的作用域在被解析時,就已經確定了作用域,且不會再改變。有靜態就有動態,而「動態作用域」又是什麼?
「動態作用域」是變數的作用域,在調用函式的時候才決定。

靜態作用域,是在 語法解析的時候,就已經確定了。
動態作用域,是在函式被調用呼叫的時候才決定的。

1
2
3
4
5
function callName() {
let moi = 'Tsuifei';
console.log(moi);
}
callName(); // Tsuifei

function裡的變數因為被函式包住,所以是區域變數,而在函式最外層的則是全域變數,所以在上面這段程式中,我們呼叫了callName()這個函式,再進去一行行執行函式內,當我們要它印出moi時,他會先去上面(已經讀到的)找,這時會找到let moi = 'Tsuifei';而把'Tsuifei'印出來。

但是如果函式裡面找不到moi,又要在函式裡面印出moi呢?因為moi這個變數是在callName()這個函式被定義的,所以它的作用域就會在這個函式裡。

1
2
3
4
5
function callName() {
let moi = 'Tsuifei';
}
callName(); //
console.log(moi);
1
2
3
4
5
6
7
8
9
let moi = 'Philippe';
function callName() {
let moi = 'Tsuifei';
console.log('內:' + moi);
}
console.log('外:' + moi);
callName();
// 外:Philippe
// 內:Tsuifei

參考:
Javascript 進階 2-3 語法作用域(Lexical scope) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

Ajax 全名為 Asynchronous JavaScript and XML,一種允許瀏覽器與伺服器交換資料,而不需刷新頁面的技術,都可以叫做 Ajax.

Ajax 這個名字是在 2005 年 5 月的時候,Adaptive Path 的 Jasse James Garrett 在他所寫的文章 Ajax : New Approach to Web Application 中提出的。而 Ajax 這項技術,是由 Google 在 Google labs 發佈的 Google Maps 和 Google Suggest 後真正為人所認識。

Ajax 的技術特殊在於,資料在瀏覽器端與伺服器端交換資料時是「獨立傳輸」而不需要返回整個頁面,只需要更新頁面的一部分。

不需要更新整個頁面資料的技術有好幾種:

  • Flash
  • Java applet
  • 框架
  • 隱藏的 iframe
  • XMLHttpRequest : 此物件是 JavaScript 的一個模組,可使網頁與伺服器進行溝通,是創建 Ajax 應用的最佳選擇,實際上通常我們會把 Ajax 當成 XMLHttpRequest 物件的代名詞。

Ajax 的工作原理

客戶端 傳輸 伺服器端
xhtml 協議:xmlhttp PHP…等
css 載體: Text, xml, Json… 其他語言
JavaScript

Ajax 相關工具

Ajax 並不是新技術,它實際上是集合好幾種技術,每種技術各盡其職,整合起來而成的技術。

  • 伺服器端語言:伺服器端需具備像瀏覽器發送特定訊息的能力,Ajax 與伺服器端語言無關。
  • XML(eXtensible Markup Language, 可擴展標記語言),是一種描述資料的格式。Ajax 需要某種格式化的格式來在客戶端和伺服器端之間傳遞資料,XML 是其中一種。
  • XHTML 和 CSS 標準化呈現
  • DOM 可以與之實現動態顯示與互動。DOM 簡介
  • 使用 XMLHTTP 組件 XHLHttpRequest 物件進行非同步資料讀取。
  • 使用 JavaScript 綁定和處理所有的資料。

Ajax 缺點

  • 由 JavaScript 和 AJAX 引擎導致的瀏覽器兼容問題。
  • 頁面局部更新,導致後退功能失效。
  • 對串接媒體的支持沒有 Flash, JavaScript 好。
  • 部分 Mobile 設備如手機、平板支援度差。

XMLHttpRequest 概述

XMLHttpRequest 最早是在 IE 5 中以 ActiveX 組件的型態實現的,它並不是 W3C 的標準。

  • Internet Explorer 把 XMLHttpRequest 當成是一個 ActiveX 物件。
  • 其他瀏覽器如 FireFox, Safari, Opera 把 XMLHttpRequest 當成一個本地端的 JavaSCript 的物件。
  • XMLHttpRequest 在不同瀏覽器上是可以互相兼容的,所以可以用同樣的方法去走訪 XMLHttpRequest 實例的屬性和方法,不論這個實例是用哪種方式創建。

創建 XMLHttpRequest 物件

為了每次寫 Ajax 的時候可快速開發,可以把 XMLHttpRequest 物件測試寫成一個可重複用的函式:

1
2
3
4
5
6
7
8
function getHTTPObject() {
let xhr = false;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
}

HTTP 請求(request)與回應(response)

一個 HTTP 請求(request)由四個部分組成

  • HTTP 請求方法(method)或「動詞」(verb)
  • 所請求的 url
  • 一組選擇性的請求標頭(headers),其中包含認證(authentication)資訊
  • 一組選擇性的請求主體(body)

伺服器所送出的的 HTTP 回應(response)有三個部分

  • 由數值與文字所組成的狀態碼(status code),指定請求或失敗。
  • 一組回應標頭(headers)
  • 回應主體(body)

使用 Axios

Axios 在 Github 上說明,可透過 npm 安裝在開發專案上,或者也可以使用 CDN 將 Axios 引進來,就可以開始用了。

先以 GET 的方式向 Server 請求資料,因為 Axios 是非同步,所以response會在程式一行行都跑完後,最後才會跑.then的部分。

線上模擬 api www.mocky.io

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>;

// 使用 GER 方法

// Make a request for a user with a given ID
axios
.get('/user?ID=12345')
.then(function(response) {
// handle success 接收伺服器的回應
console.log(response);
})
.catch(function(error) {
// handle error 如有錯誤會到這裡
console.log(error);
})
.then(function() {
// always executed 無論如何都會執行
});

// 使用 POST 方法

HTTP Methods

運作方式為 Server -> JSON -> Client -> AJAX -> Server

1. GET 讀取 readoncy

只有 GET 才應使用 Query String (重要)
如果 fd 結尾 -> 讀取單一物
如果沒有 fd 結尾 -> 讀取該物的 collection

2. DELELE 刪除特定資料

3. POST 建立新資源

會把資源的 ID 傳回給用戶
如果 POST 兩次怎麼辦?

4. PATCH 更動資源的部分內容

  • URL = /v1/users/1001
  • Method = PATCH
  • Request Body = { “age” : 31}

5. PUT 新上傳的內容、覆蓋原來的

或是 Partial Update 部分更動

6. Method OPTIONS

  • 用來查詢某ㄧ資源,並能使用的 method
  • 在 cors domain request 時 Client 端會先發出 OPTIONS 查詢

相關連結:
axios/axios: Promise based HTTP client for the browser and node.js

什麼時候會用到自定義指令?在 Vue 內建的指令無法滿足需求或需要一個特別的功能時,就可以自己攥寫自定義指令,好處是可以重複使用。

自定義指定有兩種:全域自定義指令與局部的自定義指令。有時候我們在一個頁面裡可能會引入或增加好幾個 Vue 的實例,如果是全域的自定義指令,表示所有的 Vue 實例都可使用這個指令,但如果是局部自定義指令,需要指定能使用這組指令的 Vue 實例。

Read more »