0%

接續著上一篇的進階模板語法-01的內容繼續記錄。

Computed與Watch

Computed過濾陣列內容

之前的章節是利用按下一個鈕,觸發methods裡面的一個function進而來過濾陣列,並將過濾完的結果
呈現在畫面上。
那這邊的話,我們希望使用者輸入完內容後,就會自動的將過濾完且符合搜尋內容的條件給呈現在畫面上。
那這樣的話,我們就需要用到computed來達成,不需要額外操作(像是:按下enter)才達成這種效果。

上面這個例子,當我們在input欄位裡面輸入搜尋值,此時,filterText會變動,
也就會連動到computed中的filterData,並在filterData裡面做判斷,若輸入的搜尋內容
有符合arrayData的內容的話,就回傳該元素值到filterData中,進而在畫面呈現filterData,
但以上這個例子,在資料量大的話會有效能上的議題。

使用 Computed 來呈現時間格式。

ex:

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
---HTML---
<div id="app">
<p>{{formatTime}}</p>
</div>

---JavaScript---
var app = new Vue({
el:'#app',
data:{
newDate:0
},
computed:{
formatTime: function(){
this.newDate = new Date();
var dates = this.newDate;
var year = dates.getFullYear();
var month = dates.getMonth() + 1;
var date = dates.getDate();
var hours = dates.getHours();
var minutes = dates.getMinutes();
var seconds = dates.getSeconds();
return `${year}/${month}/${date} ${hours}:${minutes}:${seconds}`;
}
}
})

以上用computed的方式,就能即時的呈現當下的時間囉~

Watch

當特定的變數變化的時候,會去執行特定的function

以上這個範例,就是利用watch去監聽trigger是否有變動,若有,就去執行相對應的function。
也就是當1秒後,trigger的值會被切回去false,也就是把rotate的效果給拿掉。

表單細節操作

透過v-for來製作selected裡面的資料
ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
---HTML---
<div id="app">
<select name="" id="" class="form-control" v-model="selected2">
<option disabled value="">請選擇</option>
<option :value="item" v-for="item in selecData">{{item}}</option>
</select>
<p>小明喜歡的女生是 {{ selected2 }}。</p>
</div>
--JavaScript---
var app = new Vue({
el:'#app',
data:{
selectData:['阿明', '力宏', '漂亮阿姨'],
selected2:''
}
})

以上的範例,就會動態的將selectData陣列裡面的元素渲染進option裡面。
但要特別記得,每個optionvalue屬性都是動態的被加入的,所以,前面要記得加v-bind
另外,當點選某個option的時候,該optionvalue會被塞到selected2裡面,
所以,最終在p段落裡面就會成現selected2的值,也就是你選取的optionvalue囉~

多選

只要在select的HTML標籤中,加入multiple就可以有多選的功能囉
ex:

1
2
3
4
5
6
7
8
---HTML---
<div id="app">
<select name="" id="" class="form-control" multiple v-model="selected2"> // 加入multiple
<option disabled value="">請選擇</option>
<option :value="item" v-for="item in selecData">{{item}}</option>
</select>
<p>小明喜歡的女生是 {{ selected2 }}。</p>
</div>

當你在select中加入multiple時,你在點選該欄位中的option時,記得按下Ctrl鍵來複選,
此時,selected2裡的內容,就是你複選完的結果囉。

閱讀全文 »

接續著上一篇的進階模板語法的內容繼續記錄。

反轉陣列元素-透過key

因為Vue在操作DOM元素的時候,是用快速置換的方式操作,導致有些元素不會被置換掉。
所以,我們會透過將key的屬性,來綁定元素某些獨有的屬性,來讓各元素的整體DOM都可以被完整置換。
ex:

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
---HTML---
<ul>
<li v-for="(item, key) in arrayData" :key="item.age">
{{ key }} - {{ item.name }} {{ item.age }} 歲 <input type="text">
</li>
</ul>
<button class="btn btn-outline-primary" @click="reverseArray">反轉陣列</button>

---JavaScript---
var app = new Vue({
el: '#app',
data:{
arrayData:[
{
name: '漂亮阿姨',
age: 24
},
{
name: '小明',
age: 10
},
{
name: '力宏',
age: 35
}
]
},
methods: {
reverseArray: function(){
this.arrayData.reverse()
console.log(this.arrayData)
}
}
})

可以看到以上這個範例,我們在ulli透過v-bind綁上key這個屬性,
而要用item.age去作為key的值,是因為每個元素的age的值都不一樣,所以,可以代表各個的元素,
用這種方式就可以整體置換對應的DOM元素,而不是只有部分的DOM元素被置換。

filter 過濾

以上這個範例,
當你在input欄位輸入內容,並按下enter後,會觸發filterData函式,
此時,會先對dataArray使用filter,當input欄位輸入的內容跟dataArray裡面的元素的name的成員屬性有匹配的話,
就會把那個物件push進去filterArray陣列裡面。
最後,在ul的區塊中去遍歷filterArray陣列裡面的元素,並用該元素的age為索引,
來置換頁面上的DOM內容。

閱讀全文 »

v-html可能被XSS攻擊

Vue的v-html的語法,盡量不要用在可以讓使用者提交資料的欄位中。
因為,有可能被有心人士使用XSS的方式,來攻擊你的網站。

v-once單次綁定

當你希望該欄位的資料,只會變更一次,那你就要使用v-once
ex:

1
2
3
<input type="text" class="form-control" v-model="text">

<div v-text="text">內容</div>

在以上這個範例,當你在input欄位輸入的內容,會更改到text成員屬性的值,
div這個內容因為有利用v-text去綁定text成員屬性的值,所以,
div內的內容,會連動input所輸入的內容。

以下是用v-once綁定更改後的內容
ex:

1
2
3
<input type="text" class="form-control" v-model="text">

<div v-text="text" v-once>內容</div>

透過在div的html標籤內,寫入v-once,我們就可以讓,div的內容,只會更動一次。

在大括號中輸入表達式

ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---HTML---
<div id="app">
{{text + rwHtml}}
{{text.split('').reverse().join('')}}
{{number1 + number2}} // 也可以在你面放入計算式
</div>

---JavaScript---
var app = new Vue({
el: '#app',
data:{
text: '這是一段文字',
rawHtml: '示範文字',
number1: 100,
number2: 400
}
})

透過資料狀態,來操作HTML屬性

我們可以透過v-bind來為HTML標籤動態綁定一些屬性,像是id或是className
而下面的範例,我們是要透過v-bind來為一個input欄位的disabled綁定一個成員屬性值。
ex:

1
2
3
4
5
6
7
8
9
---HTML---
<input type="text" class="form-control" :disabled="isDisabled">

---JavaScript---
var app = new Vue({
el:{
isDisabled:true
}
})

以上的範例,就可以看到我們透過v-binddisabled屬性透過v-bind綁定isDisabled,
如此,該input欄位的disabled屬性值會為true,造成該input欄位不能被輸入任何內容。
若你希望該input欄位可以被輸入內容的話,就只要將isDisabled改成false即可。

閱讀全文 »

在css文件中,加入以下的程式碼,就可以對div區塊做出由左到右的移動,

background顏色漸變的動畫。

接下來介紹一下上面的動畫程式碼

@keyframes example

@keyframes的右邊名稱example就是你為這段動畫效果的命名。
那這個名稱必須要跟,要做這段動畫效果的區塊中的css樣式中animation-name一樣。

animation-duration

在要做這段動畫效果的區塊中的css樣式中的animation-duration的值,
是代表這段動畫總共要做多少時間。
像以上這段codepen的範例,就是設定4s,也就是這段動畫總共時間是4秒。

那在@keyframe中,有寫0%, 25%, 50%, 75%, 100%的內容,
就像上面這張圖畫的一樣,它會將animation-duration的時間,平均分到這些區間裡面,
所以,這邊的code總共有4段,所以,4s/4 = 1s。
也就是每一段動畫的執行時間是1秒。

animation-delay

這段程式碼表示這段動畫要延後animation-delay所設定的時間後,才會開始執行這段動畫。

animation-fill-mode

這段程式碼以下三種選項可以寫:
forwards: 代表動畫效果會停留到最後的效果,以上面的codepen為例,div會停留在最後的
background:pink;left:0px;top:-2000px; 的位置。

backwards: 代表這段動畫執行完成後,執行這段動畫的區塊會回到這個區塊原本的狀態。
以上面的codepen為例,div會回到一開始的background:pink;left:0px;top:0px; 的位置。

both: 同時擁有forwardsbackwards的效果。

animation-iteration-count

這段程式碼表示你設計的這段動畫總共要執行多少次。
以上面的codepen為例,這段動畫總共會做2次。
如果你想要無限循環執行這段動畫的話,你就將這個屬性的值設為Infinity

閱讀全文 »

  1. bootstrap的載入scss檔案的細節
    如果你的all.css檔案本身就已經有引入了,bootstrap的scss的檔案時,
    記得不要再你的檔案裏面又再引入一次bootstrap的scss檔案囉~

  2. 載入bootstrap的js檔案
    當你像要利用bootstrap中,某些互動性的效果,就得載入它們家的js程式碼。
    bootstrap的js檔案,要放在</body>前面。

  3. 在bootstrap的按鈕樣式裡面
    寫法如下
    ex:

    1
    <div class="btn btn-primary">按鈕</div>

    你可以看到以上是按鈕的bootstrap寫法,
    第一個.btn的className,是用來為按鈕樣式打底的
    第二個.btn-primary的className是擴充樣式,可能是來為這個按鈕新增顏色,或者,修改該按鈕大小之類
    的功能。
    bootstrap是用這樣模組化的方式,來讓他們的框架的code比較簡潔,不會出現大量重複的code內容。

  4. 在bootstrap中的.row,原本就有display:flex的屬性了,
    所以,你不需要在.row中新增d-flex的className了。

閱讀全文 »

  1. 坊間有兩套css reset
    一套是meyerweb,另一套是Normalize。
    但要記得,它們兩個不能共同使用。
    所以,當你使用bootstrap的scss的時候,就不要再使用meyerweb了,
    因為,bootstrap的css reset就有載入normalize了。

  2. 在專案的head中,常用的語法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <head>
    <meta charset="UTF-8">
    <title>HTML、CSS教學</title>
    <link rel="shortcut icon" href="favicon.ico">
    <meta name='description' content='網站描述文字' />


    <meta property="og:title" content="FB的標題" />
    <meta property="og:description" content="FB的描述">
    <meta property="og:type" content="website" />
    <meta property="og:url" content="FB上的網址" />
    <meta property="og:image" content="FB的圖片" />

    <link href="圖片路徑" rel="apple-touch-icon" />

    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />

    <link rel="stylesheet" href="CSS檔案路徑">
    <script type="text/javascript" src="JS檔案路徑"></script>
    </head>
    閱讀全文 »

  1. 不同的物件呼叫同一個function,在該function的this會不同。
  2. 巢狀函式造成的不同的this
    a. 因為JavaScript的變數的最小區分單位是function
    b. 在JavaScript中,this變數預設綁定的是window物件
    c. 這種情況可以利用用一個變數存存外層的this,在傳入內層函式
  3. 強制綁定this
    a. 箭頭函式
    b. bind()
    c. call()
    d. apply()
    e. 關鍵字new來創建一個新物件
  4. ‘use strict’造成this無法再預設綁定成window物件了。

箭頭函式與this
首先,箭頭函式有以下幾種特性

  1. 超簡潔的寫法
  2. this變數的強制綁定
    而箭頭函式的的this變數綁定的方式有跟傳統的function不一樣
    傳統函式: 呼叫該function時的物件
    箭頭函式: 綁定定義該箭頭函式時的物件

我們直接用一個含是裡面包另一個函式的範例來看看他們的差別

ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
---傳統函式---
let obj = {
test: function(){
console.log(this); // 回傳obj物件

(function(){
console.log(this); // 回傳window物件
})();
}
}
obj.test();


---箭頭函式---
let obj = {
test: function(){
console.log(this); // 回傳obj物件

(()=>{
console.log(this); // 回傳obj物件
})();
}
}
obj.test();

來解釋一下為什麼內層函式回傳的值會不一樣。
首先,傳統函式
在外層的this回傳是obj物件,是因為呼叫test函式的物件是obj,所以,回傳obj物件。
而內層的話,是因為JavaScript的變數的最小區分單位是function,所以,在內部的立即函式的作用環境跟
外層是分隔開的,而它所擁有的this變數也是獨立的,而this變數的預設綁定是window物件,所以,最終結果才會回傳window物件。

接著,箭頭函式
外層的函式上面解釋過了,會回傳obj物件。
內層的話,會因為該立即函式被定義的時候,是在obj物件的環境下,所以,以箭頭函式定義的立即函式它的this變數會綁定obj,
而這也是為什麼它會回傳obj物件的原因。

———————我是分隔線——————————–
接下來,我來改寫一下上面的箭頭函式的範例
ex:

1
2
3
4
5
6
7
8
let obj = {
test: ()=>{
console.log(this); // 回傳window物件
(()=>{
console.log(this); // 回傳window物件
})();
}
}

我們將成員函式test也用箭頭函式的形式來定義它,
按照arrow function的特性,其this會綁定該arrow function被定義時的物件,
而物件obj在定義的時候,它是屬於window物件的其中一個屬性,所以,test的箭頭函式會綁定window物件,
而在test內層的IIFE也因為是在外層是window物件的狀態下定義的,故該IIFE的this會綁定window物件。

從上面的這些範例中,就要特別注意,你在使用arrow function在定義某函式時,其定義當下物件是誰,
如果,你有要在這個箭頭函式裡面使用this的變數的話。

———————我是分隔線——————————–
另外,特別紀錄一下,監聽是件如果也用arrow function來撰寫觸發事件的話,回傳的this也會和傳統函式不一樣
ex:

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
---傳統函式範例---
---html文件---
<button id="btn">按鈕</buntton>


---JavaScript文件---
<script>
let el = document.getElementById('btn').addEventListener('click', function(){
console.log(this); // 回傳被點擊的按鈕物件
});


---箭頭範例---
---html文件---
<button id="btn">按鈕</buntton>


---JavaScript文件---
<script>
let el = document.getElementById('btn').addEventListener('click', ()=>{
console.log(this); // 回傳window物件
});

</script>

來解釋一下
在傳統函式範例
該監聽函式的觸發事件是被button這個物件所觸發的,所以,this會是這個button物件。

在箭頭函式範例
該監聽函式的觸發事件是透過el變數來定義的,而el變數是window物件的其中一個屬性,所以,該監聽事件的箭頭函式
的this事綁定window物件。

———————我是分隔線——————————–
比較一下傳統函式在監聽事件 和 一般函式造成的this差別在哪
ex:

1
2
3
4
5
6
7
8
9
10
---傳統函式範例---
---html文件---
<button id="btn">按鈕</buntton>


---JavaScript文件---
<script>
let el = document.getElementById('btn').addEventListener('click', function(){
console.log(this); // 回傳被點擊的按鈕物件
});

我在這邊順便為傳統函式加一範例,讓整個狀況更混亂XDD

ex:

1
2
3
4
let foo = function(){
console.log(this);
}
foo(); // 回傳window物件

我在看這個範例的時候,覺得跟上面用傳統函式來撰寫監聽事件的那個範例有點混淆,
來講一下this,this是代表”觸發該事件的人”
所以,在傳統函式來撰寫監聽事件的那個範例,觸發該事件的物件是那個按鈕物件,所以,this會綁定button物件。
而這邊這個範例,
我們是利用foo變數來呼叫函式,而變數foo是window物件的屬性,所以,其實是window物件觸發了該事件,
所以,該函式裡面的this才會是window。

接續上一篇還沒介紹完的基礎Vue的功能。

computed 運算功能

computed物件中的屬性,它都會是一個function,而這些function都會回傳一個值。
另外,必須要是在同一個Vue物件底下的data物件的屬性值有更動時,computed才會被觸發。
換言之,如果不是在同一個Vue物件底下的data物件的屬性值有更動的話,computed是不會被觸發的。

上面這個例子,當你在input的欄位裡面輸入內容,
會直接在的位置,直接呈現被反轉後的字串結果。

由以上範例可知,當data物件中的text內容有被更動的時候,因為,computed中,有調用data中的text成員,
所以,computed會被觸發,而其reverseText屬性會存入函式回傳的text反轉後的字串內容,
並透過的方式,呈現在畫面上。
另外,要注意,在reverseText中,要調用同一個物件底下的成員屬性時,要記得加this

computed 和 methods的差別

computed 是在監控資料更動後,重新運算結果呈現於畫面上
一般來說不會修改資料,只會回傳用於畫面呈現的資料。
就像是在computed那邊提到的範例一樣。

methods 就是互動的函式,需要觸發才會運作,
像是:按下某個鈕,才會觸發某個事件
像是在v-on那邊提到的範例一樣。

Vue 表單與資料的綁定

將表單中的值,與陣列資料綁定在一起。
用checkBox和radioBox來舉例。
其中,checkBox可以多選,radioBox是單選。

checkBox

首先,若該選項有值的話,可以將該值塞入到一個陣列裡面。

當你按下其中一個選項,會將相對應的value塞到陣列checkboxArray裡面,
並用v-for的方式去遍歷checkboxArray這個陣列,將裡面的元素印出來。

radioBox

接下來,以radioBox為例

由上面這個例子可以看到,RadioBox是去綁定singleRadio這個值,並將該
singleRadio的結果呈現在最後的p段落裡面。其實,用法跟CheckBox差不
多啦,只是一個是多選,一個是單選,並且v-model要綁定的對象也不同
醬。

selected

接下來,以selected為例

以上面這個例子,你可以看到v-model綁定的是selected,就是被選擇的選項。
要注意,在”請選擇”的選項的value要記得給它預設值””。
而在請選擇的這個option裡面有disabled這個內容,它的意思是,當其他選
項被選擇後,”請選擇”這個選項就不能被選擇了。

元件基礎概念 - 如何自製自己的Vue元件

這邊是用計數器來作範例

首先,在製作Vue物件的內容,要寫在你創建Vue物件的內容的”前面”喔,
也就是Vue.component()的內容要寫在var app = new Vue({})的前面。
不然,自製元件會不見,不過我現在也只有發現這個現象,沒去研究這個現象。

以上這個製作元件的內容
在Vue.component中第一個引數,要丟你想製作的標籤的名稱,像這邊就
取名為countercomponent,
接著,Vue的自製元件的data物件,限定你得用function的形式回傳物件,
並在回傳的物件中加入你想要的成員。
最後,是這個自製元件的樣式
你就在template的指令裡面,加入你想要這個標籤的樣式。
最後,你在html文件中,加入妳自定義的標籤,如此,就可以達成標籤與
標籤之間,擁有自己的計數器了。

MVVM

Vue的整體概念是MVVM。
View(介面) -> ViewModel(資料繫結器) -> Model(資料狀態)
在MVVM的架構中,各部份處理的任務是

  1. 模型(Model):負責提供數據,例如:新增、刪除、修改。
  2. 介面(View):負責展示數據。
  3. ViewModel(VM):負責處理業務邏輯(像是觸發事件)。將 View 和 Model 綁定為 ViewModel,當數據發生改變,View 會即時更新。

創建Vue物件

首先,先來介紹一下怎麼在專案上使用Vue。
ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
---HTML---
<div id="app">
{{message}}
<input type="text" v-model="message">
</div>

---JavaScript---
var app = new Vue({
el: '#app',
data: {
message: '你好嗎'
}
})

在上面這個範例,在HTML文件中,我們有先為一個區塊命名一個id叫app。
接著,你在你的JS檔案裡面,創建一個變數,並用他來創建Vue的物件。
像上面這個例子,就是用app這個變數去創建Vue物件。
接著,在Vue的物件的成員屬性中,
el 是代表你要綁定區塊的id或class名稱是什麼。
通常我們不會綁定class名稱,因為,相同的class名稱可以在專案裡面重複宣告,這樣會造成
Vue的物件綁定錯誤。
所以,通常都會綁定id名稱。
data 這個成員屬性裡面,就放各種資料在裡面,像這邊就是放message這個字串成員。

Vue物件不要巢狀的方式創建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
---html---
<div id="app">
{{ text }}
<div id="app2">
{{ text2 }}
</div>
</div>

---JavaScript---
var app = new Vue({
el: "#app",
data:{
text: '這是一段話'
}
})

var app2 = new Vue({
el: "#app2",
data:{
text2 : '這是一段話2'
}
})

以上這個範例會報錯,它會說’text2 is not defined’,及瀏覽器找不到text2。
由此可知,雖然,創建兩個Vue的應用程式在同一個html文件中是沒問題的。
但是,你不能用巢狀的方式來建立Vue的應用程式,這樣會導致內層的Vue物件,
瀏覽器會找不到它,進而報錯。

閱讀全文 »