0%

前言

之前在安裝套件時,就有先安裝過 Node.js 但從沒有特別去注意,它是應用在哪一塊、可以做什麼?就找了之前 udemy 全端課程,特意拉此部分來認識一下。

Node.js,讓我們可以將js檔案拿出瀏覽器,並直接和電腦硬件互動

  • js: 進行網頁中的實作、函式、行為的建立。動畫的執行、下拉選單
  • Node.js: 允許我們用JS 直接與電腦的硬體互動。例如建立桌面應用程式
  • 此外,還能在別人的電腦或server用Node.js來用行JS。例如:使用者登入 google 並輸入詢問,而你的瀏覽器會發出請求給google servers,而在這些servers 可以真的執行JS程式碼來執行發出的請求

如何使用Node

  1. 首先,建立一個資料夾 intro-to-node,在資料夾內建立檔案index.js
  2. 在該資料夾位置,運行node index.js

  • 印出檔案內的console

node REPL

  • Read Evaluation Print Loop
  • 要進入:就是在終端機下node
  • 和google 的console有點類似
  • 取得些提示 con+ tab 會列出相關的可能性

    離開

  • .exit
  • control+c 兩次
  • clear 可以清除終端機的資料

    native node module

  • 當安裝node,他就會包含許多建立好的模組

    使用node.js 進入電腦本地端的資料

  • nodejs.org/api 可以查到所有native node module,以及使用方式說明的文件
  • 當要使用 modual

  • 警告 jshint esversion:6

實際應用練習:複製檔案

  • 在原本的資料夾內建立新的檔案

  • 在index.jd 輸入該語法
  • 輸入後要運行 node index.js
    • 運行之後會看到 file2 建立完成
  • 若是已經建立好的檔案
  • 在檔案內輸入資訊I am file2
  • 執行 copyFileSync

NPM package manager

如何使用真實npm

  • 在要進行安裝的資料夾內,npm install superheroes

  • 參考文件的說明
    • 在js檔案中輸入
    • 運行 node index.js

什麼是 Node.js?Node.js 完整介紹懶人包!

v-for 呈現多筆陣列

  • v-for= item in peopleArr , item 為 自定義名稱,後面(peopleArr)填入要迴圈的資料
    • item是表示 peopleArr 陣列中每個單一物件
  • key :為帶入陣列的 key 值
1
2
3
4
5
6
7
8
9
10
11
<div id="app">
<h3>v-for 與 key</h3>
<p> 人員介紹</p>
<ul>
<li v-for="(item, key) in peopleArr">
{{ key }} - {{ item.name}} / {{ item.age }} 歲
</li>
</ul>

</div>

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
Vue.createApp({

data(){
return {
peopleArr: [
{
name: 'Ken',
age: 30,
vegan: false
},
{
name: 'Wong',
page: 35,
vegan: false
},
{
name: 'Merry',
age: 60,
vegan: false
},
{
name: 'Tom',
age: 30,
vegan: true
},
],
}
},

}).mount('#app')

codepen

物件迴圈

  • 每個item 就是每個物件的資料
  • key值為物件的屬性名稱
1
2
3
4
5
6
7
8
9
10
11
12
<div id="app">
<h3>v-for 與 key</h3>
<p> 人員介紹</p>
<ul>
<li v-for="(item, key) in peopleObj">
{{ key }} - {{ item.name}} / {{ item.age }} 歲

</li>
</ul>

</div>

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
Vue.createApp({

data(){
return {
peopleObj:{
Salse: {
name: 'Ken',
age: 30,
vegan: false
},
Manager: {
name: 'Wong',
page: 35,
vegan: false
},
HumanResource: {
name: 'Merry',
age: 60,
vegan: false
},
Crew: {
name: 'Tom',
age: 30,
vegan: true
}
},
}
},

}).mount('#app')

v-for 與 key

v-for 可以使用 index 當作 key 嗎?

以六角課程為範例說明

1
2
3
4
5
6
7
8
<h3>v-for 與 key </h3>
<p>菜單</p>
<ul>
<li v-for="(item, key) in products">
{{ key }} - {{ item.name}} / {{ item.price }} 元
<input type="text">
</li>
</ul>
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
Vue.createApp({

data(){
return {
products: [
{
name: '蛋餅',
price: 30,
vegan: false
},
{
name: '飯糰',
price: 35,
vegan: false
},
{
name: '小籠包',
price: 60,
vegan: false
},
{
name: '蘿蔔糕',
price: 30,
vegan: true
},
],
},
method:{
reverseArray: function () {
this.products.reverse();
},
}
}
}).mount('#app')

  • 反轉之後,並沒有跟著

  • 綁定key之後

    1
    <li v-for="(item, key) in products" v-bind:key='item.name'>

v-for 可以使用 index 當作 key 嗎?

索引是依照位置來判定,所以當資料的位置修改,索引值也會跟著變動,導致後續的渲染錯誤。
如果key是會變動的話,可能會導致資料的渲染錯誤

如果後端提供的資料,沒有唯一索引要如何處理?

1.與後端溝通,為何前端要用到key的值
2.拿到資料後,自己產生key,並放入該物件資料中

1
2
3
使用v-for時,一定要用key 
使用v-for時,不要拿索引當作key
請使用唯一的值當作key的值

使用v-model來進行資料的「雙向」綁定, v-model 會根據不同的表單類別來更新元素的內容。
主要應用在表單類型進行綁定,常見的表單元素像是 <input><textarea> 以及 <select> 等。

v-model 可以與 input 、textarea 綁定

1
2
3
4
<h3>input</h3>
<input type="text" class="form-control" v-model="name">
{{ name }}

1
2
3
4
5
6
7
8
9
Vue.createApp({

data(){
return {
name: "小明"
}
},

}).mount('#app')

1
2
3
<h3>textarea</h3>
<textarea cols="30" rows="3" class="form-control" v-model="text"></textarea>
{{ text }}
1
2
3
4
5
6
7
8
9
Vue.createApp({

data(){
return {
text: "一段文字敘述"
}
},

}).mount('#app')

checkbox 單選框

  1. checkbox與p段落連動
  • 在input加入v-model="checkAnswer"
  • P段洛,放入三元運算:用來判斷當checkAnswer為true,顯示’吃飽了’;反之,’還沒’
    • 透過選單的勾選,來顯示 checkAnswer 是 true \ false
1
2
3
4
5
6
7
 <h3>checkbox 單選框</h3>
<p>小明,你是吃飽沒?</p>
<p>{{ checkAnswer ? '吃飽了' : '還沒'}}</p>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="check1" v-model="checkAnswer">
<label class="form-check-label" for="check1">小明回覆</label>
</div>
1
2
3
4
5
6
7
8
9
Vue.createApp({

data(){
return {
checkAnswer: false,
}
},

}).mount('#app')

  1. checkbox 單選延伸
  • 回傳單一的值,相對使用三元運算比較直觀
  • checkAnswer2 是空字串,在 input 綁定後,設定false-value、true-value
  • 將文字綁入:true-value="吃飽了" false-value="還沒",就可以放入資料欄位上
1
2
3
4
5
6
7
8
<h3>checkbox 單選延伸</h3>
<p>小明,你是吃飽沒?</p>
<p>{{ checkAnswer2 }}</p>
<div class="form-check">
<input type="checkbox" v-model="checkAnswer2" true-value="吃飽了" false-value="還沒" class="form-check-input"
id="check2">
<label class="form-check-label" for="check2">小明回覆</label>
</div>
1
2
3
4
5
6
7
8
9
Vue.createApp({

data(){
return {
checkAnswer2: '',
}
},

}).mount('#app')

checkbox 複選框

  • 資料格式為陣列
  • 覆選框的input裡面要有value
  • 當綁定v-model,於畫面點選該項目時,會將 input 中的 value,放入的陣列中
    • 最後將資料渲染於畫面
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      <h3>checkbox 複選框</h3>
      <p>你還要吃什麼?</p>
      <p>{{ checkAnswer3.join('') }}</p>
      <div class="form-check">
      <input type="checkbox" class="form-check-input" id="check3" value="蛋餅" v-model="checkAnswer3">
      <label class="form-check-label" for="check3">蛋餅</label> </div>
      <div class="form-check">
      <input type="checkbox" class="form-check-input" id="check4" value="蘿蔔糕" v-model="checkAnswer3">
      <label class="form-check-label" for="check4">蘿蔔糕</label>
      </div>
      <div class="form-check">
      <input type="checkbox" class="form-check-input" id="check5" value="豆漿" v-model="checkAnswer3">
      <label class="form-check-label" for="check5">豆漿</label>
      </div>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      Vue.createApp({

      data(){
      return {
      checkAnswer3: [],
      }
      },

      }).mount('#app')

v-model 修飾符

修飾符為畫面上,v-model的資料和實際data中的資料在綁定之間,額外處理的小方法。

  1. 延遲 Lazy
  • 輸入文字後,要點擊外面或是按下enter,才會出現
  • 綁定到html的change事件:當完成輸入框的事件之後,才會綁定到資料集
    1
    2
    3
    4
    <h3>修飾符</h3>
    <h4 class="mt-3">延遲 Lazy</h4>
    {{ lazyMsg }}
    <input type="text" class="form-control" v-model.lazy="lazyMsg">

純數值 Number

需要用戶輸入數值,可先將type改為number,並加入修飾符

  • <input type="number">:輸入框無法輸入文字,只能輸入數字,但型別依然是string
1
2
3
<h4 class="mt-3">純數值 Number</h4>
{{ numberMsg }}{{ typeof numberMsg }}
<input type="number" class="form-control" v-model="numberMsg">

  • 要確保輸入的內容為純數字型別:要加修飾符
1
2
3
<h4 class="mt-3">純數值 Number</h4> 
{{ numberMsg }}{{ typeof numberMsg }}
<input type="number" class="form-control" v-model.number="numberMsg">

trim

將資料內容的前後空白鍵,刪除

  • 應用於要輸入e-mail帳號,避免用戶不小心在前後加入空白,而造成資料錯誤
    1
    2
    3
    <h4 class="mt-3">修剪 Trim</h4>
    這是一段{{ trimMsg }}緊黏的文字
    <input type="text" class="form-control" v-model.trim="trimMsg">

參考資料:
重新認識 Vue.js | Kuro Hsu

動態屬性綁定(注意大小寫)

  • 宣告變數dynamic,將 dynamic 綁定於點擊事件上 :click="dynamic = dynamic === 'disabled' ? 'readonly':'disabled'"
    • 如果變數結果是 disable 的話就會切換成 readonly,反之,就會切換為 disabled
  • 接著可以將值動態地加入 HTML 屬性上 :[dynamic]
    • 綁定後,就會發現輸入框隨著切換,有不同效果
      1
      2
      3
      4
      5
      <h3>動態屬性綁定(注意大小寫)</h3>
      <button type="button"
      v-on:click="dynamic = dynamic === 'disabled' ? 'readonly':'disabled'">切換為 {{ dynamic }}</button>
      <br>
      <input type="text" :[dynamic] :value="name">
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      //JS

      Vue.createApp({

      data(){
      return {
      dynamic: 'disabled',
      breakfastShop: {
      name: '奇蹟早餐',
      imgUrl: 'https://images.unsplash.com/photo-1600182610361-4b4d664e07b9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80',
      resizeImg: 'https://images.unsplash.com/photo-1600182610361-4b4d664e07b9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&q=80'
      },
      }
      }
      }).mount('#app')

readony:可以選擇輸入框,但無法輸入值
disabled:無法點選輸入框

1
2
3
4
再次補充說明:
1. dynamic = 【這邊是最前面的變數,用來存放後面回傳回來的值】
2. dynamic === 'disabled' ? 【這邊就是中間判斷式的部分,判斷 dynamic 變數是否為 'disabled'】
3. 'readonly':'disabled' 【這邊就是最後面的值,會依照前方的判斷式來決定回傳 'readonly' 還是 'disabled',如果判斷式結果為 True 則回傳 'readonly' ,反之回傳 'disabled'】

HTML 樣式綁定

樣式綁定是時常使用到的效果,能透過此方式,使顏色改變、增加一點簡易動畫的效果。

範例解說

  • 替 box 增加旋轉效果
  • 綁定class可以用陣列方式、或物件方式來添加,以下範例為物件方式
    • 物件key值對應 className,物件的值是對應 true\false(判斷式)
    • 若className 有 - , 注意要 “bg-danger”
  • 事件的綁定 change() 透過函式來切換 true\falsethis[key] = !this[key];
  • 切換是否旋轉、切換背景色
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <style>
    .box {
    background-color: var(--bs-light);
    border: 1px solid var(--bs-gray);
    width: 80px;
    height: 80px;
    }
    .box {
    transition: all .5s;
    }
    .box.rotate {
    transform: rotate(45deg)
    }
    </style>

    <h2>切換 Class</h2>
    <h3>物件寫法</h3>
    <!-- 物件key值對應 className,物件的值是對應 true\false -->
    <div class="box" :class="{ rotate: isTransform ,'bg-danger':boxColor}"></div>
    <hr>
    <button class="btn btn-outline-primary" v-on:click="change('isTransform')">選轉物件</button>
    <button class="btn btn-outline-primary ms-1" v-on:click="change('boxColor')">切換色彩</button>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    const App = {
    data() {
    return {
    isTransform: true,
    boxColor: false,


    };
    },
    methods: {
    change: function (key) {
    this[key] = !this[key];
    },
    addClass(arr) {
    this.arrayClass.push(...arr);
    }
    },
    };

    Vue.createApp(App).mount('#app');

整合為一個物件

將上個範例的兩個class樣式,整合成一個物件

1
2
3
4
<hr class="mt-4">
<h3>物件寫法 2</h5>
<div class="box" :class='classObj'></div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const App = {
data() {
return {
isTransform: true,
boxColor: false,

classObj:{
rotata: true,
"bg-danger": true,
}

};
},
methods: {
change: function (key) {
this[key] = !this[key];
},
addClass(arr) {
this.arrayClass.push(...arr);
}
},
};

Vue.createApp(App).mount('#app');

綁定樣式,陣列寫法

  • 針對單一元素,加入多個class
    • 此方式就不用 true\false 的判斷動作,只要綁定在陣列之中的樣式,就會套入效果
    • 像是範例,就是使按鈕背景色彩為紅色(‘btn-danger’)、無法點擊(‘disabled’)
      1
      2
      3
      4
      <h4>陣列寫法</h4>
      <button class="btn" :class="['disabled','btn-danger']">請操作本元件</button>
      <button type="button" class="btn btn-outline-primary" v-on:click="addClass(['btn-primary', 'active'])">為陣列加入
      Class</button>
  • 另一種,製作陣列,並將陣列放入
    • 將arrayClass,綁定在標籤的class上
    • 在點擊按鈕,綁定點擊事件,addClass(arr),在該函式傳入參數,將陣列內容加入arrayClass,並套入綁定的標籤上
    • 相對應的方法:
1
2
3
4
5
<h4>陣列寫法</h4>
<button class="btn" :class="arrayClass" >請操作本元件</button>
<button type="button"
class="btn btn-outline-primary"
v-on:click="addClass(['btn-primary', 'active'])">為陣列加入 Class</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const App = {
data() {
return {
// Array 操作
arrayClass: [''],
};
},
methods: {

addClass(arr) {
this.arrayClass.push(...arr);
}
},
};

Vue.createApp(App).mount('#app');

  • btn-primary:背景色為綠色

補充:混合寫法

  • 將bootstrap的class放入,且加入arrayClass
    • :class="[arrayClass,'text-danger'],也就是除了放入 arrayClass 這個變數之外,我們還可以放入新的class給予不同樣式
      1
      2
      3
      4
      <h4>陣列寫法</h4>
      <button class="btn" :class="[arrayClass,'text-danger']">請操作本元件</button>
      <button type="button" class="btn btn-outline-primary" v-on:click="addClass(['btn-primary', 'active'])">為陣列加入
      Class</button>

行內樣式style

要綁定style的時候

  • key會帶入style的屬性(注意要以駝峰式),如background-color,要改為backgroundColor
  • 值則是帶入style相對應的值
1
2
3
4
5
<h2>行內樣式</h2>
<h4>綁定行內樣式</h4>
<div class="box" :style="{backgroundColor:'red'}"></div>
<div class="box"></div>
<div class="box"></div>

加入準備好的資料格式

  • 將設定好的物件,裡面有包含數個樣式,直接綁定至style

  • 背景色彩,紅色,邊框5px

同時多個樣式

  • 以陣列裡面包多個物件
    1
    <div class="box" :style="[styleObject,styleObject2]"></div>

  • 建立add、minus兩個按鈕
    • 點選add增加數字、點選minus減少數字
  • 讓add按鈕綁定addFn函式:v-on:click="addFn" on click事件,執行addFn函式
  • 綁定後,在methods撰寫addFn函式內容,要取得 data 中的 num 才能進行運算 =>this.num++
  • 同理,在minus的按鈕,函式內運算this.num++,並將點擊事件放入button
    • v-on:Event 事件綁定,有兩種撰寫方式
1
2
3
4
5
6
7
8
<div id="app">
<h1>{{num}}</h1>

<button v-on:click="addFn">Add</button>
<!-- v-on 改為@ -->
<button @click="MinusFun">Minus</button>

</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Vue.createApp({

data(){
return {
num: 0
}
},
methods: {
addFn() {
//num.value = num.value + 1;
this.num ++;
},
MinusFun(){
this.num--;
},
}
}).mount('#app')

codepen

事件與class的綁定

  • 於 box 綁定旋轉的效果 :class="{ rotate: isTransform }
  • 在button綁定觸發旋轉的事件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <style>
    .box {
    margin:0 auto;
    background-color: #fff;
    border: 1px solid #ccc;
    width: 80px;
    height: 80px;
    }
    .box {
    transition: all .5s;
    }
    .box.rotate {
    transform: rotate(45deg)
    }
    </style>
    <div id="app">
    <h3>觸發事件 與 縮寫*</h3>
    <div class="box" :class="{ rotate: isTransform }"></div>
    <hr>
    <button class="btn btn-outline-primary" @click="changeClass" >選轉物件</button>
    </div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Vue.createApp({

    data() {
    return {

    isTransform: true,
    };
    },
    methods: {
    changeClass() {
    this.isTransform =!this.isTransform;
    },
    }
    };

    }).mount('#app')

帶入參數

  • 建立 change() 函式以帶入參數方式,來變化 isTransform 的 true\false
    1
    2
    3
    <h3>帶入參數*</h3>
    <div class="box" :class="{ rotate: isTransform }"></div>
    <button class="btn btn-outline-primary" @click="change('isTransform')">選轉物件</button>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Vue.createApp({

    data() {
    return {

    isTransform: true,
    };
    },
    methods: {
    changeClass() {
    this.isTransform =!this.isTransform;
    },
    change(key) {
    this[key] = !this[key];
    },
    }
    };

    }).mount('#app')

    動態物件方法 {}

  • 在一個元素上,加入多個事件
  • 注意:此方式無法傳入參數
    1
    2
    3
    4
    5
    6
    7
    <h3>動態物件方法 {}</h3>
    <!-- 此方法無法傳入參數 -->
    <button class="box" @="{
    mousedown:down,
    mouseup:up
    }">
    </button>
    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
    Vue.createApp({

    data() {
    return {

    isTransform: true,
    };
    },
    methods: {
    changeClass() {
    this.isTransform =!this.isTransform;
    },
    change(key) {
    this[key] = !this[key];
    },
    down() {
    console.log("按下");
    },
    up() {
    console.log("放開");
    }
    }
    };

    }).mount('#app')

codepen

屬性綁定可以輕鬆的將data中的資料,與HTML的標籤屬性綁定,這樣一來可以動態的變更資料。

原本 HTML 的樣子

  • img中原本有個圖片資料
  • v-bind是指令,後接的是HTML的屬性
1
2
3
<h3>綁定屬性 v-bind</h3>
<p>{{ breakfastShop.name }}</p>
<img src="https://images.unsplash.com/photo-1600182610361-4b4d664e07b9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" class="square-img" alt="">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//JS

Vue.createApp({

data(){
return {
breakfastShop: {
name: '奇蹟早餐',
imgUrl: 'https://images.unsplash.com/photo-1600182610361-4b4d664e07b9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80',
resizeImg: 'https://images.unsplash.com/photo-1600182610361-4b4d664e07b9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&q=80'
},
}
}
}).mount('#app')

修改 => 綁定JS中 breakfastShop 物件資料內容

  • 將原本src => v-bind:src="breakfastShop.imgUrl"
    • 此外title 屬性,也能照樣綁定喔!
      1
      2
      3
      <h3>綁定屬性 v-bind</h3>
      <p>{{ breakfastShop.name }}</p>
      <img v-bind:src="breakfastShop.imgUrl" class="square-img" v-bind:title="breakfastShop.name" alt="">

縮寫形式

  • 留下冒號
    1
    2
    3
    <h3>縮寫形式 <code>:</code></h3>
    <img :src="breakfastShop.imgUrl" class="square-img" :title="breakfastShop.name" alt="">

其他屬性的綁定

  • 當他是飽的狀態,就無法按下送出
    • 預設是false 所以可以送出表單
    • 但當點擊狀態切換(isFull: true),此時就會無法點擊送出按鈕
  • 由範例可得知,可以透過 true\false 的狀態切換,製造出不同互動效果
    1
    2
    3
    4
    5
    6
    7
    8
    <h3>更多屬性綁定</h3>
    小明還想點餐:
    <form action="">
    <input type="text" value="我要吃蘿蔔糕">
    <button type="submit" :disabled="isFull">送出</button>
    </form>

    <button type="button" v-on:click="change('isFull')">狀態切換</button>

  • 預設是false,所以可以點擊送出

資料來源:
六角學院 - Vue.js 3 課程

今天要介紹的是 Vue.js3 的起手式,主要參考官方文件來學習

載入方式

1
<script src="https://unpkg.com/vue@next"></script>

引入之後,在index.html檔案

1
2
3
<div id="app">
<h1>{{message}}</h1>
</div>
1
2
3
4
5
6
7
8
9
10
//JS

Vue.createApp({

data(){
return {
message: 'I am Eva!'
}
}
}).mount('#app')
  • 畫面就會出現相應的文字

成品

scss 檔案的建立

所建立的各分檔,個別會負責不同的區塊,並透過@import放入主要的sass檔

  • main.scss 引入其他分檔
  • abstracts
    • /_variables.scss:設定常用的變數,如:顏色、字體大小
    • /_mixin.scss:設定某些區段中,重複用到的樣式,並於該區段要使用的時候引用
  • base
    • /_base.scss:為設定大框架,如html、body、container,等主幹的大小、字型的設定
  • components:放置部分功能元件
    • /_button.scss:按鈕的設定
    • /_heading.scss:標題
    • /_logo.scss
    • /_dropdown.scss
  • layout (設計網頁版面配置(Layout))
    • /_header.scss
    • /_navigation.scss
    • /_products.scss
    • /_slidshow.scss
    • /_footer.scss
  • pages 通常是用來放置其他分頁(網頁內會連結到其他相關分頁)
  • venders 放置外部套件

(1)基礎設置

(1.1)Grid 練習

_base.scss

  • 總共要設置10欄
  • 列的則是設置4區塊
  • 並設置每個區塊都有1.6rem的gap
    1
    2
    3
    4
    5
    6
    7
    .container{
    display: grid;
    grid-template-columns:minmax(6rem,1fr) repeat(8,minmax(min-content,16 rem)) minmax(6rem,1fr);//10欄
    grid-template-rows: repeat(4,min-content);
    grid-row-gap:1.6rem ;

    }

  • minmax(min, max)
    minmax(6rem,1fr):設定格線最小6rem,最大1fr
    fr 單位就是為了格線布局而生,fraction,中文意思是分數,當使用在網格軌道上時,可以直接想像成 “我的這個空位要佔有總 fr 數量的幾等份”
  • repeat(8,minmax(min-content,16rem)):重複8個,最小:min-content;最大16rem
    • repeat() 重複網格線及間距
      • max-content/min-content 最小內容尺寸/最大內容尺寸
        • max-content:給予網格區域所需的最大尺寸空間,內容盡可能避免折行。
        • min-content:給予網格區域所需的最小尺寸空間,內容盡可能的折行,但不會溢出邊界。

[Day19] grid-template 屬性之 rows/columns
Min & Max Content Sizing in CSS Grid — 1/3 Flexibility
CSS Layout很難?用這招30秒就讓你輕鬆生出網頁版面!


(1.2)常用變數

  • _variable.scssmap與function的搭配使用
  • 設定不同的顏色,並設置函式,以利後續使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$colors:(
primary:#333,
secondary:#ffe,
tertiary:#f2f0f1,
quaternary:#f5b149

);
//創造函式
//函式名稱為color代入參數為$color-name,使用map代入物件,最為回傳的結果
@function color($color-name){
@return map-get($map: $colors, $key:$color-name )
}

$font-size:(
xl:3rem,
lg:2.5rem,
md:2rem,
sm:1.8rem,
xs:1.6rem
);
@function size($size){
@return map-get($map: $font-size, $key:$size )
}


(2)layout/_header.scss

header的版面

  • grid-column: 1/-1; (1/11) grid-row: 1/2;表示所佔的區隔
  • 而在header這區,在設置grid劃分區塊
    • 有9欄
    • 列設置3區塊
      1
      2
      3
      4
      5
      6
      7
      8
      .header{
      grid-column: 1/-1; //1/11
      grid-row: 1/2;
      display: grid;
      grid-template-columns: 1fr repeat(7,minmax(min-content,16rem)) 1fr;
      grid-template-rows: repeat(3,min-content);
      grid-gap: 2rem;
      }
  • grid-column: 1/-1; //1/11 ; grid-row: 1/2; What’s the difference between grid-column value 1/1 and 1/2?

(3)logo的大小設置

_logo.scss

  • 注意:設立所設定的欄和列的區塊,是在header設置的grid底下
1
2
3
4
5
6
7
8
9
10
11
.logo{
grid-column: 1/2;
grid-row: 1/2;
padding: 1rem;
//class="logo-img"
&-img{
width: 10rem;
height: 100%;
}
}

(4)heading

  • 標題的位置一樣利用grid來設定
  • 在文字的字體、大小、間距進行調整
    _heading.scss
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    .heading{
    grid-column: 4/7;
    grid-row: 2/3;
    text-align: center;
    &-text{
    font-family: 'Great Vibes',cursive;
    font-size: size(xl)*2; //結果為6rem
    font-weight: lighter;
    letter-spacing: 0.5rem;
    }
    }

(5)heading中的navigation

layout/_navigation.scss

  • .first-nav為放置右上角
  • .second-nav為放置下方,中間的位置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    .first-nav{
    //放在最後三欄
    grid-column: 7/10;
    grid-row: 1/2;
    @include navigation;
    }
    .second-nav{
    grid-column: 3/8;
    grid-row: 3/4;
    @include navigation;
    }
    .dropdown{
    display: none;
    }


  • @mixin,創造navigstion共用樣式
    • 使navigation的li-list可以橫向分散排列
    • 設定hover效果,使游標摸到顏色變淺lighten()
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      //.first-nav-list
      @mixin navigation{

      &-list{
      display: flex;
      justify-content: space-around;
      align-items: center;
      height: 100%;
      }
      &-item{
      list-style: none;
      }
      &-link{
      color: color(primary);
      text-decoration: none;
      font-size: size(sm);
      transition: all .3s;

      &:hover{
      color: lighten(color(primary),40%);
      }
      }
      }

(6)下拉選項:dropdown list的箭頭符號

components/_dropdown.scss

1
2
3
4
5
6
7
8
9
10
11
.dropdown-li{
position: relative;
//創造下拉選單的箭頭符號
&::after{
font-family: 'Font Awesome 5 Free';
content: '\f078';
font-weight:bold ;
}

}

  • 製作下拉式選單的三角形

    • 先利用border製作出上、下、左、右的三角
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      .dropdown{
      &::before{
      content: '';
      display: block;
      position: absolute;
      top: -1.5rem;
      left: 7.3rem;
      border-top: 15px solid red;
      border-right: 15px solid green;
      border-bottom: 15px solid orange;
      border-left: 15px solid blue;

      }
      }
  • 調整上方各色的三角形,並留下要保留的一個三角形

1
2
3
4
5
6
7
8
9
10
11
12
&::before{
content: '';
display: block;
position: absolute;
top: -1.5rem;
left: 7.3rem;
// border-top: 15px solid red;
border-right: 15px solid transparent;
border-bottom: 15px solid orange;
border-left: 15px solid transparent;

}

  • right: -2.8rem;:條整位置對齊正方形list
  • border-bottom: 15px solid darken(color(tertiary),5%);:修改三角形的顏色,使整體為灰色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.dropdown{
position: absolute;
top: 3rem;
right: -2.8rem; //使整個往右移動
width: 10rem;
background-color:darken(color(tertiary),5%);
@include navigation;
padding: 1rem;
text-align: center;
border-radius: 0.2rem;

&::before{
content: '';
display: block;
position: absolute;
top: -1.5rem;
left: 7.3rem;
// border-top: 15px solid red;
border-right: 15px solid transparent;
border-bottom: 15px solid darken(color(tertiary),5%);
border-left: 15px solid transparent;

}

  • hover使下拉選單消失\出現
    • 建立游標摸到.dropdown-li,會顯示下拉選單
    • visibilityopacity
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      .dropdown-li{

      &:hover .dropdown{
      visibility: visible;
      opacity: 1;
      }
      }

      .dropdown{
      visibility: hidden;
      opacity: 0;
      transition: opicity .3s;
      }

使slideshow可以跳轉(如幻燈片效果)

  • 使用@keyframes做出動畫位置

  • Animation Duration(動畫整個完成一次的時間): (fade-in + visible) × images = duration.

    • 假設你要讓圖片花1秒fade-in,再讓他顯示1秒。而你共有3張圖片,所以總共所需時間為6秒。
  • Animation Delay:(fade-in + visible) × (ordinal position − 1) = delay.

  • Keyframes: 100 ÷ animation duration = percentage for 1 second.(100/20=5%),5%為1秒,所以4秒大約是20%的位置

    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
    .slideshow{

    &-slide{
    //使圖片、文字都放在同一個位置
    position: absolute;
    top: 0;
    left: 0;
    width: inherit;
    height: inherit;//預設先讓slide消失

    visibility: hidden;
    opacity: 0;
    animation: slideshow 20s linear infinite ;
    }

    }

    @keyframes slideshow{

    //主要是0~20時圖片顯示,之後都消失,讓其他圖片得宜顯示
    //0~2%創造fade的效果
    0%{
    visibility: hidden;
    opacity: 0;
    };
    2%{
    visibility: visible;
    opacity: 1;
    }
    //2%~18% slide要顯示
    18%{
    visibility: visible;
    opacity: 1;
    }
    //18~20要消失
    20%{
    visibility: hidden;
    opacity: 0;

    }
    100%{
    visibility: hidden;
    opacity: 0;
    }

    }

    Simplest CSS Slideshow
    CSS3 Keyframes Animation
    [筆記] CSS動畫Animation — @keyframes
    完整解析 CSS 動畫 ( CSS Animation )

  • 設置延遲時間(4秒),使每張圖片呈現(css的撰寫方式)

    • :nth-child()選擇第幾張圖片
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      /*設置延遲時間,讓每張slide呈現4秒替換*/
      .slideshow-slide:nth-child(1){
      animation-delay: 0s;
      }
      .slideshow-slide:nth-child(2){
      animation-delay: 4s;
      }
      .slideshow-slide:nth-child(3){
      animation-delay: 8s;
      }
      .slideshow-slide:nth-child(4){
      animation-delay: 12s;
      }
      .slideshow-slide:nth-child(5){
      animation-delay: 16s;
      }
  • 將上方轉化為@each的寫法
    • 先創造一個列表$animlist,在each迴圈時要但進去的項目
    • 在each迴圈中.slideshow-slide:nth-child放入slide of number(取得列表中第一個值),後面接著寫下要執行的動作animation-delay: nth($item,2);
1
2
3
4
5
6
7
8
9
///改寫為=>$animlist:第幾個 延遲秒數,
//#{nth($item,1)}: 1表示(2 4s),第一個值=2
$animList:1 0s,2 4s,3 8s,4 12s, 5 16s;
@each $item in $animList {
.slideshow-slide:nth-child(#{nth($item,1)}){
animation-delay: nth($item,2);
//2就是指秒數
}
}

Sass Tutorials #9 - Nth Function In Lists

產品區下方see more按鈕

  • html part
    • 有三個arrow-line,於後續在scss中會運用此三個div製作箭頭符號
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      <div class="products-btn">
      <a href="#" class="btn">
      <div class="btn-bg">
      <div class="arrow">
      <div class="arrow-line arrow-line-1"></div>
      <div class="arrow-line arrow-line-2"></div>
      <div class="arrow-line arrow-line-3"></div>
      </div>
      </div>
      <span class="btn-text">
      See More
      </span>
      </a>
      </div>
  • 創造arrow
    transform: rotateZ :Z軸 (使其斜向旋轉45度)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    &-line {
    height: .2rem;
    background-color: color(secondary);
    position: absolute;
    }

    &-line-2 {

    width: 1rem;
    //透過旋轉線2,線3使其成為交叉
    transform: rotateZ(45deg);
    }

    &-line-3 {

    width: 1rem;
    transform: rotateZ(-45deg);
    }

transform-origin去設定物件變形的起始點

1
2
3
4
5
6
7
8
&-line {
height: .2rem;
background-color: color(secondary);
position: absolute;
//將x變成arrow > ;因預設原點是在center,所以須將原點拉到右邊,形成箭頭
transform-origin:right ;
}

CSS 属性篇(三):transform-origin属性

  • 增加橫向直線
1
2
3
4
&-line-1{
width: 2rem;
transform: translateX(-0.7rem);
}

  • 設置動畫,透過摸到箭頭,會延展
    • bg的的寬度進行延展
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

.btn{

&:hover .btn-bg{
width: 18rem;
}

&-bg{
width: 4rem;
height: 4rem;
background-color: color(primary) ;
//使其變圓形
border-radius: 5rem ;
position: absolute;
left: 0;
transition: width .2s ;
}

&-line-1{

width: 0;
transform: translateX(-0.7rem);
}
//* line-1預設看不到,透過hover出現
}

  • 使see more 出現

    • 先修改see more的顏色
    • 即便改變顏色,還是會被bg覆蓋,所以要調整z-index
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      .btn{

      &:hover .btn-text{
      color: color(secondary);
      }


      &-text{
      font-size: size(xs);
      text-transform: uppercase;
      color: color(primary);
      z-index: 10;
      }



      }
  • 將箭頭向右移動,並呈現完整箭頭符號

    • 設定.arrow右移,並讓line-1得宜呈現並延展
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      .btn{

      &:hover .arrow{
      transform: translateX(1rem);
      }
      &:hover .arrow-line-1{
      width: 2rem;
      }

      .arrow{
      @include flexPosition;
      transition: transform .2s ;

      &-line-1{
      width: 0;
      transform: translateX(-0.7rem);
      transition: width .2s ;
      }

      }



      }

表尾區塊

(1)footer區塊的樣式

layout/_footer.scss

  • footer有三區,中間是表單,左右邊分別為資訊連結
    1
    2
    3
    4
    5
    6
    7
    8
    9
    .footer{


    grid-column: 1/-1;
    grid-row: 4/5;
    @include flexPosition(space-around);
    padding:5rem 0 ;
    border-top: .1rem solid color(primary);
    }

  • 透過@mixin一次修改2區的條例項目(mixin_scss
    • 其中包含文字大小、樣式、hover效果
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      @mixin footerList {
      &-heading{
      font-size: size(lg);
      color:color(primary);
      }
      &-item{
      list-style: none;
      margin: 1rem 0;
      }
      &-link{
      font-size: size(xs);
      text-decoration: none;
      color: lighten(color(primary),15%);
      transition: color .2s ;

      &:hover{
      color:lighten(color(primary),35%)
      }
      }
      }

(2)社群icon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

.social-icons{
display: flex;
justify-content: space-between;
padding: 1rem;
box-sizing: border-box;

&-item{
list-style: none;
}
&-link{
text-decoration: none;
width: 4rem;
height: 4rem;
border:.1rem solid color(primary);

}


  • border-radius: 100%;調整為圓形外框
  • a標籤的前放為i的圖示,所以flex的設置,是針對social-icons-lik
  • 利用@each來套入icon的顏色
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
&-link{
text-decoration: none;
width: 4rem;
height: 4rem;
border:.1rem solid color(primary);

//修改icon成圓形
// display: block;
border-radius: 100%;
@include flexPosition;

i{
font-size: size(md);
}
}


$socialMediaColors: 1 #3b5998, 2 #b31217, 3 #dc4e41, 4 #55acee, 5 #517fa4, 6 #0077b5;

@each $color in $socialMediaColors {
.social-icons-item:nth-child(#{nth(($color),1)}) .social-icons-link{
color:nth($color,2);
border:.1rem solid nth($color,2);
}
}
  • 轉為css
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    .social-icons-item:nth-child(1) .social-icons-link {
    color: #3b5998;
    border: 0.1rem solid #3b5998; }

    .social-icons-item:nth-child(2) .social-icons-link {
    color: #b31217;
    border: 0.1rem solid #b31217; }

    .social-icons-item:nth-child(3) .social-icons-link {
    color: #dc4e41;
    border: 0.1rem solid #dc4e41; }

    .social-icons-item:nth-child(4) .social-icons-link {
    color: #55acee;
    border: 0.1rem solid #55acee; }

    .social-icons-item:nth-child(5) .social-icons-link {
    color: #517fa4;
    border: 0.1rem solid #517fa4; }

    .social-icons-item:nth-child(6) .social-icons-link {
    color: #0077b5;
    border: 0.1rem solid #0077b5; }

前言

CSS預處理器,增加了一些編寫的特性,也可以說是運用程式化的方式寫CSS。

  • 其中SASS最廣泛使用:Sass包含SASS與SCSS兩種
    • 兩者之間不同之處有以下兩點:
    • 1.文件擴展名不同,Sass 是以“.sass”後綴為擴展名,而SCSS 是以“.scss”後綴為擴展名
    • 2.語法書寫方式不同,Sass是以嚴格的縮進式語法規則來書寫,不帶大括號({})和分號(;),而SCSS的語法書寫和我們的CSS語法書寫方式非常類似。

      安裝sass

      sass-github
  • 在專案底下,安裝
    1
    npm install -g sass
  • 安裝後,建立index.scss檔案
  • 手動轉擋
    • 會出現css檔案

使用node-sass編譯

  1. 先取得package.json檔案
    安裝語法:npm init --yes
    (要注意安裝的路徑位置)

  2. 安裝node-sass
  • npm i -g node-sass (i -> install)
  • 查尋安裝是否完成
  1. 將檔案編譯為css
    建立css(資料夾)

    使用watch,使每次修改sass檔案時,會自動編譯到css中

  • 在package.jason檔案中的"scripts"
  • 要注意編譯資料的位置
    • css :為資料夾路徑
    • scss/main.scss:建立的css路徑
1
2
3
"scripts": {
"watch": "node-sass -o css scss/main.scss -w"
}
  • 在終端機要輸入
    npm run watchcontrol+c退出

基本語法實作

變數

  • 在變數前加上$,來宣告要使用的變數
  • 運用抽取變數方式,使運用版面顏色時,可以有一致性,修改版面時也較快速
  • 變數:數量不要超過10個,自己在記憶上會混亂
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 創造顏色、字大小的變數
    $white:#fff;
    $black:#000;
    .button{
    text-align:center;
    background-color:$black;
    border:1px solid $black;
    color:$white;
    }

    $font-lg:40px;
    $font-md:30px;
    $font-sm:20px;

    .footer h3{
    font-size: $font-md;
    color: $color-secondary;
    text-align: center;

    }

    scope of sass variable

  • 一般常見屬於global scope
  • 如果將變數設在,標間架構中->local scope
  • 在後面加上!global就變成全域

PS: 還是建議以global 的方式進行修改,才不會造成維護的混亂

  • 命名中使用-以及_,在sass中是一樣的
    • $font-lg改為$font_lg一樣也會有效

Nested 巢狀

1.針對nav下的ulli

1
2
3
4
5
6
7
8
9
10
11
.nav{
background-color: $color-primary;
ul li{
list-style: none;
}
a{
text-decoration: none;
font-size: $font-sm;
color: $color-secondary;
}
}
  • 轉換為css
    1
    2
    3
    4
    5
    6
    7
    8
    .nav {
    background-color: orange; }
    .nav ul li {
    list-style: none; }
    .nav a {
    text-decoration: none;
    font-size: 20px;
    color: gray; }

2.增加hover的效果

  • &,來指出parent element:在這便是指<a>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.nav{
background-color: $color-primary;
ul li{
list-style: none;
}
a{
text-decoration: none;
font-size: $font-sm;
color: $color-secondary;
&:hover{
color: $color-tertiary;
}
}
}
  • 轉換為css
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    .nav {
    background-color: orange; }
    .nav ul li {
    list-style: none; }
    .nav a {
    text-decoration: none;
    font-size: 20px;
    color: gray; }
    .nav a:hover {
    color: royalblue; }

巢狀層級不可以太多層,否則會出現效率問題

@import 是什麼

  • import 讓我們可以拉出特定區塊或是根據功能性不同拆成不同區塊,來撰寫scss,並利用@import放入主要的scss檔案,最後彙整到同一個css之中。
  • 再用一個css引入(@import),各個功能
  • 要引入的檔案命名:在要import的檔案要加_

六角學院

_test.scss為撰寫footer樣式的檔案

1
2
3
4
.footer h3{
font-style:italic ;
border: blue 3px solid;
}

main.scss 要引入檔案的主要檔案

1
@import "test";

轉譯為css(main.css)

1
2
3
.footer h3 {
font-style: italic;
border: blue 3px solid; }

@mixin 與 @include

  • 當在多個地方想使用同一種style的方式。可以組成一組的樣式,並於scss中重複使用。
  • @mixin 開頭,並自定義一個名稱
  • 需要它的時候就用 @include呼叫
  1. 設定對齊方式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @mixin horizontal-list{
    li{
    display:inline-block;
    margin:{
    left:-2px;
    right:2em;
    }
    }
    }

    /*當要引用時*/
    nav ul{
    @include horizontal-list
    }

  2. 調整字體大小(以帶參數的方式)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 發現h1,h3樣式一樣
    @mixin headingStyles($fontSize){
    //以代參數方式來放入不同字體大小的變數設定
    font-size: $fontSize;
    color: $color-secondary;
    text-align: center;
    }


    .banner h1{

    @include headingStyles($font-lg);
    }
    .footer h3{

    @include headingStyles($font-md);
    }
  • 在css的地方,可以看到字的大小不同
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    .banner h1 {
    font-size: 40px;
    color: gray;
    text-align: center; }

    .footer h3 {
    font-size: 30px;
    color: gray;
    text-align: center; }

  1. 加入動畫效果
  • footer h3加上hover
  • @mixin transition($param...)加上設定參數特性
    • 當要同時設定特性中的多個值時,要記得在參數後面加上...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 發現h1,h3樣式一樣
@mixin headingStyles($fontSize){
//以代參數方式來放入不同字體大小的變數設定
font-size: $fontSize;
color: $color-secondary;
text-align: center;
}

@mixin transition($param...) {
transition: $param;
}
.banner h1{

@include headingStyles($font-lg);
}
.footer h3{

@include headingStyles($font-md);
@include transition(color .5s ,background-color 1s);
&:hover{
color:$color-tertiary;
background-color: $color-primary;
}
}
  • 轉譯為css
    1
    2
    3
    4
    5
    6
    7
    8
    .footer h3 {
    font-size: 30px;
    color: gray;
    text-align: center;
    transition: color 0.5s, background-color 1s; }
    .footer h3:hover {
    color: royalblue;
    background-color: orange; }

Day27:小事之 Transition 與 Animation
CSS3 Animation

新手也可以輕鬆玩轉 SASS - @mixin and @include

Functions

  • 透過函式的建立,可以在需要使用時,不斷地呼叫使用
  • @function fontSize($size){ @return $size*2; }建立函式
1
2
3
4
5
6
7
8
9
10
11
12
13
@function fontSize($size){
@return $size*2;
}


h1{


.banner p{
font-size: fontSize($font-sm);
//字的大小會變成 20px*2 =>40px
}

轉譯為css

1
2
.banner p {
font-size: 40px; }
  • 將文字大小,預先設定預設值
1
2
3
4
5
6
7
8
9
10
//設定預設為25px
@function fontSize($size:25px){
@return $size*2;
}



.footer p{
font-size: fontSize();
}

轉譯為css

1
2
3
.footer p {
font-size: 50px; }
/* 25*2=>50 */
  • 若插入數字
1
2
3
4
.footer p{
font-size: fontSize(30px);
}

  • 轉譯為css
    1
    2
    3
    .footer p {
    font-size: 60px; }
    /* 30*2=>50 */

    內建函式介紹

  1. lighten()
    1
    2
    .nav{
    background-color: lighten($color-primary,20%);}
    css
    1
    2
    .nav {
    background-color: #ffc966; }
  • 顏色變淡
  1. darken()
    1
    2
    .nav{
    background-color: darken($color-primary,20%);}
  • 編譯為css
    1
    2
    .nav {
    background-color: #996300; }

3.transparentize()

  • 透明度從0-1 (1是完全透明)
    1
    2
    .nav{
    background-color: transparentize($color-primary,0.6);}
  • 編譯為css
    1
    2
    .nav {
    background-color: rgba(255, 165, 0, 0.4); }

4.mix()

  • 將顏色混合
    1
    2
    .nav{
    background-color: mix(blue,green);}
    css
    1
    2
    .nav {
    background-color: #004080; }

加入百分比(利用百分比來調配顏色的比重)

  • mix(blue,green,10%)表示只有10%的藍色,90%為綠色
    1
    2
    .nav{
    background-color: mix(blue,green,10%);}
    css
    1
    2
    .nav {
    background-color: #00731a; }

補充scss檔案編制

  • 主要視自己專案上的區分來編制
    vendor:外部套件,放置bootstrap或其他frameworks、liberaries、hover.css
    utils(helpers):工具類的class,放置字的大小、margin、border顏色設置、hover效果
    partials:放置一些部分區域的css,如:nav、footer; layout: (共通的佈局)如表頭、表尾,就是每頁都會出現
    而這幾個檔案,放在main.scss要有順序

    base:p段落、h1..等的全站設定(css reset)
    components :元件,如按鈕、卡片的設定

參考資料:alphacamp-Sass/SCSS 基本語法介紹,搞懂CSS 預處理器

成品

觀察功能需求

  • 搜尋框,輸入搜尋關鍵字,下方會列出5筆列表
    • 有圖片縮圖、影片標題、影片描述
  • 按下next page 會取得下5筆資料
  • 按下prev page,會取得上5筆資料

ajax 在同一個頁面,不做刷新就可以改變頁面的內容。
q: query

youtube API(application programming interface)資料查看

YouTube 資料 API 參考手冊

取得授權:憑證

API 金鑰:AIzaSyCKPRCaNS-PQJLl2jzoQEf-O4I0tnrtd8M

1
2
jQuery API D ocument => 表示看官方文件
串API =>

檢視範例,ajax資料的情形

JS 部分

1.嘗試串接Youtube API

  • 首先需考量,我們所需要的資料參數有哪些(
  • 在抓取成功的部分,要設置抓取五筆搜尋到的五筆資料,並將其呈現於頁面
    • 除了5筆資料外,還需要跳轉上、下頁的按鈕
      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
      function getVideo() {
      let value = $('#search-field').val();
      let youtubeURL = "https://www.googleapis.com/youtube/v3/search";
      $.ajax({
      type: "GET",
      url: youtubeURL,
      data: {//將要放入網址的參數放在這
      part:
      'id,snippet',// 必填,把需要的資訊列出來
      q: value,// 查詢文字
      maxResults: 5,// 預設為五筆資料,可以設定1~50
      type: "video",
      key: 'AIzaSyCKPRCaNS-PQJLl2jzoQEf-O4I0tnrtd8M'// 使用 API 只能取得公開的播放清單

      },
      dataType: "json",
      success: function (data) {
      //console.log(data);
      let nextPageToken = data.nextPageToken;
      let prevPageToken = data.prevPageToken;

      //試著將收到的資料傳入,並呈現於畫面中
      insertItems(data);

      getBtn(data, prevPageToken, nextPageToken)


      }, error: function (err) {
      console.log('oh no');
      }
      });
      }
      網址放入參數
      [JS] 使用 JavaScript 解析網址與處理網址中的參數(URL Parameters)

2.將資料呈現於頁面(insertItems())

  • 透過迴圈方式將要抓取的資料依序填入
  • 觀察原本畫面結構,並依據去找尋資料中符合的資料
    • videoId、videoTitle、description、channelTitle…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function insertItems(item) {
let output = '';
$.each(item.items, function (index, value) {
let videoId = item.items[index].id.videoId;
let videoTitle = item.items[index].snippet.title;
let description = item.items[index].snippet.description;
let thumbnailURL = item.items[index].snippet.thumbnails.high.url;//高解析度影片縮圖
let channelTitle = item.items[index].snippet.channelTitle;
let publishedDate = item.items[index].snippet.publishedAt;
// 按鈕



output += `<li><div class="list-left">
<img src=" ${thumbnailURL}"></div>
<div class="list-right">
<h3>
<a data-fancybox data-type="iframe" data-src="https://www.youtube.com/embed/${videoId}" "href="javascript:;"> ${videoTitle} </a></h3> <small>By <span class="cTitle"> ${channelTitle}</span> on ${publishedDate}</small>
<p> ${description} <p></div></li> <div classs="clearfix"></div>
`

$('#results').html(output);
});
};

3.製作上、下頁的按鈕鍵

  • 注意該函式要帶入的參數有哪些
  • 我們要判斷為,在第一頁時,只有下一頁的按鈕
    • 判斷方式為,(!prevPageToken)沒有上一頁的token
    • (截圖)
  • 在判斷之中,我們需要將要插入的標籤與內容,放入,並append到畫面要呈現的位置
  • 注意:在插入的button之中,加入data-token="${nextPageToken}" data-query="${value}",用於後續抓取屬性內容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getBtn(value, prevPageToken, nextPageToken) {
console.log(nextPageToken)
if (!prevPageToken) {
var btnOutput = $(`<div class="button-container">
<button id="next-button" class="paging-button" data-token="${nextPageToken}" data-query="${value}" onclick="pressNext();"> Next Page</button></div>`
)
$("#buttons").append(btnOutput);
} else {
var btnOutput = $(`<div class="button-container"><button id="prev-button" class="paging-button" data-token="${prevPageToken}" data-query="${value}" onclick="pressPrev();"> Prev Page</button>
<button id="next-button" class="paging-button" data-token="${nextPageToken}" data-query="${value}" onclick="pressNext();">Next Page</button></div>`)
$("#buttons").append(btnOutput);
}

}

Youtube:Implementation: Pagination

4.下一頁點下後,下五筆的資料

  • 同樣以ajax的方式來抓取
    • 在參數的地方我們要抓取的是,按取下一頁的token
  • success之中所應用的函示,同樣為插入5筆的資料,以及上下頁的按鈕
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
//取得下一頁的資料
function pressNext() {

let youtubeURL = "https://www.googleapis.com/youtube/v3/search";
let token = $('#next-button').data('token');
let value = $('#search-field').val();
$.ajax({
type: "GET",
url: youtubeURL,
data: {//將要放入網址的參數放在這
part:
'id,snippet',// 必填,把需要的資訊列出來
q: value,// 查詢文字
pageToken: token,
maxResults: 5,// 預設為五筆資料,可以設定1~50
type: "video",

key: 'AIzaSyCKPRCaNS-PQJLl2jzoQEf-O4I0tnrtd8M'// 使用 API 只能取得公開的播放清單

},
dataType: "json",
success: function (data) {
console.log(data);
let nextPageToken = data.nextPageToken;
let prevPageToken = data.prevPageToken;

// 清空內容
$('#results').html('');
$('#buttons').html('');
//試著將收到的資料傳入,並呈現於畫面中
insertItems(data);

getBtn(data, prevPageToken, nextPageToken)


}, error: function (err) {
console.log('oh no');
}
});

}

5.上一頁

  • 同樣的抓取方式,只有要帶入的資料有些差異
  • token = $('#prev-button').data('token');
    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 pressPrev() {
    // 清空內容
    $('#results').html('');
    $('#buttons').html('');
    let youtubeURL = new URL(`https://www.googleapis.com/youtube/v3/search?`);
    let token = $('#prev-button').data('token');
    let value = $('#search-field').val();
    $.ajax({
    type: "GET",
    url: youtubeURL,
    data: {//將要放入網址的參數放在這
    part:
    'id,snippet',// 必填,把需要的資訊列出來
    q: value,// 查詢文字
    pageToken: token,
    maxResults: 5,// 預設為五筆資料,可以設定1~50
    type: "video",

    key: 'AIzaSyCKPRCaNS-PQJLl2jzoQEf-O4I0tnrtd8M'// 使用 API 只能取得公開的播放清單

    },
    dataType: "json",
    success: function (data) {
    console.log(data);
    let nextPageToken = data.nextPageToken;
    let prevPageToken = data.prevPageToken;

    // 清空內容
    $('#results').html('');
    $('#buttons').html('');
    //試著將收到的資料傳入,並呈現於畫面中
    insertItems(data);

    getBtn(data, prevPageToken, nextPageToken)


    }, error: function (err) {
    console.log('oh no');
    }
    });

    }

HTML5 自定義屬性 data-* 和 jQuery.data 詳解
2018.06.20

[技術分享] 什麼是 HTML 5 中的資料屬性(data-* attribute)

6.運用fancybox的方式彈出

  • 使用fancyBox展示影片

  • 使用iframe連結欲嵌入的外部影片連結

    • iframe 是框架的一種,也稱為內置框架或內聯框架,用來在網頁內嵌入另外一個網頁
  • 透過CDN方式連結fancybox套件

    1
    2
    3
    <!-- fancyBox -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script>
  • 在我們點選該影片名稱區,插入影片id

    1
    2
    <h3><a data-fancybox data-type="iframe" data-src="https://www.youtube.com/embed/${videoId}" "href="javascript:;"> ${videoTitle} 
    </a></h3>
    1
    2
    3
    4
    5
    6
    7
    $('[data-fancybox]').fancybox({
    toolbar : false,
    smallBtn : true,
    iframe : {
    preload : false
    }
    })

    [jQuery] - 練習-Youtube Search Engine


補充知識:
XMLHttpRequest(XHR):是一種規範,用來發ajax使用

token(令牌):唯一的、可以認證身份或取得資料

GET:向伺服器發request,(伺服器會告訴我們要發伺服器的網址,我們向它請求資訊)

用瀏覽器debug

  • 可在watch加上要觀察的變數

參考資料
[30apis] Day 7 : YouTube Data API + 基礎 Fetch API
How To Implement A Youtube Video Search Using Youtube Data API V3
Youtube Data API 使用手札
Youtube Data API 申請
配額

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"error": {
"code": 403,
"message": "The request cannot be completed because you have exceeded your \u003ca href=\"/youtube/v3/getting-started#quota\"\u003equota\u003c/a\u003e.",
"errors": [
{
"message": "The request cannot be completed because you have exceeded your \u003ca href=\"/youtube/v3/getting-started#quota\"\u003equota\u003c/a\u003e.",
"domain": "youtube.quota",
"reason": "quotaExceeded"
}
]
}
}

favicon.ico error

問題:

  • script.js: Allow attribute will take precedence over ‘allowfullscreen’.