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])
}
}
})

學習來源

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