一、什么是全局API?
全局API並不在構造器里,而是先聲明全局變量或者直接在Vue上定義一些新功能,Vue內置了一些全局API,比如我們今天要學習的指令Vue.directive。說的簡單些就是,在構造器外部用Vue提供給我們的API函數來定義新的功能。
二、Vue.directive自定義指令
我們在第一季就學習了內部指令,我們也可以定義一些屬於自己的指令,比如我們要定義一個v-jspang的指令,作用就是讓文字變成綠色。
在自定義指令前我們寫一個小功能,在頁面上有一個數字為10,數字的下面有一個按鈕,我們每點擊一次按鈕后,數字加1.
你不妨模仿下面的功能,在自己本地先寫出這個效果。我用JSRun提供了預覽和代碼展示功能,你也可以在線調試。
寫好了這個功能,我們現在就自己定義一個全局的指令。我們這里使用Vue.directive( );
1
2
3
|
Vue.directive('jspang',function(el,binding,vnode){
el.style='color:'+binding.value;
});
|
可以看到數字已經變成了綠色,說明自定義指令起到了作用。可能您看這個代碼還是有些不明白的,比如傳入的三個參數到底是什么。
三、自定義指令中傳遞的三個參數
el: 指令所綁定的元素,可以用來直接操作DOM。
binding: 一個對象,包含指令的很多信息。
vnode: Vue編譯生成的虛擬節點。
四、自定義指令的生命周期
自定義指令有五個生命周期(也叫鈎子函數),分別是 bind,inserted,update,componentUpdated,unbind
- bind:只調用一次,指令第一次綁定到元素時調用,用這個鈎子函數可以定義一個綁定時執行一次的初始化動作。
- inserted:被綁定元素插入父節點時調用(父節點存在即可調用,不必存在於document中)。
- update:被綁定於元素所在的模板更新時調用,而無論綁定值是否變化。通過比較更新前后的綁定值,可以忽略不必要的模板更新。
- componentUpdated:被綁定元素所在模板完成一次更新周期時調用。
- unbind:只調用一次,指令與元素解綁時調用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
bind:function(){//被綁定
console.log('1 - bind');
},
inserted:function(){//綁定到節點
console.log('2 - inserted');
},
update:function(){//組件更新
console.log('3 - update');
},
componentUpdated:function(){//組件更新完成
console.log('4 - componentUpdated');
},
unbind:function(){//解綁
console.log('1 - bind');
}
|
第2節:Vue.extend構造器的延伸
Vue.extend 返回的是一個“擴展實例構造器”,也就是預設了部分選項的Vue實例構造器。經常服務於Vue.component用來生成組件,可以簡單理解為當在模板中遇到該組件名稱作為標簽的自定義元素時,會自動調用“擴展實例構造器”來生產組件實例,並掛載到自定義元素上。
由於我們還沒有學習Vue的自定義組件,所以我們先看跟組件無關的用途。
二、自定義無參數標簽
我們想象一個需求,需求是這樣的,要在博客頁面多處顯示作者的網名,並在網名上直接有鏈接地址。我們希望在html中只需要寫<author></author> ,這和自定義組件很像,但是他沒有傳遞任何參數,只是個靜態標簽。
我們的Vue.extend該登場了,我們先用它來編寫一個擴展實例構造器。代碼如下:
1
2
3
4
5
6
7
8
9
|
var authorExtend = Vue.extend({
template:"<p><a :href='authorUrl'>{{authorName}}</a></p>",
data:function(){
return{
authorName:'JSPang',
authorUrl:'http://www.jspang.com'
}
}
});
|
這時html中的標簽還是不起作用的,因為擴展實例構造器是需要掛載的,我們再進行一次掛載。
1
|
new authorExtend().$mount('author');
|
這時我們在html寫<author><author>就是管用的。我們來看一下全部代碼:
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
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>vue.extend-擴展實例構造器</title>
</head>
<body>
<h1>vue.extend-擴展實例構造器</h1>
<hr>
<author></author>
<script type="text/javascript">
var authorExtend = Vue.extend({
template:"<p><a :href='authorUrl'>{{authorName}}</a></p>",
data:function(){
return{
authorName:'JSPang',
authorUrl:'http://www.jspang.com'
}
}
});
new authorExtend().$mount('author');
</script>
</body>
</html>
|
最終實現結果:
三、掛載到普通標簽上
還可以通過HTML標簽上的id或者class來生成擴展實例構造器,Vue.extend里的代碼是一樣的,只是在掛載的時候,我們用類似jquery的選擇器的方法,來進行掛載就可以了。
1
|
new authorExtend().$mount('#author');
|
第3節:Vue.set全局操作
一、引用構造器外部數據:
什么是外部數據,就是不在Vue構造器里里的data處聲明,而是在構造器外部聲明,然后在data處引用就可以了。外部數據的加入讓程序更加靈活,我們可以在外部獲取任何想要的數據形式,然后讓data引用。
看一個簡單的代碼:
1
2
3
4
5
6
7
8
9
10
|
//在構造器外部聲明數據
var outData={
count:1,
goodName:'car'
};
var app=new Vue({
el:'#app',
//引用外部數據
data:outData
})
|
二、在外部改變數據的三種方法:
1、用Vue.set改變
1
2
3
|
function add(){
Vue.set(outData,'count',4);
}
|
2、用Vue對象的方法添加
1
|
app.count++;
|
3、直接操作外部數據
1
|
outData.count++;
|
其實這三種方式都可以操作外部的數據,Vue也給我們增加了一種操作外部數據的方法。
三、為什么要有Vue.set的存在?
由於Javascript的限制,Vue不能自動檢測以下變動的數組。
*當你利用索引直接設置一個項時,vue不會為我們自動更新。
*當你修改數組的長度時,vue不會為我們自動更新。
看一段代碼:
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
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>Vue.set 全局操作</title>
</head>
<body>
<h1>Vue.set 全局操作</h1>
<hr>
<div id="app">
<ul>
<li v-for=" aa in arr">{{aa}}</li>
</ul>
</div>
<button onclick="add()">外部添加</button>
<script type="text/javascript">
function add(){
console.log("我已經執行了");
app.arr[1]='ddd';
//Vue.set(app.arr,1,'ddd');
}
var outData={
arr:['aaa','bbb','ccc']
};
var app=new Vue({
el:'#app',
data:outData
})
</script>
</body>
</html>
|
這時我們的界面是不會自動跟新數組的,我們需要用Vue.set(app.arr,1,’ddd’)來設置改變,vue才會給我們自動更新,這就是Vue.set存在的意義。
第4節:Vue的生命周期(鈎子函數)
其實在Vue的官網有一張圖已經很好的詮釋了生命周期,我在這里就不再多講了,直接貼圖,然后上程序代碼。
我們直接來看一段代碼:
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>構造器的聲明周期</title>
</head>
<body>
<h1>構造器的聲明周期</h1>
<hr>
<div id="app">
{{message}}
<p><button @click="jia">加分</button></p>
</div>
<button onclick="app.$destroy()">銷毀</button>
<script type="text/javascript">
var app=new Vue({
el:'#app',
data:{
message:1
},
methods:{
jia:function(){
this.message ++;
}
},
beforeCreate:function(){
console.log('1-beforeCreate 初始化之后');
},
created:function(){
console.log('2-created 創建完成');
},
beforeMount:function(){
console.log('3-beforeMount 掛載之前');
},
mounted:function(){
console.log('4-mounted 被創建');
},
beforeUpdate:function(){
console.log('5-beforeUpdate 數據更新前');
},
updated:function(){
console.log('6-updated 被更新后');
},
activated:function(){
console.log('7-activated');
},
deactivated:function(){
console.log('8-deactivated');
},
beforeDestroy:function(){
console.log('9-beforeDestroy 銷毀之前');
},
destroyed:function(){
console.log('10-destroyed 銷毀之后')
}
})
</script>
</body>
</html>
|
第5節:Template 制作模版
一、直接寫在選項里的模板
直接在構造器里的template選項后邊編寫。這種寫法比較直觀,但是如果模板html代碼太多,不建議這么寫。
javascript代碼:
1
2
3
4
5
6
7
8
9
|
var app=new Vue({
el:'#app',
data:{
message:'hello Vue!'
},
template:`
<h1 style="color:red">我是選項模板</h1>
`
})
|
這里需要注意的是模板的標識不是單引號和雙引號,而是,就是Tab上面的鍵。
二、寫在<template>標簽里的模板
這種寫法更像是在寫HTML代碼,就算不會寫Vue的人,也可以制作頁面。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<template id="demo2">
<h2 style="color:red">我是template標簽模板</h2>
</template>
<script type="text/javascript">
var app=new Vue({
el:'#app',
data:{
message:'hello Vue!'
},
template:'#demo2'
})
</script>
|
三、寫在<script>標簽里的模板
這種寫模板的方法,可以讓模板文件從外部引入。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script type="x-template" id="demo3">
<h2 style="color:red">我是script標簽模板</h2>
</script>
<script type="text/javascript">
var app=new Vue({
el:'#app',
data:{
message:'hello Vue!'
},
template:'#demo3'
})
</script>
|
這節課我們學習了Template的三種寫法,以后學習到vue-cli的時候還會學到一種xxx.vue的寫法。
第6節:Component 初識組件
一、全局化注冊組件
全局化就是在構造器的外部用Vue.component來注冊,我們注冊現在就注冊一個<jspang></jspang>的組件來體驗一下。
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
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>component-1</title>
</head>
<body>
<h1>component-1</h1>
<hr>
<div id="app">
<jspang></jspang>
</div>
<script type="text/javascript">
//注冊全局組件
Vue.component('jspang',{
template:`<div style="color:red;">全局化注冊的jspang標簽</div>`
})
var app=new Vue({
el:'#app',
data:{
}
})
</script>
</body>
</html>
|
我們在javascript里注冊了一個組件,在HTML中調用了他。這就是最簡單的一個組件的編寫方法,並且它可以放到多個構造器的作用域里。
二、局部注冊組件局部注冊組件和全局注冊組件是向對應的,局部注冊的組件只能在組件注冊的作用域里進行使用,其他作用域使用無效。
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
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>component-1</title>
</head>
<body>
<h1>component-1</h1>
<hr>
<div id="app">
<panda></panda>
</div>
<script type="text/javascript">
var app=new Vue({
el:'#app',
components:{
"panda":{
template:`<div style="color:red;">局部注冊的panda標簽</div>`
}
}
})
</script>
</body>
</html>
|
從代碼中你可以看出局部注冊其實就是寫在構造器里,但是你需要注意的是,構造器里的components 是加s的,而全局注冊是不加s的。
三、組件和指令的區別
組件注冊的是一個標簽,而指令注冊的是已有標簽里的一個屬性。在實際開發中我們還是用組件比較多,指令用的比較少。因為指令看起來封裝的沒那么好,這只是個人觀點。
第7節:Component 組件props 屬性設置
一、定義屬性並獲取屬性值
定義屬性我們需要用props選項,加上數組形式的屬性名稱,例如:props:[‘here’]。在組件的模板里讀出屬性值只需要用插值的形式,例如{{ here }}.
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
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>component-2</title>
</head>
<body>
<h1>component-2</h1>
<hr>
<div id="app">
<panda here="China"></panda>
</div>
<script type="text/javascript">
var app=new Vue({
el:'#app',
components:{
"panda":{
template:`<div style="color:red;">Panda from {{ here }}.</div>`,
props:['here']
}
}
})
</script>
</body>
</html>
|
上面的代碼定義了panda的組件,並用props設置了here的屬性值,在here屬性值里傳遞了China給組件。
最后輸出的結果是紅色字體的Panda from China.
二、屬性中帶’-‘的處理方式
我們在寫屬性時經常會加入’-‘來進行分詞,比如:<panda from-here=”China”></panda>,那這時我們在props里如果寫成props:[‘form-here’]是錯誤的,我們必須用小駝峰式寫法props:[‘formHere’]。
html文件:
1
|
<panda from-here="China"></panda>
|
javascript文件:
1
2
3
4
5
6
7
8
9
|
var app=new Vue({
el:'#app',
components:{
"panda":{
template:`<div style="color:red;">Panda from {{ here }}.</div>`,
props:['fromHere']
}
}
})
|
PS:因為這里有坑,所以還是少用-為好。
三、在構造器里向組件中傳值
把構造器中data的值傳遞給組件,我們只要進行綁定就可以了。就是我們第一季學的v-bind:xxx.
我們直接看代碼:
Html文件:
1
|
<panda v-bind:here="message"></panda>
|
javascript文件:
1
2
3
4
5
6
7
8
9
10
11
12
|
var app=new Vue({
el:'#app',
data:{
message:'SiChuan'
},
components:{
"panda":{
template:`<div style="color:red;">Panda from {{ here }}.</div>`,
props:['here']
}
}
})
|
第8節:Component 父子組件關系
一、構造器外部寫局部注冊組件
上面上課我們都把局部組件的編寫放到了構造器內部,如果組件代碼量很大,會影響構造器的可讀性,造成拖拉和錯誤。
我們把組件編寫的代碼放到構造器外部或者說單獨文件。
我們需要先聲明一個對象,對象里就是組件的內容。
1
2
3
|
var jspang = {
template:`<div>Panda from China!</div>`
}
|
聲明好對象后在構造器里引用就可以了。
1
2
3
|
components:{
"jspang":jspang
}
|
html中引用
1
|
<jspang></jspang>
|
二、父子組件的嵌套
我們先聲明一個父組件,比如叫jspang,然后里邊我們加入一個city組件,我們來看這樣的代碼如何寫。
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
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>component-3</title>
</head>
<body>
<h1>component-3</h1>
<hr>
<div id="app">
<jspang></jspang>
</div>
<script type="text/javascript">
var city={
template:`<div>Sichuan of China</div>`
}
var jspang = {
template:`<div>
<p> Panda from China!</p>
<city></city>
</div>`,
components:{
"city":city
}
}
var app=new Vue({
el:'#app',
components:{
"jspang":jspang
}
})
</script>
</body>
</html>
|
第9節:Component 標簽
1.我們先在構造器外部定義三個不同的組件,分別是componentA,componentB和componentC.
1
2
3
4
5
6
7
8
9
|
var componentA={
template:`<div>I'm componentA</div>`
}
var componentB={
template:`<div>I'm componentB</div>`
}
var componentC={
template:`<div>I'm componentC</div>`
}
|
2.我們在構造器的components選項里加入這三個組件。
1
2
3
4
5
|
components:{
"componentA":componentA,
"componentB":componentB,
"componentC":componentC,
}
|
3.我們在html里插入component標簽,並綁定who數據,根據who的值不同,調用不同的組件。
1
|
<component v-bind:is="who"></component>
|
這就是我們的組件標簽的基本用法。我們提高以下,給頁面加個按鈕,每點以下更換一個組件。
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
47
48
49
50
51
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>component-4</title>
</head>
<body>
<h1>component-4</h1>
<hr>
<div id="app">
<component v-bind:is="who"></component>
<button @click="changeComponent">changeComponent</button>
</div>
<script type="text/javascript">
var componentA={
template:`<div style="color:red;">I'm componentA</div>`
}
var componentB={
template:`<div style="color:green;">I'm componentB</div>`
}
var componentC={
template:`<div style="color:pink;">I'm componentC</div>`
}
var app=new Vue({
el:'#app',
data:{
who:'componentA'
},
components:{
"componentA":componentA,
"componentB":componentB,
"componentC":componentC,
},
methods:{
changeComponent:function(){
if(this.who=='componentA'){
this.who='componentB';
}else if(this.who=='componentB'){
this.who='componentC';
}else{
this.who='componentA';
}
}
}
})
</script>
</body>
</html>
|