Vue-(六)HTML元素的屬性綁定

6-1.綁定資料為一個元素的class (影片)

以下寫法:會綁定css中命名為btnEnter的樣式

1
<button class="btnEnter">Enter</button>

以下v-bind寫法:會綁定JS中的屬性btnEnter的回傳值(可以是字串、物件、陣列)

1
<button v-bind:class="btnEnter">Enter</button>

完整案例示範-綁定回傳值:字串

1
2
3
4
<div id="app">
<input type="text" v-model='text'/>
<button v-bind:class='btnEnter'>Enter</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
#app{
text-align:center;
}
.enter{
background-color:green;
color:white;
border:none;
border-radius:8px;
padding:9px;
}
.enter.disable{
background-color:grey;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Vue({
el:'#app',
data:{
text:'',
},
computed:{
btnEnter(){
if(this.text.length === 0){
return 'btnEnter disable';
}else{
return 'btnEnter';
}
},
}
})

改寫-綁定回傳值:物件

  • btnEnter:true —>render出來的class會含有btnEnter
  • disabled:true —>render出來的class會含有disabled
  • disabled:false —>render出來的class不會含有disabled
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    new Vue({
    el:'#app',
    data:{
    text:'',
    },
    computed:{
    btnEnter(){
    console.log('111');
    if(this.text.length === 0){
    return {
    btnEnter:true,
    disabled:true,
    }
    }else{
    return {
    btnEnter:true,
    disabled:false,
    }
    }
    },
    }
    })

簡化寫法,只有在條件式成立為true時,class才會含有disable這個屬性

1
2
3
4
5
6
7
8
computed:{
btnEnter(){
return {
btnEnter:true,
disabled:this.text.length === 0,
}
}
}

改寫-綁定回傳值:陣列

陣列中可以放入多個字串,代表含有這些css樣式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
new Vue({
el:'#app',
data:{
text:'',
btnEnterAble:['btnEnter'],
btnEnterDisabled:['btnEnter','disabled'],
},
computed:{
btnEnter(){
if(this.text.length === 0){
return this.btnEnterDisabled;
}else{
return this.btnEnterAble;
}
}
}
})


6-2.綁定資料為一個元素的style (影片)

以下寫法:在css定義樣式

1
2
3
<div id='app'>
<h1>Hello</h1>
</div>

1
2
3
.h1{
color:red;
}

以下寫法:直接在元素中定義style

1
<h1 style='color:red'>Hello</h1>

以下v-bind寫法:動態綁定在Vue實例中的屬性字串

1
<h1 v-bind:style="h1Style">Hello</h1>

完整案例示範-綁定回傳值:字串

1
2
3
<div id="app" :style="textCenter">
<h1 :style="h1Style">Hello</h1>
</div>
1
2
3
4
5
6
7
new Vue({
el:"#app",
data:{
textCenter:'text-align:center',
h1Style:"color:red",
},
})

改寫-綁定回傳值:物件

1
2
3
4
5
6
7
8
9
10
new Vue({
el:"#app",
data:{
h1Style:{
color:'white',
fontSize:'20px',
backgroundColor:'gray'
},
},
})

改寫-綁定回傳值:陣列

陣列中放物件,會依序套用陣列中的物件所定義的樣式
補充:樣式的定義中,key要用駝峰式命名,例:”font-size”要寫為”fontSize”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const commonStyle = {
fontSize:'20px',
}
const whiteWord = {
color:'white',
}
const grayBackground = {
backgroundColor:'gray'
}
new Vue({
el:"#app",
data:{
h1Style:[commonStyle,whiteWord,grayBackground]
},
})

實作練習:

1
2
3
4
<div id="app">
<h1 :style="h1Style">Hello</h1>
<button @click="shrink">縮小</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new Vue({
el:"#app",
data:{
h1Style:{
color:'green',
fontSize:'30px',
}
},
methods:{
shrink(){
const size = parseInt(this.h1Style.fontSize.replace('px'),10);
console.log(size);
this.h1Style.fontSize = `${size-1}px`;
}
}
})

改寫為更精簡化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
new Vue({
el:"#app",
data:{
size: 40,
},
computed:{
h1Style(){
return {
color:'green',
fontSize:`${this.size}px`,
}
}
},
methods:{
shrink(){
this.size--;
}
}
})

Vue-(五)Vue實例

5-1.創建Vue實例 (影片)

「實例」為何?

* 類別:廣泛的描述、藍圖
* 實例:具體的個體
1
2
3
4
5
6
7

// 1.先描述Human類別
Human;//Human是一種類別

// 2.再創立個體,new是把類別產生一個實例的語法
const me = new Human(); //me是一個實例
const you = new Human(); //you是另外一個實例
  • 創建Vue實例的語法

    1
    2
    3
    new Vue({

    });

也可以宣告一個變數,並將將new出來的實例,assign給該變數

1
2
3
const vm = new Vue({

});


5-2.元素(el)、掛載($mount)、模板(template) (影片)

掛載(mount)?

掛載(mount):將「vue實例」與「html元素」做連結

創建Vue實例之初,在el中用css選擇器,找到元素

元素通常只有一個,所以通常都用id,而非class

1
2
3
<div id="aaa">{{msg}}</div> //Hello
<div class="bbb">{{msg}}</div> //Hi
<div class="bbb">{{msg}}</div> //{{msg}} (一個vue實例只能掛載到一個元素上,所以這裡會出錯)

1
2
3
4
5
6
7
8
9
10
11
12
const a = new Vue({
el:'#aaa',
data:{
msg:'Hello',
}
});
const b = new Vue({
el:'.bbb',
data:{
msg:'Hi',
}
});

創建Vue實例之初,在el中用元素的參照,找到元素

1
2
3
<div id="app">
{{message}}
</div>
1
2
3
4
5
6
new Vue({
el:document.getElementById('app'),
data:{
message:'Hello!',
},
})

創造Vue實例時先不掛載,之後當需要的時候再掛載到元素上

宣告一個DOM元素,id命名為app

1
2
3
<div id="app">
{{message}}
</div>

先創建Vue實例

1
2
3
4
5
const vm = new Vue({
data:{
message:'Hello!',
},
})

之後再掛載到元素上

  • 方法1:(css選擇器寫法)

    1
    vm.$mount('#app');
  • 方法2:(元素參照寫法)

    1
    vm.$mount(document.getElementById('app'));

用template模板取代html元素?

template裡面的字串內容被解析之後,會取代html元素中的內容,所以html元素可以是空的

1
<div id="app"></div>

1
2
3
4
5
6
7
const vm = new Vue({
el:'#app',
template:"<div><h1>{{message}}{{message}}</h1></div>",
data:{
message:'Hello!',
},
})

5-3.狀態(data) (影片)

Vue實例中同步宣告data

1
2
3
4
5
6
7
const vm = new Vue({
el:'#app',
data:{
x:1,
y:2,
},
})

先宣告data,再assign到Vue實例中

1
2
3
4
5
6
7
8
const data = {
x:1,
y:2,
}
const vm = new Vue({
el:'#app',
data:data,
})

data改為shorthand語法

1
2
3
4
5
6
7
8
const data = {
x:1,
y:2,
}
const vm = new Vue({
el:'#app',
data,
})

此時,vm.x等同於data.x,是同一個參照

1
2
3
4
5
6
7
8
9
10
11
12
const data = {
x:1,
y:2,
}
const vm = new Vue({
el:'#app',
data,
})

vm.x = 5;//此時,data.x = 5
console.log(data.x === vm.x);//true
console.log(vm.$data === data);//true


5-4.方法(methods) (影片)

Vue實例中宣告方法

注意:methods裡面不能用箭頭函式,因為箭頭函式中的this等於global或window,會出錯

1
2
3
4
<div id="app">
<h1>{{number}}</h1>
<button v-on:click="add">+Add {{count}}</button>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
const vm = new Vue({
el:'#app',
data:{
number:0,
count:0,
},
methods:{
add(){
this.number += this.count;
this.count += 1;
}
}
})

呼叫methods中的方法

注意:methods中的函式命名不得與data的屬性命名相同,會出錯

1
2
3
4
<div id="app">
<h1>{{number}}</h1>
<button v-on:click="add2">+Add {{count}}</button>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const vm = new Vue({
el:'#app',
data:{
number:0,
count:0,
},
methods:{
add(){
this.number += this.count;
this.count += 1;
},
add2(){
this.add();
}
}
})

5-5.計算屬性(computed) (影片)

computed代表計算之後的屬性,用物件的形式宣告

computed中的函式,一定要return一個值

==注意:==
computed裡面不能用箭頭函式,因為箭頭函式中的this等於global或window,會出錯

1
2
3
4
5
6
7
<div id="app">
<input type="number" v-model='a'>
+
<input type="number" v-model='b'>
=
<span>{{c}}</span>
</div>

在computed中有一個函式c,其中有使用到a和b,會自動偵聽a與b,當a或b有變動時,會自動重新計算c的返回值

1
2
3
4
5
6
7
8
9
10
11
12
const vm = new Vue({
el:'#app',
data:{
a:0,
b:0,
},
computed:{
c(){
return parseInt(this.a,10)+parseInt(this.b,10);
},
}
})

computed中也可以宣告物件,物件中有getter和setter

1
2
3
4
5
6
7
8
9
<div id="app">
<input type="number" v-model='a'>
+
<input type="number" v-model='b'>
=
<input type="number" v-model='c'>
<br/>
{{a}} + {{b}} = {{c}}
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const vm = new Vue({
el:'#app',
data:{
a:0,
b:0,
},
computed:{
c:{
get(){
return parseInt(this.a,10) + parseInt(this.b,10);
},
set(value){
this.b = parseInt(value,10) - parseInt(this.a,10)
}
},
}
})

5-6.偵聽器(watch) (影片)

watch 可以偵聽 data 與 computed 的屬性或方法變動

當被偵聽的“data中的屬性”有變動,就會觸發在watch中同名的函式

1
2
3
<div id="app">
<input/ type="number" v-model="value">
</div>

1
2
3
4
5
6
7
8
9
10
11
const vm = new Vue({
el:'#app',
data:{
value:0,
},
watch:{
value(val, oldVal){
console.log(`${oldVal}---->${val}`);
}
}
})

當被偵聽的“computed中的屬性或方法”有變動,就會觸發在watch中同名的函式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const vm = new Vue({
el:'#app',
data:{
a:0,
b:0,
},
computed:{
c(){
return parseInt(this.a, 10) + parseInt(this.b, 10);
}
},
watch:{
c(val, oldVal){
console.log(`${oldVal}---->${val}`);
}
}
})

進階用法:將watch中的屬性宣告為物件

watch中的value被改寫為一個物件

1
2
3
4
5
6
7
8
9
10
11
12
13
const vm = new Vue({
el:'#app',
data:{
value:0,
},
watch:{
value:{
handler(val,oldVal){
console.log(`${oldVal}---->${val}`);
},
},
}
})

  • 在物件中增加immediate屬性(true or false)
    true:在Vue實例被創建時,就會跑這個watch

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const vm = new Vue({
    el:'#app',
    data:{
    value:0,
    },
    watch:{
    value:{
    handler(val,oldVal){
    console.log(`${oldVal}---->${val}`);
    },
    immediate:true,//所以會馬上console出"undefined---->0"
    },
    }
    })
  • 在物件中增加deep屬性(true or false)
    true:當被偵聽的屬性為物件或陣列時,會去偵聽該物件或陣列裡面一層的值是否有被改變

    1
    2
    3
    <div id="app">
    <input/ type="number" v-model="value.a">
    </div>

被偵聽的value其實沒有改變,被改變的是value物件中的a,因此要新增deep屬性去偵聽value物件內層的a值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const vm = new Vue({
el:'#app',
data:{
value:{
a:0,
}
},
watch:{
value:{
handler(val,oldVal){
console.log(`${oldVal.a}---->${val.a}`);//"1---->1"
},
deep:true,
},
}
})


5-7.生命週期 (影片)

Vue實例從創建、更新、消滅的過程中,中間過程會去執行生命週期函式(lifecycle hooks function)

主要四個步驟:
1.建立—> 2.掛載—> 3.更新—> 4.消滅

  1. 建立(唯二兩個在server side rendering)
    • beforeCreate():Vue建立之前
    • created():Vue建立之後,data與computed中的屬性放到Vue實例中,此時用this.拿得到data與computed中的屬性
  2. 掛載

    • beforeMount():掛載之前
    • mounted():掛載之後,經常用ajax取得資料 並且把資料塞進 data
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      const vm = new Vue({
      el:'#app',
      data:{
      list:[],
      },
      mounted(){
      $.getJSON('...',(data)=>{
      this.list = data;
      })
      }
      }
      })
  3. 更新

    • beforeUpdate():更新之前
    • updated():更新之後
  4. 消滅
    • beforeDestroy():消滅之前
    • destroyed():消滅之後

5-8.實作「密碼強度檢查」 (影片)

  • codepen實作結果
    1
    2
    3
    4
    5
    6
    7
    <div id="app">
    <input id="inputBox" v-bind:type="showType" v-model="password" placeholder="請輸入密碼"/>
    <button id="statusBtn" v-on:click="changeStatus">{{statusBtn}}</button>
    <button>確定送出</button>
    <br/>
    <span>密碼強度:{{strength}}</span>
    </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
31
32
33
34
35
36
37
38
const vm = new Vue({
el:'#app',
data:{
password:'',
show:false,
statusBtn:'顯示密碼'
},
methods:{
changeStatus(){
this.show = !this.show;
}
},
computed:{
showType(){
if(this.show) {
this.statusBtn = '隱藏密碼';
return 'text';
}
else{
this.statusBtn = '顯示密碼';
return 'password';
}
},
strength(){
let score = this.password.length;
if(/[A-Z]/.test(this.password)) score *= 1.25;
if(/[a-z]/.test(this.password)) score *= 1.25;
if(/[0-9]/.test(this.password)) score *= 1.25;
if(/[^A-Za-z0-9]/.test(this.password)) score *= 1.25;

if(score>40) return "Perfect";
if(score>30) return "Great";
if(score>20) return "Good";
return "Weak"
}
}

})

5-9.片尾彩蛋:你聽過Single source of truth嗎? (影片)

  • 以下這種寫法,要找到有‘被選擇的項目’,有兩個data參照來源
    1. a,b,c各自的值
    2. selected陣列
      有兩種參照來源就不符合single source原則
      1
      2
      3
      4
      5
      6
      7
      <div id="app">
      <input type="checkbox" :check='a' @change="changeStatus('a')">A:{{a}}</input>
      <input type="checkbox" :check="b" @change="changeStatus('b')">B:{{b}}</input>
      <input type="checkbox" :check="c" @change="changeStatus('c')">C:{{c}}</input>
      <br/>
      <span>Selected:{{selected}}</span>
      </div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
new Vue({
el:'#app',
data:{
a:false,
b:false,
c:false,
selected:[],
},
methods:{
changeStatus(item){
const index = this.selected.indexOf(item);
if(index == -1){
this.selected.push(item);
}else{
this.selected.splice(index, 1);
}
this[item] = !this[item] ;
},
},
})
  • 為了符合single source原則,將selected改寫為computed,確保‘被選擇的項目’資料單一一致

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    new Vue({
    el:'#app',
    data:{
    a:false,
    b:false,
    c:false,
    },
    methods:{
    changeStatus(item){
    this[item] = !this[item] ;
    },
    },
    computed:{
    selected(){
    const result = [];
    if(this.a) result.push('A');
    if(this.b) result.push('B');
    if(this.c) result.push('C');
    return result;
    }
    }
    })
  • 更進一步簡化程式:將input的data改為v-model雙向綁定,且改用filter寫法

    1
    2
    3
    4
    5
    6
    7
    <div id="app">
    <input type="checkbox" v-model='a'>A:{{a}}</input>
    <input type="checkbox" v-model="b">B:{{b}}</input>
    <input type="checkbox" v-model="c">C:{{c}}</input>
    <br/>
    <span>Selected options:{{selected}}</span>
    </div>
1
2
3
4
5
6
7
8
9
10
11
12
13
new Vue({
el:'#app',
data:{
a:false,
b:false,
c:false,
},
computed:{
selected(){
return ['a','b','c'].filter(item => this[item])
}
}
})

學習來源

Vue-(四)模板語法

4-1.用括號語法,插入動態的數值或文字 (影片)

雙大括號:動態綁定

1
2
3
<div id="app">
<span v-once>{{message}}</span>
<div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
message:'Hello',
},
})

v-once:模板只渲染一次,不被二次變更

第一個”“因為加上v-once,即使按button會執行函式改變message的值,但第二個”“在畫面中,並不會被重新渲染

1
2
3
4
5
6
7
<div id="app">
<span v-once>{{message}}</span>
<br/>
<span>{{message}}</span>
<br/>
<button v-on:click="append">Append</button>
</div>

1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:"#app",
data:{
message:'Hello',
},
methods:{
append(){
this.message += "!";
},
}
})

v-html:渲染出html字串

1
2
3
<div id="app">
<span v-html="message"></span>
</div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
message:'<h1 style="color:red;">Hello</h1>'
},
})

使用v-html的風險:
因為允許使用者輸入的內容包含html,使用者可以故意用 ‘‘,裡面包了挖礦或攻擊程式。
所以使用v-html時,要確保資料來源,資料來源應當是資料庫中的安全內容。


4-2.v-bind, v-on指令 (影片)

v-bind:透過資料綁定,改變某個屬性的值

1
2
3
<div id="app">
<input type="checkbox" v-bind:checked="check_status">
</div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
check_status:false,
},
})

v-on:用來偵聽DOM事件,以改變資料

  • v-on:click
  • v-on:load
  • v-on:mouseover
  • ….其他事件
    1
    2
    3
    4
    <div id="app">
    <input type="checkbox" v-bind:checked="check_status">
    <button v-on:click="change">Change status</button>
    </div>
1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:"#app",
data:{
check_status:false,
},
methods:{
change(){
this.check_status = !this.check_status;
}
}
})

v-bind也可以加入表達式

表達式:用()括起來會是一個值,就代表它是一個表達式

1
2
3
4
5
<div id="app">
<h1>{{count}}</h1>
<input type="checkbox" v-bind:checked="(count%2==0)">
<button v-on:click="add">Add</button>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
new Vue({
el:"#app",
data:{
count:0,
check_status:false,
},
methods:{
add(){
this.count += 1;
}
}
})

雙大括號中也可以使用表達式

1
2
3
4
<div id="app">
<h1>{{count*2}}</h1>
<button v-on:click="add">Add</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:"#app",
data:{
count:0,
},
methods:{
add(){
this.count += 1;
}
}
})

4-3.v-bind, v-on的縮寫 (影片)

  • v-on:click ——–> @click
  • v-bind:xxx ——–> :xxx

4-4.雙向綁定的v-model (影片)

v-model

1
2
3
4
5
<div id="app">
<span>{{message}}</span>
<br/>
<input type="text" v-model="message"/>
</div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
message:'',
},
})

重點釐清

  • v-bind: 單向綁定
  • v-model: 雙向綁定

學習來源

Hiskio-姚偉揚老師-精通 VueJS 前端開發完全指南

Vue-(三)基本概念

3-1.關於Vue (影片)

followMVVM架構

  • 透過DOM裡面的監聽event來控制/影響View Model,然後去修改Model中的資料內容;
  • 當Model中的資料變更,會讓View Model知道,再去修改相對應DOM中的內容

Vue的學習重點

3-2.Hello World (影片)

創建新的html模板

![](https://i.imgur.com/8t8CEQP.png)

加入vue的cdn

cdnjs網站上,搜尋vue,將其cdn複製貼上html的head中,為一個script tag,即可使用vue 的library

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.8/vue.min.js"></script>
</head>
<body>

</body>
</html>

在html的body中創建一個容器

讓這個容器可以跟vue做綁定,習慣用div,並給予一個id(習慣會命名為app)

1
2
3
<body>
<div id="app"></div>
</body>

在html的body中宣告一個vue

先有一個script tag,接這用new vue的方式去宣告出一個vue的實體(vue裡面是一個{}物件)

1
2
3
4
5
6
7
8
<body>
<div id="app"></div>
<script>
new Vue({

});
</script>
</body>

將該vue綁定到某個元素(id)上面

在Vue實例中,使用el屬性,其值為html中定義的元素,兩者作綁定

1
2
3
4
5
6
7
8
9
10
11
12
13
new Vue({
el:"#app",
});
```
### 定義vue中的data
在Vue實例中,使用data屬性,並以物件的寫法,將資料放於其中
```htmlmixed=
new Vue({
el:"#app",
data:{
message:"Hello world!",
}
});

data被呼叫使用

用大括號呼叫出data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
{{message}}
</div>
```
### html模板與vue的綁定大功告成!

存檔之後,點開html檔案,在瀏覽器上可以看到message被呈現出來

![](https://i.imgur.com/Q2IBvDL.png)

## 3-3.相對於「命令式」與「宣告式」渲染 [(影片)](https://hiskio.com/courses/145/lectures/5327)
### 製作一個計數器(聲明式寫法):給他一個目標

先在html中宣告一個div容器,命名id為counter,裡面有一個文字h1其中顯示data中的count;另外有一個按鈕button,如果被點按會執行add函式
```htmlmixed=
<div id="counter">
<h1>{{count}}</h1>
<button v-on:click="add">點我+1</button>
</div>

改為jquery(命令式寫法):

一個口令一個動作

1
2
3
4
<div id="counter">
<h1>0</h1>
<button>點我+1</button>
</div>

當button被點按,會執行{}中的流程:將h1中的文字轉為10進位的數字型態int,宣告其為count,完成count+=1之後,再將count存回h1中

1
2
3
4
5
$('button').click(()=>{
let count = parseInt ($('h1').text(),10);
count += 1;
$('h1').text(count);
})

![](https://i.imgur.com/RmCLUp5.png)

主流框架皆為聲明式寫法

  • 聲明式(舉一反三): React, Vue, Angular
  • 命令式(一個口令): jQuery

3-4.if-else:流程控制與迴圈 (影片)

v-if與v-else:如果為true成立,則…

v-if可以單獨存在;但是,v-else不可以單獨存在,前面一定要搭配v-if使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="app">
<span v-if="see">Now you see mee.</span>
<span v-else>Now you don't.</span>
</div>
<script>
new Vue({
el:"#app",
data:{
see:true,
},
methods:{
change_status(){
this.see = ! this.see;
},
}
})
</script>

v-for

在v-for=”step in steps”語法中,定義每次從steps中拿出來的東西是step;接著,再用”“將step的內容顯示出來

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="app">
<div v-for="step in steps">{{step}}</div>
</div>
<script>
new Vue({
el:"#app",
data:{
see:true,
steps:['步驟一','步驟二','步驟三']
},
methods:{
change_status(){
this.see = ! this.see;
},
}
})
</script>

3-5.處理使用者輸入 (影片)

偵聽事件v-on

按鈕button被偵聽點按click事件,每當click事件發生,就會執行remove

1
2
3
4
5
6
<div id="counter">
<ul>
<li v-for="item in counts">{{item}}</li>
</ul>
<button v-on:click="remove">remove a number</button>
</div>

每當remove()函式被呼叫執行,就會從this.counts陣列中拿走一個項目

1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:'#counter',
data:{
counts:[1,2,3,4,5],
},
methods:{
remove(){
this.counts.pop();
},
}
})

自動雙向綁定v-model

透過v-model語法將input跟show_word綁定,若input中的內容改變,會自動更新到data的show_word

1
2
3
4
<div id="inputer">
<h1>{{show_word}}</h1>
<input type="text" v-model="show_word" placeholder="請輸入文字內容"/>
</div>

1
2
3
4
5
6
new Vue({
el:'#inputer',
data:{
show_word:'',
},
})

3-6.實作:老梗才是好梗「Todo List」 (影片)

用內容比對刪除

如果內容重複,只會找到第一筆一樣的資料,會出錯

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
<div id="app">
<input type="text" v-model="input"></input>
<button v-on:click="addItem">add</button>
<ul>
<li v-for="item in lists">
<span>
{{item}}<button v-on:click="removeItem(item)">delete</button>
<span>
</li>
</ul>
</div>
<script>
new Vue({
el:'#app',
data:{
input:'',
lists:[],
},
methods:{
addItem(){
this.lists.push(this.input);
this.input=''
},
removeItem(item){
//只找到第一筆內容符合的項目,會出錯
const idx = this.lists.indexOf(item);
this.lists.splice(idx,1);
}
},
})
</script>

用index刪除

直接指定該index的數值,刪除在陣列中第(index+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
25
26
27
28
29
<div id="app">
<input type="text" v-model="input"></input>
<button v-on:click="addItem">add</button>
<ul>
<li v-for="(item, index) in lists">
<span>
第{{index+1}}點:{{item}}<button v-on:click="removeItem(index)">delete</button>
<span>
</li>
</ul>
</div>
<script>
new Vue({
el:'#app',
data:{
input:'',
lists:[],
},
methods:{
addItem(){
this.lists.push(this.input);
this.input=''
},
removeItem(index){
this.lists.splice(index,1);
}
},
})
</script>

3-7.Vue/React/Angular,我該上哪部攻城車? (影片)

  • React需要較多的JS基礎,因此若JS功力深厚者,React可以很快上手
  • 若為初學JS,建議可以從Vue開始學習
  • Angular學習框架成本高


Vue-(一)課程前言、(二)行前準備

1-1.老師的話 (文章)

如何設計出好架構,如何寫出好程式?
許多人問過我,要如何設計出好架構,寫出好程式 我回答的都是同一個方法: 空氣朋友 在你寫 code 時請你想像一個不存在的朋友 你要向他解釋你寫出來的每一行程式碼,他甚至可能提問 如果在某處你無法流暢清晰的解釋 代表那個地方你必須想的更深更廣,作更多的研究 長此以往,必定可以有顯著的進步!

2-1:課程準備(影片)

  • vscode中安裝Vue 2 Snippets套件
    針對編譯器中coding,做不同文字顏色的呈現,便於檢視code
  • codepen中載入Vue
    javascript的地方新增框架vue,即可使用vue

2-2:取代var的let與const(影片)

  • var是全域變數

    1
    2
    3
    4
    全域變數var i可以在所有地方被使用
    for(var i=0;i<3;i++){
    }
    console.log(i);//會印出3
  • letconst是區域變數
    區域變數let i只在for迴圈中可以被使用

    1
    2
    3
    for(let i=0;i<3;i++){
    }
    console.log(i);//錯誤:i is not defined

const 宣告出來的變數是無法被re-assign的

1
2
3
for(const i=0;i<3;i++){
}
console.log(i);//錯誤:i無法被修改

  • const被宣告為物件,是可以改變其中的內容
    const若被宣告為物件,const本身無法被重新re-assign,但是物件{}其中的內容是可以重新被re-assign

    1
    2
    const c ={x:0};
    c.x = 3;
  • javascript的hoisting特性
    可以先執行Function,再補宣告

    1
    2
    3
    a();//先呼叫執行
    function a(){ //再補宣告
    }

可以先呼叫a,再補宣告var;
但是,不能補宣告let

1
2
a+=1;
var a;

1
2
a+=1;//會報錯,找不到a
let a;

2-3:簡潔快速的縮寫shorthands(影片)

  • object中的屬性縮寫
    當object裡的內容,其key與value是同名的情況(key=value=x),
    1
    2
    3
    4
    5
    6
    7
    function makePoint(x,y){
    return{
    x:x,//左邊的x代表key,右邊的x代表value
    y:y,
    name:name,
    }
    }

可以改寫為

1
2
3
4
5
6
7
function makePoint(x,y){
return{
x,//x key的value也是‘x’,所以會往上找到參數‘x’
y,
name,
}
}

  • 補充:物件object
    物件的內容是由屬性組成的,而屬性是由 key-value pair 構成,value 可為任意資料型別的值,並且值是以參考型別(reference)的方式(存位置)儲存。

如何存取物件的屬性呢?有兩種方式

1
2
1. 特性存取(property access),使用 .
2. 鍵值存取(key access),使用 [ ]

1
2
3
4
5
const obj = {
'a': 'Hello World',
};
console.log(obj.a);<!--"Hello World" -->
console.log(obj['a']);<!--"Hello World" -->
  • 計算屬性
    若object中的key為動態的,key可以用中括號[]括起來,代表[]裡面是計算後的屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    function createObj(key,value){
    const obj={};
    obj[key]=value;
    return obj;
    }
    const person = createObj('name','John');
    // 會生成出一個物件
    // person={name:'John'}

    改寫為

    1
    2
    3
    4
    5
    6
    7
    8
    function createObj(key,value){
    const obj={
    [key]:value;
    };
    return obj;
    }
    const person = createObj('name','John');
    const cat = createObj('legs',4);

[]裡面也可以放運算子

1
2
3
4
5
6
function createObj(key,value){
const obj={
[key+1]:value;
};
return obj;
}

  • 函式縮寫
    當物件中有函式function()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const options={
    name:'Options',
    level:3,
    created:function(){

    },
    mounted:function(){

    },
    };

可以改寫為

1
2
3
4
5
6
7
8
9
10
const options={
name:'Options',
level:3,
created(){

},
mounted(){

},
};

2-4:便利的取出元素:解構賦值(影片)

解構賦值(Destructuring assignment)語法是一種 JavaScript 運算式,可以將陣列或物件中的資料取出成獨立變數。

  • 陣列解構(拿多個)

    1
    2
    3
    4
    const nums = [111,222,333];
    const first = nums[0];
    const second = nums[1];
    const third = nums[2];

    可以將陣列解構,改寫為

    1
    2
    3
    4
    const nums = [111,222,333];
    // const [first,second] = nums;
    const [first,second,third,forth]=nums;//forth會是undefine
    const result = first+second+third+forth;//錯誤:因為forth是undefine
  • 陣列解構(預設值)
    若想避免為undefined,可以在解構的同時給予預設值

    1
    2
    const nums = [111,222,333];
    const[first, second, third, forth=0 ]=nums;//forth會是undefine
  • 陣列解構(忽略元素,拿一個)
    假設只要拿出third為333,前面可以忽略

    1
    2
    const nums = [111,222,333];
    const [,,third] = nums;
  • 陣列解構(變數交換)

    1
    2
    3
    4
    5
    let a = 1;
    let b = 2;
    let temp = a;
    a = b;
    b = temp;

利用解構賦值做變數交換的改寫

1
2
3
let a = 1;
let b = 2;
[a,b]=[b,a]

  • 陣列解構(剩餘部分)

    1
    2
    3
    4
    5
    const nums = [1,2,3,4];
    const[first,...others]=nums;
    //
    // first = 1;
    // others = [2,3,4]
  • 物件解構

    1
    2
    3
    4
    5
    6
    const point={
    x:100,
    y:150,
    }
    const x = point.x;
    const y = point.y;

    物件解構可以用大括號{}改寫

    1
    2
    3
    4
    5
    const point={
    x:100,
    y:150,
    }
    const {x,y}= point;
  • 物件解構(預設值)
    為了避免undefined,可以在解構的同時給予預設值

    1
    2
    3
    4
    5
    const point={
    x:100,
    y:150,
    }
    const {x, y, z = 0} = point;
  • 物件解構(指派新名稱)
    透過冒號:給予新名稱

    1
    2
    3
    4
    5
    6
    7
    const point = {
    x:100,
    y:150,
    }
    const[x:px, y:py] = point;
    const result = px*py;
    const result = x*y;//錯誤:找不到x,y
  • 解構函式參數
    計算point到圓點的距離
    數學算式:(x平方+y評分)=>再開根號

    1
    2
    3
    4
    5
    6
    7
    const point = {
    x:100,
    y:150,
    }
    function distance(point){
    return Math.sqrt(point.x*point.x + point.y*point.y);
    }

可以改寫為

1
2
3
4
function distance(point){
const{x,y} = point;
return Math.sqrt(x*x + y*y);
}

或是直接在函式的參數中作解構

1
2
3
function distance({x,y}){
return Math.sqrt(x*x + y*y);
}

甚至還可以在參數中給予預設值,並重新命名

1
2
3
function distance({x:px=0;y:py=0}){
return Math.sqrt(px*px + py*py);
}

2-5:更強的字串:字串模板與多行字串(影片)

  • 字串模板(string templete)
    原始寫法
    1
    2
    3
    4
    function greet(name){
    console.log('Hello, ' + name + '!');
    }
    greet('Jack');//印出 Hello, Jack!

改寫用backtick`宣告字串模板,在要放入變數的地方用${}將變數括起來

1
2
3
function greet(name){
console.log(`Hello, ${name}!`);
}

補充:表達式(expression)vs.陳述式(statement)
陳述式statement:只做行動但不立即產生結果
表達式expression:用小括號()將內容包起來,()裡面是值

1
2
const a;//陳述式
(a+1);//表達式

  • 字串模板中插入表達式
    1
    2
    3
    4
    function greet(name,days){
    const hours = days * 24;
    console.log(`Hello, ${name}! It's been ${hours} hours!`);
    }

在字串模板中,加入表達式的改寫

1
2
3
function greet(name,days){
console.log(`Hello, ${name}!It's been ${days * 24} hours!`);
}

  • 字串模板中加入三元判斷式
    三元判斷式解釋:若(days<7)成立,則回傳’’,否則回傳’Long time no see.’

    1
    2
    3
    4
    5
    6
    function greet(name,days){
    console.log(`Hello, ${name}! ${(days<7)?'':'Long time no see.'}`)
    }

    greet('Jack',3);//Hello, Jack!
    greet('Peter',8);//Hello, Peter! Long tome no see.
  • 多行字串
    長文章斷行,宣告多行字串不能斷行,若要換行只能使用+

    1
    const words = 'aaa\n'+'bbbb\n'+'ccccc';

用字串模板改寫(字串模板支援多行字串)

1
2
3
4
5
const words = `
aaa
bbbb
ccccc
`;

2-6:不只更簡短:箭頭函式(影片)

  • 箭頭函式,語法簡短
    1
    2
    3
    var double = function(x){
    return x*2;
    }
1
2
3
const double = (x) => {
return x*2;
}

如果參數只有一個,可以將小括號()省略

1
2
3
const double = x => {

}

如果函式本體只有一行,而且是return,可以省略{},將return內容直接寫在後面,

1
const double = x => x*2;

  • 箭頭函式,自動綁定
    箭頭函式內部的this與外部相同
    1
    2
    3
    4
    5
    const a =()=>{
    console.log(this);//等於外面的this
    }
    console.log(this);
    //第2行、第4行執行的this,指向同一個
1
2
3
4
5
6
7
const a = () =>{
console.log(this);
const aa = () =>{
console.log(this);/等於外面的this
}
}
//第2行、第4行執行的this,指向同一個

補充:函式裡面的this是什麼?
this是函式的context,情境不同,執行結果也不同

  1. 直接執行:“this”代表window(瀏覽器的global是window)

    1
    2
    3
    4
    5
    var name = 'Heisenburg';
    var sayMyName = function(){
    console.log(this.name);
    }
    sayMyName();//Heisenburg
  2. 宣告一個物件,將函式作為該物件的成員函式:“this”代表該物件

    1
    2
    3
    4
    5
    var teacher = {
    name:'Jack',
    }
    teacher.sayMyName = sayMyName;//物件的成員函式
    teacher.sayNyName();//Jack
  3. 作為DOM中的監聽函式:“this”代表該DOM元素

假設html中有一個button

1
<button id="btn" name="Btn-click">click me!</button>

當button被按下之後,會執行函式sayMyName

1
2
btn.addEventListener('click',sayMyName);
//Btn-click

==但是,若將函式改為箭頭函式…==
箭頭函式中的this代表外面的this,所以三種執行結果的name都ㄧ樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var name = 'Heisenburg';

var sayMyName = () =>{
console.log(this.name);
}

var teacher = {
name = 'Jack',
}
teacher.sayMyName = sayMyName;

sayMyName();//Heisenburg
teacher.sayMyName();//Heisenburg
btn.addEventListener('click',sayMyName);//Heisenburg

2-7:片尾彩蛋:ES5、ES6、Es2017!?到底是什麼東西?(影片)

  • ECMAScript(往往被稱作JavaScript)
    ECMA組織訂出JavaScript的語法規範,再讓各家瀏覽器依照規範實作

學習來源

CSS-將footer置底

通常一個頁面中包含三個部分:header、main-content、footer,可是當main-content中的內容不足以撐開整個頁面高度,footer下方就會出現一塊空白區域。這種情況,如果希望footer可以維持底部,整理兩種做法:

方法1. 設定main-content的最小高度為100%
方法2. 在最外部再包一層wrapper,設定期高度為100% ; 且讓footer設定為絕對定位bottom:0

方法1.設定main-content的最小高度為100%

html, body

  • 高度為100%
    main-content
  • 最小高度為100%
  • 上、下padding空間,作為放置header、footer的空間

header

  • 使用絕對定位,top為0
  • 設定z-index確保在最上方

footer

  • 使用相對定位,top為自己的高度
1
2
3
4
5
6
<!-- html -->
<body>
<header class='header'></header>
<div class="main-content"></div>
<footer class="footer"></footer>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
html,body{
height: 100%;
/* background-color: azure; */
}
.header{
height: 50px;
position: absolute;
top:0;
z-index: 900;
}
.main-content{
min-height: 100%;
padding-top:50px;
padding-bottom:50px;
}
.footer{
position: relative;
top: -100px;
height: 50px;
}

方法2.在最外部再包一層wrapper

html, body

  • 高度為100%

wrapper

  • 最小高度為100%

footer

  • 使用絕對定位,bottom為0
1
2
3
4
5
6
7
8
<!-- html -->
<body>
<div class='wrapper'>
<header class='header'></header>
<div class="main-content"></div>
<footer class="footer"></footer>
</div>
</body>
1
2
3
4
5
6
7
8
9
10
html, body{
height: 100%
}
.wrapper{
min-height: 100%;
}
.footer{
position: absolute;
bottom: 0;
}

jQuery-改變CSS樣式

語法結構

1
$('選擇器').css('屬性','值');
  • $()函式的功能是將HTML元素轉換為jQuery特殊元素,經此方法轉換後的HTML元素稱為「jQuery物件
  • css()中所定義的指令是「jQuery方法」,意即「jQuery其js中定義了的css()這個函式」

  • 選擇器:與CSS相同的選擇器

  • 屬性:CSS的屬性
  • 值:若為字串,需用單引號或雙引號(""'')括號起來;若值為數值,則不需要。

補充:jQuery可以修改元素的CSS屬性中的值,但若有使用!important的項目仍會優先套用。

語法執行概念

  1. 先利用$()函式,將作為指令對象的HTML元素,轉換為jQuery物件
  2. 針對jQuery物件呼叫方法,以進行相關操作

    簡易範例

1
2
3
4
5
$(function(){
$('#typo').css('color','#556A5B');
$('#typo').css('transform','rotate(10deg)')
$('#typo .inner').css('opacity',0.5)
})

jQuery-事件處理

事件處理函式

語法結構

1
2
3
$('選擇器').on('事件類型', function(){
任意處理程序
})
  • $()函式的功能是將HTML元素轉換為jQuery特殊元素,經此方法轉換後的HTML元素稱為「jQuery物件
  • on()是設定「當某事件發生時,執行某指令」的方法。
    • 第一個參數是「事件類型(Event Type)」:事件觸發的條件
    • 第二個參數是「處理程序(Event Handler)」:事件被觸發後,接著要调用的方法。

語法執行概念

  1. 先利用$()函式,將作為指令對象的HTML元素,轉換為jQuery物件
  2. 針對jQuery物件呼叫on()方法
  3. on()方法中傳入兩個參數,定義要被觸發的「事件類型」以及接下來要執行的「處理程序」

簡易範例

當滑鼠移入#typo,接著會執行:透過css樣式修改#typo的顏色

1
2
3
4
5
$function(){
$('#typo').on('mouseover',function(){
$('#typo').css('color','#ebc000')
})
}

多個處理程序

.on()方法中的第一個參數「事件類型」被觸發之後,第二個參數「處理程序函式」中可以執行數個個別處理的程序

語法結構

1
2
3
4
5
$('選擇器').on('事件類型', function(){
處理1;
處理2;
處理3...;
})

簡易範例

  • 當滑鼠移入#typo,接著會執行:
    • 透過css樣式修改#typo的顏色
    • 透過css樣式修改header的背景顏色
      1
      2
      3
      4
      5
      6
      $function(){
      $('#typo').on('mouseover',function(){
      $('#typo').css('color','#ebc000') ;
      $('header').css('background-color','#ffffff')
      })
      }

設定多個事件類型

一個jQuery物件,可以有多個.on()方法,例如:當A事件(滑鼠移入)時要執行a程序,而當B事件(滑鼠移出)時要執行b程序

方法鏈串語法

多個方法如鎖鏈一般串連起來,針對$()產生的同一個jQuery物件作為執行對象,程式會從左到右開始執行。

1
$('選擇器').事件A().事件B().事件C()....

簡易案例

  • 當滑鼠移入#typo元素時,會改變文字即背景顏色
  • 當滑鼠移出#typo元素時,會回復為原本的顏色

多個事件一般寫法(效能差)

  • 針對同一個物件,寫兩次$()函式,瀏覽器花時間分析HTML並取得目標元素,會造成CPU負擔
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $(function(){
    $('#typo').on('mouseover',function(){
    $('#typo').css({
    color:'#ebc000',
    backgroundColor:'#ae5e96'
    });
    });
    $('#typo').on('mouseout',function(){
    $('#typo').css({
    color:'',
    backgroundColor:''
    });
    });
    })

修改為鏈串寫法(效能佳)

  • 只需要使用一次$()函式,除了簡化程式碼,也提稱程式處理速度
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $(function(){
    $('#typo')
    .on('mouseover',function(){
    $('#typo').css({
    color:'#ebc000',
    backgroundColor:'#ae5e96'
    })
    })
    .on('mouseout',function(){
    $('#typo').css({
    color:'',
    backgroundColor:''
    })
    })
    })

主要的事件類型

jQuery中,大部分的操作都基於HTML DOM,所以必須確定頁面文件已經完全下載好,才能開始執行程式。jQuery 提供下面這個函式來處理 DOM ready事件

當DOM載入後,執行ready()方法。

1
2
3
$(document).ready(function() {
// 這裡放你要執行的程式碼
});

也可以這樣寫

1
2
3
$function(){
// 這裡放你要執行的程式碼
}

Hexo-使用靜態生成器,建立blog(3/3)變更主題

系列文章

將別人的製作好的主題repository clone下來的時候,可能會連.git 一起 clone下來,出現「Git Submodule

Git Submodule」就是原先的repository中,還內嵌一到多個外部repository

  • 查看clone下來的repository是否含有.git
    1
    2
    3
    //進入themes資料夾,查看檔案列表
    $ cd themes
    $ ls -al
1
2
3
//進入內部主題資料夾,查看其中檔案列表
$ cd hiero
$ ls -al

  • 刪除內部主題資料夾中的.git
    1
    2
    3
    //強制刪除.git(-rf : recursive + force)
    $ rm -rf .git
    $ ls -al

  • 刪除快取

    1
    $ git rm --cached  themes/hiero -f
  • 查看尚未commit的當案

    1
    $ git status
  • 新增檔案

    1
    $ git add <file name>
  • 使用git管理檔案

    1
    $ git commit -m"<commit message>"
  • 檢視提交紀錄(也可以用soursetree檢視)

    1
    $ git log

  • 使用hexo產生靜態網頁
    hexo 是把產生出來的網站push到github(可以理解為,hexo的deploy指令會先把原始碼變成網站瀏覽器可以閱讀的程式碼 再push到github)
    1
    $ hexo deploy -g

Hexo-使用靜態生成器,建立blog(2/3)推上github

系列文章

  1. 先在github新增一個repository,命名邏輯為

    1
    2
    [github account].github.io
    例:leahlin912.github.io
  2. 複製該repository的網址(例:`git@github.com:leahlin912/leahlin912.github.io.git`)

  3. 用vscode(或其他編譯器)打開_config.yml檔案,並修改# Deployment的部分

    1
    2
    3
    4
    5
    6
    # Deployment
    ## Docs: https://hexo.io/docs/deployment.html
    deploy:
    type: git
    repository: git@github.com:leahlin912/leahlin912.github.io.git
    branch: master
  4. 安裝git

    1
    $ npm install hexo-deployer-git --save
  5. 輸入指令,將網站佈署到伺服器上

    1
    $ hexo deploy -g
  6. 設定repository的主題
    在github的該repository頁面,進入「setting」

    往下滑,點按「change theme」

  7. 在瀏覽器中查看網址,成功!https://leahlin912.github.io/

  8. 若有檔案更新,則重複輸入指令

    1
    hexo deploy -g

更換主題

  1. 選擇要套用的主題
    [Themes]
    (https://hexo.io/themes/index.html)

  2. 點進該主題的github頁面

  3. 在README.md中,依照install指令複製起來,並在terminal中進入blog資料夾中執行指令完畢

  4. 用vscode開啟blog資料夾,並進入_config.yml檔案中,修改主題theme(參考readme中開發者定義的theme名稱)

  5. 因為檔案有更新,所以需要在terminal輸入指令

    1
    hexo deploy -g
© 2020 Leah's Blog All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero