0%

Vue常用API-02

接續上一篇內容。

Directive 開發自己的互動UI

Directive的功用為,Vue.js 提供自定義指令讓開發者直接從底層操作 DOM 物件。

Directive 有屬於它自己的生命周期。

ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---HTML---
<div id="app">
<input type="text" v-focus>
</div>


---Javascript---
Vue.directive('focus', {
// 當綁定元素插入父元素後,會觸發 inserted hook 內的內容
inserted: function (el) {
el.focus() // 聚焦元素
}
})

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

以上這個範例,可以看出來directive有它自己的生命週期。
bind: 只會執行一次,即該自訂義事件第一次跟被綁定元素綁定時會觸發這個hook的內容。
inserted: 當被綁定元素,完成插入父元素之後,會觸發inerted hook 的內容。
update: 綁定元素在模版更新時,會觸發
它不只有上面三種生命週期,可以直接去看官方看看其他生命週期介紹。
官方文件

directive 的 Hook函式所能使用的參數

在官方文件中有提供,directive的Hook有一些參數可以直接使用
el: 可以獲得被自訂義指令綁定的目標元素,且直接操縱這個被綁定的目標元素
binding: 被綁定目標元素的特性,有以下幾個,我只簡列幾項

  • name: 沒有前綴詞v-的自訂義事件名稱,像上面範例的v-focus,去掉v-,它的自訂義事件的name屬性就是focus
    有關binding還有其他的參數可以使用,可以看一下官方文件。

那以上這個範例,每次頁面刷新的時候,該input欄位就會藉由v-focus來觸發在directive中自訂義的focus內容,自動將畫面焦點移到這個input欄位中。

透過directive 製作email驗證功能

以上這個範例中,我們創了兩個directive
focus的directive中的生命週期,有inserted
表示,當頁面刷新時,會觸發這個focus的內容也就會讓頁面的focus鎖定到這個input欄位中。

validation這個directive中,
bind的生命週期,代表該元件已經確實的被掛載到HTML中了,所以,可以對它的HTML做操作,有點像Vue元件的mounted生命週期。
所以,當該元件掛完成後,就將它的class名稱改為form-control

update的Hook函式,代表該欄位內的內容有更動的話,就會觸發這個事件。
但是,你要注意一下,我們有在這個input欄位裡面,加入了v-model:'email',去綁定email這個data,如果,你沒有去綁定這個email的屬性的話,是不會進update事件的喔。
而且,還有加入驗證email格式的正規式,
如果,輸入的格式是正確的eamil的格式的話,就為該input欄位加入is-valid的className,此時,input欄位的框框會變綠色的。
如果,輸入的格式是錯誤的eamil的格式的話,就為該input欄位加入is-invalid的className,此時,input欄位的框框會變紅色的。

如此,就完成email的驗證器囉。

Directive 細節說明 

Directive傳入參數

我們改寫一下以上的範例
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
35
36
37
38
39
40
41
---HTML---
<div id="app">
<input type="email" v-model="email" v-focus v-validaton="{ className: 'form-control' }">
</div>

---Javascript---
<script>
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})

Vue.directive('validaton', {
update: function(el, binding, vnode) {
console.log('update', el.value, el.className, vnode);
var value = vnode.context.email;
// Email validate
var re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
if (!re.test(value)) {
el.className = 'form-control is-invalid'
} else {
el.className = 'form-control is-valid'
}
},
bind: function(el, binding, vnode) {
console.log('bind', el, binding, vnode);
el.className = binding.value.className;
}
});

var app = new Vue({
el: '#app',
data: {
email: 'aaa',
},
mounted: function() {
console.log('Vue init:', this)
}
});
</script>

以上你可以看到,我們先在input欄位的html標籤中,v-validaton接一個式子,前面是屬性,後面是屬性值{className: ‘form-control’}
接著,我們validaton的bind hook裡面,利用binding.value來接收由外界傳入的className內容,接著,再把它設給el.className,也就是為這個dom元素的class設入form-control

Directive取得Vue的資料內容

例如:將v-model綁定的屬性名稱取出來,進而,把v-model所綁定屬性值的內容也取出來。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
---HTML---
<div id="app">
<input type="email" v-model="email" v-focus v-validaton="{ className: 'form-control' }">
</div>


---Javascript---
<script>

Vue.directive('focus', {
inserted: function (el) {
// 聚焦元素
el.focus()
}
})

Vue.directive('validaton', {
update: function(el, binding, vnode) {
console.log('update', el.value, el.className, vnode);

// 尋找當前的 model 名稱
var currentModel = vnode.data.directives.find(function(o) {
return o.name === 'model';
}).expression;

// 從當前 Model 取值
var value = vnode.context[currentModel];

// Email validate
var re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
if (!re.test(value)) {
el.className = 'form-control is-invalid'
} else {
el.className = 'form-control is-valid'
}
},
bind: function(el, binding, vnode) {
console.log('bind', el, binding, vnode);
var vModel = vnode.data.directives.find(item=> item.name === 'model').expression;
console.log(vModel);
console.log(vnode.context[vModel]);
}
});

var app = new Vue({
el: '#app',
data: {
email: 'aaa',
},
mounted: function() {
console.log('Vue init:', this)
}
});
</script>

取得屬性名稱

像以上這個範例就是將input欄位中,v-model所綁定的email內容皆取出來。
在以上的範例,你可以在bind這個hook中取出該元件的vnode內容,
在vnode->data->directives,可以看到model, focus, validation三個元素。
並打開model元素的屬性欄,你可以看到experssion裡面的內容就有email了。
而這個expression就是我們要取得的屬性名稱。
像這樣
var vModel = vnode.data.directives.find(item=> item.name === 'model').expression;

取得屬性值

接著,當我們知道我們要取的元素的屬性名稱的時候,
那我們要怎麼取得這個屬性的內容呢?
在同樣的vnode底下,有context屬性,而這個屬性裡面就有一個email屬性,而它的內容就是這個
email的內容值囉。
那我們在上面不是已經將email的屬性名稱存入vModel了媽,你就利用它來尋找vnode.context中的eamil屬性。
像這樣
vnode.context[vModel],如此,就可以取得屬性eamil的內容囉。

使用外部載入的套件

課程是介紹引入Bootstrap4的Vue套件。
那在引入套件的時候,一定要注意他們所引用的版本是在多少,免得不能使用。
官方文件
像以上連結中,所引入的套件,
就可以看到Boostrap是引入Bootstrap4的版本。
那Vue是引入v2.6版本。

那在這個套件,有可以不經由Webpack就引入套件,
你就在這個文件中,搜尋Brower關鍵字,應該就可以看到官網提供的引入的CDN內容。

1
2
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />

第一行是Bootstrap的樣式
第二行是bootstrap為vue所設計的樣式,所以,這一行也要引入那這兩行要加在<head>中。

1
2
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>

以上這兩行,官網說要放在引入Vue的js那行的前面。

最後,引入

1
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>