今天看到澎澎的教學影片,覺得觀念清晰好懂,就紀錄一下這重要觀念。

在 JavaSctip 裡面如果故意把宣告變數擺在最後面,它仍就會因為 Hoisting 的效果被放到最前面。
( 注意我只說宣告變數 ( var a ),沒說變數賦值 ( a = 10 ) )

閱讀更多

當我點擊藍色區塊時會改變顏色

1
<div id="app"></div>
1
2
3
4
5
6
7
8
9
10
// 綁定 DOM
let app = document.querySelector('#app')

// 綁定事件
app.addEventListener('click', function () {
//計時器
setTimeout(function () {
this.style.background = 'red'
}, 2000)
})

但是這樣的執行結果會顯示 fail

console.log 看一下,會發現 this 是指向 window 的。

window 是沒有 style 屬性的,所以會顯示 undefined。

要解決這樣的問題就是在計時器外層將 this 命名到一個變數上,然後在計時器內層呼叫。

為甚麼要這麼做?

console.log 看一下外層的 this

點擊前

點擊兩秒後

會發現在這一層是有 background style 屬性的。

所以計時器在執行到 self 時會呼叫到外層含有 style 的屬性的 this ,這樣就可以改變樣式了。

不過有了箭頭函式後,就不需要這麼麻煩了,因為箭頭函式會指向聲明時所在作用域下的 this 值。

1
2
3
4
5
6
7
8
9
10
11
12
// 綁定 DOM
let app = document.querySelector('#app')

// 綁定事件
app.addEventListener('click', function () {
// 箭頭函式是在這一層作用域下聲明的,所以會拿到這一層的 this 值

// arrow function 計時器
setTimeout(() => {
this.style.background = 'red'
}, 2000)
})

codePen

參考資料

尚硅谷 Web 前端 ES6 教程,涵盖 ES6-ES11

以下示範 function & arrow function 的差異。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//具名函釋
function test1() {
console.log(this.name)
}

// 箭頭函式
let test2 = () => console.log(this.name)

window.name = '外層'

const obj = {
name: 'ken',
}

// 具名函示會看命名變數作用域下的 this
test1() // "外層"
test1.call(obj) // "ken"

// 箭頭函式永遠指向 window
test2() // "外層"
test2.call(obj) // "外層"

如果想改變函示內的 this 值可以用 call 方法,但從結果來看,這對箭頭函式來說是無效的。

總結:
test1 具名函示的 this 會指向跟函示同層作用域下命名變數的 this 值。
test2 箭頭函示的 this 會指向聲明時所在作用域下的 this 值。

codePen

參考資料

尚硅谷 Web 前端 ES6 教程,涵盖 ES6-ES11

套件
首先安裝 npm: npm install vue-loading-overlay
再到 main.js 載入

1
2
3
4
5
6
7
// Import component
import Loading from 'vue-loading-overlay'
// Import stylesheet
import 'vue-loading-overlay/dist/vue-loading.css'

// 因為是全域每個 component 都會用,所以用 Vue.component
Vue.component('Loading', Loading)


全域 Loading

接下來要在 components 裡面加入讀取的判斷式跟綁定
先將 lading 預設好,只有在等待的時間下才會轉 isLoading: false,

然後把範例拿過來用

在 div 內一層加上 <loading :active.sync="isLoading"></loading>

接下來要在 AJAX 的行為上面新增 isLoading: false,
在啟用 getProducts 的時候就會觸發 loading ( true ),在完成的時候結束( false )
範例如下:

1
2
3
4
5
6
7
8
getProducts() {
const api = `${process.env.APIPATH}/api/${process.env.MYPATH}/products`
this.isLoading = true
this.$http.get(api).then((response) => {
this.products = response.data.products
this.isLoading = false
})
},

然後再重新整理,畫面中間就會出現 Loading 的效果,
再試試按下編輯或是新增然後直接按下確認也會有 Loading 的效果

這樣全域就完成了!!


局部 Loading

再來要做局部的,我們要在新增或是編輯圖片那邊加上 loading 的效果

要加的地方在下圖紅框處

這邊偷懶一下直接用 CDN 載入 font-awesome 到 index.html


然後再到 Animating Icons 選一個自己喜歡的 loading 樣式
這邊用 fa-spinner fa-spin 作範例
因為要在上傳圖片的旁邊顯示 loading 效果,所以我們把 fa-spinner fa-spin 加在 label 旁邊,

再到 data 函式加入決定局部 loading 的變數

再到模板那邊用 v-if 判斷做動態綁定

然後在上傳圖片的函示( uploadImg )內加入局部 loading 判斷

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
uploadImg() {
// 在拉圖片進去讀取的時候 fileUpLoading 會是 true
this.status.fileUpLoading = true
const uploadFile = this.$refs.files.files[0]
const formData = new FormData()
formData.append('file-to-upload', uploadFile)
//接下來定義路徑
const url = `${process.env.APIPATH}/api/${process.env.MYPATH}/admin/upload`
this.$http
.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((res) => {
console.log(res.data)
// AJAX 結束後 fileUpLoading 就 false
this.status.fileUpLoading = false
if (res.data.success) {
// this.tempProduct.imgUrl = res.data.imageUrl
console.log(this.tempProduct)
this.$set(this.tempProduct, 'imgUrl', res.data.imageUrl)
}
})
}

先將 selectv-model 做作雙向綁定,因為 number 是空字串,所以在一開始 option 會指定到 value 為空值的選項。
假設 option 裡面沒有 value ,那 option 就會顯示 2020 等年分,但給了 value 就會顯示 value 值。

閱讀更多

文字輸入

v-model 可以做雙向綁定,但它同時也等於 v-bind 的 value 跟偵聽 input 的事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
<!-- <input type="text" v-model="message"> -->
<input type="text" :value="message" @input="setMessage" />
<h1>{{message}}</h1>
</div>

<script>
new Vue({
el: '#app',
data: {
message: '',
},
methods: {
setMessage(e) {
this.message = e.target.value
},
},
})
</script>

codepen
setMessage 函式會接收一個參數(evt 事件),並用事件發出的 target 找到 input 元素,那 e.target.vlaue 就是使用者輸入的值。


多行輸入: textarea

用 v-model 一樣可以雙向綁定,但是他不會換行,範例如下

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

<script>
new Vue({
el: '#app',
data: {
message: '',
},
})
</script>

codepen

這時候就要用 pre 標籤,它可以保存 message 裡面的換行字元,範例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<textarea v-model="message"></textarea>
<!-- <h1>{{message}}</h1> -->
<pre>{{message}}</pre>
</div>

<script>
new Vue({
el: '#app',
data: {
message: '',
},
})
</script>

codepen

或是不想用 pre 標籤鄉用 h1 的話可以在 css 裡面加上 white-space: pre; 也會有同樣的效果。

也可以套用一開始單行 v-model 一開始單行 v-model 轉換成 v-bind 跟 v-on 一樣可以運行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
<textarea @input="setMessage">{{message}}</textarea>
<pre>{{message}}</pre>
</div>

<script>
new Vue({
el: '#app',
data: {
message: '',
},
methods: {
setMessage(e) {
this.message = e.target.value
},
},
})
</script>

codepen


參考資料:精通 VueJS 前端開發完全指南

checkbox

單選互動按鈕:

將 true & false 綁定到一個值上面,並做出沒勾選的話就會跳出 alert

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="app">
<input type="checkbox" id="chk" v-model="agree" />
<label for="chk">agree</label>
<h1>{{agree}}</h1>
<button @click="submit">submit</button>
</div>

<script>
new Vue({
el: '#app',
data: {
agree: false,
},
methods: {
submit() {
if (this.agree !== true) {
alert('agreeeeeeee')
return
}
// 表單送出後要做的事情...
},
},
})
</script>

codepen

多選互動按鈕:

這可以應用在客戶在什麼時段方便取貨或是什麼時方便聯絡等地方。

給定三個時段,也給三個時段的 value ,同時在點選時段的時候我希望能以陣列的方式呈現

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app">
<h1>可以聯絡的時段:</h1>
<input type="checkbox" id="chk1" value="8:00~12:00" v-model="times" />
<label for="chk1">morning</label>

<input type="checkbox" id="chk2" value="13:00~ 18:00" v-model="times" />
<label for="chk2">afternoon</label>

<input type="checkbox" id="chk3" value="19:00~21:00" v-model="times" />
<label for="chk3">evening</label>
<h2>{{times}}</h2>
</div>

<script>
new Vue({
el: '#app',
data: {
times: [],
},
})
</script>

codepen
透過勾選的順序決定誰要先呈現第一個,例如我先勾選 evening 再勾 afternoon 就會呈現下圖順序


radio

這是應用在表單填寫性別或是單個選項等地方。
給 2 個選項,在點擊 label 時會呈現 value ,要額外呈現 value 就要用 , v-model 做雙向綁定,那 v-model 要空值或是預設值都可以。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
<input type="radio" id="chk1" value="male" v-model="gender" />
<label for="chk1">male</label>

<input type="radio" id="chk2" value="female" v-model="gender" />
<label for="chk2">female</label>

<h1>{{gender}}</h1>
</div>

<script>
new Vue({
el: '#app',
data: {
gender: 'male',
},
})
</script>

codepen


參考資料:精通 VueJS 前端開發完全指南

8-1 用 v-for 把陣列轉換為一組元素

data 裡面的 todo 陣列顯示在 li 上,v-for="todos in todo" 後面的todos 代表陣列,前面的todo 代表陣列裡面的每個元素

閱讀更多

簡介

當組件化的網頁要從後端伺服器請求資料的時候,那些回傳的資料都會經過父層組件傳到子層組件去,那父層組件的參數要傳到子層組件的話就要透過 props 語法。

閱讀更多

簡介

面對複雜問題的處裡的方式就是將問題分割,而將東西分割的方式在 Vue 裡面我們稱為組件化。

大概 10 年前吧,原本一個網頁是由一個 HTML、CSS、JavaScript 所組成的,但這樣在改動某個地方的時候會非常麻煩也會擔心會不會影響到網頁其他地方。後來出現了用 JavaScript 寫成的前端框架,將網頁內部切分成很多區塊,讓這些區塊內都有獨立的 HTML、CSS、JavaScript,這樣當某個區塊改動時就不必擔心會影響到網頁內的其他區塊,也因為每個區塊都是獨立的所以重複利用,這也讓開發者大大的提升了開發效率。

下圖來自官網

組件化的思想就是盡可能的把頁面拆分成很多個小區塊,變成可重複利用的組件。

閱讀更多

介紹

在上一篇 Vue 組件化 ( 一 ) 介紹了組件話的觀念跟應用,但沒提到組件化的資料必須要用動態綁定來確保資料的獨立,所以這篇就來介紹一下組件化的 data 。

閱讀更多

在模板中可以直接使用插值語法顯示 data 中的資料,但是在某些狀況下有些資料還是要經過計算再顯示,或是多個資料結合或是重複顯示,這時候就會使用到 computed 計算屬性。

還有 v-on 監聽事件的修飾符跟實際應用。

閱讀更多

介紹

MVVM 是由 Model、View 跟 ViewModel 這三個東西之間的作用,可以比較好管理開發者的內容。

閱讀更多

前言

每當我們在命名變數的時候,都會有作用域上的困擾,或是不熟悉 var 、 let 、 const 三者之間的差別,導致環境中的變數被互相汙染,甚至影響到全域變數,為釐清這當中的觀念,決定寫一篇文章來幫助自己,方便日後回憶。

閱讀更多

前言

利用 Javascript 將資料存到瀏覽器裡面,但是因為 http request 的關係,瀏覽器並不會知道上一個跟目前的使用者是誰,這時候就需要把使用者的資料帶到後端 sever 上。

例如我在 A 電腦開啟購物網頁選購商品並存取選購的商品資料但是在 B 電腦開啟同樣的網頁但是卻沒有剛才在 A 電腦選購的資料,這是因為資料是存在自己本地的瀏覽器裡面而不是存在後端的 sever 上,如果是存在後台的 sever 上,那不管我使用哪一台點腦,都可以開啟我在 A 電腦上選購的資料。

接下來就要介紹瀏覽器是如何存取資料的。

閱讀更多

1. 選擇器的進階 Traversal(遍歷) 鄰居、爸爸與小孩

遍歷示意圖:

Traversal 這觀念就是透過 API 操作相鄰隔壁的元素,以下示範

閱讀更多

三大重點

  • 選擇器 (selector)
  • 事件觸發 (event)
  • 事件處發的回調函數

閱讀更多

簡介

Git 是一個可控制程式碼版本的工具
當我們在開發的時候為了不影響線上的產品,就會先開一個分支出來在分支上做開發,這樣既可以大膽的開發也不怕會影響到線上正在運行的版本,同時又做到程式碼的控管,是一個很方便的工具

閱讀更多

為了在 window 作業系統上執行 linux ,所以會需要安裝 WSL
WSL 又有分1 跟 2,1 的話較為簡單,以下只示範 WSL1

閱讀更多

計算用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="app">
<input type="number" v-model="a" />
+
<input type="number" v-model="b" />
=
<input type="text" v-model="ans" />
<br />
</div>

<script>
new Vue({
el: '#app',
data: {
a: 0,
b: 0,
c: 0,
},
computed: {
ans() {
return parseInt(this.a) + parseInt(this.b)
},
},
})
</script>

codepen
computed 裡面的屬性不能跟 data、methods 撞名,同樣的在 ans 不能是箭頭函式,因為用箭頭函式,那 ans 裡面的 this 就會是 window 物件


除了簡單的計算外還有進階的用法,就是 computed 裡面除了宣告成函式外還可以宣告成物件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
new Vue({
el: '#app',
data: {
a: 0,
b: 0,
c: 0,
},
computed: {
ans: {
get() {
return parseInt(this.a) + parseInt(this.b)
},
set(val) {
this.b = parseInt(val) - parseInt(this.a)
},
},
},
})

codepen
get 是指,當我需要 ans 值的時候,就會用 get 呼叫函式,取出 return 的值

set 是指,當我設定某個值到 ans 的時候,要用 set 的函式,那 set 函式它吃一個值( value ),範例是當我設定 ans 的時候就要算出 a or b 的值


參考資料:精通 VueJS 前端開發完全指南

Vue 組件是預先定義好的模組,包含 html 的視覺元素、綁定的資料跟偵聽器..等等,類似 Vue 實例,組件的好處是可以重複使用,在開發上可以只專注在一小區塊,維護也很方便

Vue.component 前面會先傳入參數的名稱,後面的參數是 optionoption 是用模板 template 定義視覺元素,也直接在模板裡面去定義內容,舉例 : 在模板裡面定義 html 的內容 ( hello world ) ,然後在 html 裡面定義 #app 並在裡面放入 my-component 標籤,而 my-component 並非是 html 標籤,是我在 Vue.component 定義好的。

Vue.component 有個特別的規範,就是前面的參數要全小寫並加上「 - 」分開,請養成習慣!,同時 Vue.component 的宣告必須在 new Vue 之前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<my-component></my-component>
</div>

<!-- 此為 Global 的 component -->
<script>
Vue.component('my-component', {
template: '<div>hello world</div>',
})

new Vue({
el: '#app',
})
</script>

此範例是全域都可以使用的
codePen


除了全域( Global )宣告以外還有 local 的宣告,它只會存在 Vue 實例裡面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<my-component></my-component>
</div>

<script>
new Vue({
el: '#app',
components: {
'my-component': {
template: '<div>hello world</div>',
},
},
})
</script>

new Vue 裡面給一個屬性 components ,屬性的 key 是字串 key my-component 也是組件名稱
codePen


但是 local 有缺點,就是如果我宣告兩個 div ,但只會顯示一個

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app">
<my-component></my-component>
</div>
<div id="app2">
<my-component></my-component>
</div>

<script>
new Vue({
el: '#app',
components: {
'my-component': {
template: '<div>hello world</div>',
},
},
})

new Vue({
el: '#app2',
})
</script>

它只會顯示一個 div

那用 Global 宣告就不會有這問題

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="app">
<my-component></my-component>
</div>
<div id="app2">
<my-component></my-component>
</div>

<script>
Vue.component('my-component', {
template: '<div>hello world</div>',
})

new Vue({
el: '#app',
})

new Vue({
el: '#app2',
})
</script>

這樣就會有兩個實例
codePen


參考資料:精通 VueJS 前端開發完全指南

防止預設事件發生: preventDefault

a 連結預設是開新分頁,但我想要點 a 連結就跳出 alert 同時又不要開新的分頁,這時候就要用 preventDefault
先偵聽一個事件 linkClick ,並給 linkClick 一個函式,點擊 a 連結時為了要取消預設行為 ( 開新分頁 ),所以在函式內新增 e.preventDefault()

閱讀更多

函式裡面一定會帶上一個 this , this 在執行函式的時候自然就會產生,不需要特別宣告

作用域不一樣,var 的作用域在函數 (function) 裡,let 的作用域則是在區塊 (block) 裡。

6角

範例 1

1
2
3
4
5
6
7
8
9
10
var myName = '驚不驚喜'
function callName() {
console.log(this, this.myName)
}

var family = {
myName: '老王',
callName: callName,
}
family.callName()


this 會指向函式前面的物件,所以 this 顯示 family 物件, this.myName 會顯示老王


範例 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var myName = '驚不驚喜'
function callName() {
console.log(this, this.myName)
}

var family = {
myName: '來因',
callName: callName,
ana: {
myName: '安納',
callName: callName,
},
}
family.callName()
family.ana.callName()


這邊 family 裡面多了 ana 物件,
執行 family.callName() 會找到物件第一層,跟範例 1 一樣
在執行 family.ana.callName() 時,callName()的 this 會指向 ana 物件


範例 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var myName = '驚不驚喜'

function callName() {
console.log(this, this.myName)
}

var family = {
myName: '來因',
callName: function () {
console.log(this, this.myName)
},
}

// family.callName();
var callName = family.callName
callName()


如果執行 family.callName() 結果會跟範例 1 一樣,但如果重新宣告 callName 再執行結果為什麼會是 驚不驚喜 ?
因為callName 是在全域執行,所以 this 就不會指向 family 這個物件,是指向全域的 window ,而全域 windowmyName 就是 驚不驚喜
就算少了 var callName = family.callName; 結果仍是一樣


參考資料: JavaScript 核心篇

v-if

CodePen
我想透過勾選來決定要不要顯示 h1 標籤的內容,顯用 v-model 綁定屬性,再用 v-if 判斷決定與否

閱讀更多

v-bind

v-bind 指令是用來把一個數值綁定到 HTML 屬性上,因為到後期會大量用到,所以會使用縮寫 “ : “

閱讀更多

JavaScript 是直譯式語言
當 JavaScript 在函示內找不到變數就會向外查找
window === this
但 this 會隨執行環境而有所不同

閱讀更多

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×