Vue學習之路(2)------全域性API
一、什麼是全域性API?
全域性API並不在構造器裡,而是先宣告全域性變數或者直接在Vue上定義一些新功能,Vue內建了一些全域性API,比如我們今天要學習的指令Vue.directive。說的簡單些就是,在構造器外部用Vue提供給我們的API函式來定義新的功能。
二、Vue.directive自定義指令
我們在第一季就學習了內部指令,我們也可以定義一些屬於自己的指令,比如我們要定義一個v-jspang的指令,作用就是讓文字變成綠色。
在自定義指令前我們寫一個小功能,在頁面上有一個數字為10,數字的下面有一個按鈕,我們每點選一次按鈕後,數字加1.
你不妨模仿下面的功能,在自己本地先寫出這個效果。我用JSRun提供了預覽和程式碼展示功能,你也可以線上除錯。
寫好了這個功能,我們現在就自己定義一個全域性的指令。我們這裡使用Vue.directive( );
- 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:只調用一次,指令與元素解綁時呼叫。
- 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.extend 返回的是一個“擴充套件例項構造器”,也就是預設了部分選項的Vue例項構造器。經常服務於Vue.component用來生成元件,可以簡單理解為當在模板中遇到該元件名稱作為標籤的自定義元素時,會自動呼叫“擴充套件例項構造器”來生產元件例項,並掛載到自定義元素上。
由於我們還沒有學習Vue的自定義元件,所以我們先看跟元件無關的用途。
二、自定義無引數標籤
我們想象一個需求,需求是這樣的,要在部落格頁面多處顯示作者的網名,並在網名上直接有連結地址。我們希望在html中只需要寫 ,這和自定義元件很像,但是他沒有傳遞任何引數,只是個靜態標籤。
我們的Vue.extend該登場了,我們先用它來編寫一個擴充套件例項構造器。程式碼如下:
- var authorExtend = Vue.extend({
- template:"<p><a :href='authorUrl'>{{authorName}}</a></p>",
- data:function(){
- return{
- authorName:'JSPang',
- authorUrl:'http://www.jspang.com'
- }
- }
- });
這時html中的標籤還是不起作用的,因為擴充套件例項構造器是需要掛載的,我們再進行一次掛載。
- new authorExtend().$mount('author');
這時我們在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的選擇器的方法,來進行掛載就可以了。
- new authorExtend().$mount('#author');
第3節:Vue.set全域性操作
Vue.set 的作用就是在構造器外部操作構造器內部的資料、屬性或者方法。比如在vue構造器內部定義了一個count為1的資料,我們在構造器外部定義了一個方法,要每次點選按鈕給值加1.就需要用到Vue.set。
一、引用構造器外部資料:
什麼是外部資料,就是不在Vue構造器裡裡的data處宣告,而是在構造器外部宣告,然後在data處引用就可以了。外部資料的加入讓程式更加靈活,我們可以在外部獲取任何想要的資料形式,然後讓data引用。 看一個簡單的程式碼:
- //在構造器外部宣告資料
- var outData={
- count:1,
- goodName:'car'
- };
- var app=new Vue({
- el:'#app',
- //引用外部資料
- data:outData
- })
二、在外部改變資料的三種方法:
1、用Vue.set改變
- function add(){
- Vue.set(outData,'count',4);
- }
2、用Vue物件的方法新增
- app.count++;
3、直接操作外部資料
- outData.count++;
其實這三種方式都可以操作外部的資料,Vue也給我們增加了一種操作外部資料的方法。
三、為什麼要有Vue.set的存在?
由於Javascript的限制,Vue不能自動檢測以下變動的陣列。
- 當你利用索引直接設定一個項時,vue不會為我們自動更新。
- 當你修改陣列的長度時,vue不會為我們自動更新。
看一段程式碼:
- <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一共有10個生命週期函式,我們可以利用這些函式在vue的每個階段都進行操作資料或者改變內容。
其實在Vue的官網有一張圖已經很好的詮釋了生命週期,我在這裡就不再多講了,直接貼圖,然後上程式程式碼。
我們直接來看一段程式碼:
- <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程式碼:
- var app=new Vue({
- el:'#app',
- data:{
- message:'hello Vue!'
- },
- template:`
- <h1 style="color:red">我是選項模板</h1>
- `
- })
這裡需要注意的是模板的標識不是單引號和雙引號,而是,就是Tab上面的鍵。
二、寫在template標籤裡的模板
這種寫法更像是在寫HTML程式碼,就算不會寫Vue的人,也可以製作頁面。
- <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標籤裡的模板
這種寫模板的方法,可以讓模板檔案從外部引入。
- <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 初識元件
前言(廢話):component元件是Vue學習的重點、重點、重點,重要的事情說三遍。所以你必須學好Vue component。其實元件就是製作自定義的標籤,這些標籤在HTML中是沒有的。比如:,那我們就開始學習這種技巧吧。
一、全域性化註冊元件
全域性化就是在構造器的外部用Vue.component來註冊,我們註冊現在就註冊一個的元件來體驗一下。
- <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中呼叫了他。這就是最簡單的一個元件的編寫方法,並且它可以放到多個構造器的作用域裡。
二、區域性註冊元件區域性
區域性註冊元件區域性註冊元件和全域性註冊元件是向對應的,區域性註冊的元件只能在元件註冊的作用域裡進行使用,其他作用域使用無效。
- <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選項就是設定和獲取標籤上的屬性值的,例如我們有一個自定義的元件,這時我們想給他加個標籤屬性寫成 意思就是熊貓來自中國,當然這裡的China可以換成任何值。定義屬性的選項是props。
一、定義屬性並獲取屬性值
定義屬性我們需要用props選項,加上陣列形式的屬性名稱,例如:props:[‘here’]。在元件的模板裡讀出屬性值只需要用插值的形式,例如{{ here }}.
- <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.
二、屬性中帶’-‘的處理方式
我們在寫屬性時經常會加入’-‘來進行分詞,比如:,那這時我們在props裡如果寫成props:[‘form-here’]是錯誤的,我們必須用小駝峰式寫法props:[‘formHere’]。
html檔案:
- <panda from-here="China"></panda>
javascript檔案:
- 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檔案:
- <panda v-bind:here="message"></panda>
javascript檔案:
- var app=new Vue({
- el:'#app',
- data:{
- message:'SiChuan'
- },
- components:{
- "panda":{
- template:`<div style="color:red;">Panda from {{ here }}.</div>`,
- props:['here']
- }
- }
- })
第8節:Component 父子元件關係
在實際開發中我們經常會遇到在一個自定義元件中要使用其他自定義元件,這就需要一個父子元件關係。
一、構造器外部寫區域性註冊元件
上面上課我們都把區域性元件的編寫放到了構造器內部,如果元件程式碼量很大,會影響構造器的可讀性,造成拖拉和錯誤。
我們把元件編寫的程式碼放到構造器外部或者說單獨檔案。
我們需要先宣告一個物件,物件裡就是元件的內容。
- var jspang = {
- template:`<div>Panda from China!</div>`
- }
宣告好物件後在構造器裡引用就可以了。
- components:{
- "jspang":jspang
- }
html中引用
- <jspang></jspang>
二、父子元件的巢狀 我們先宣告一個父元件,比如叫jspang,然後裡邊我們加入一個city元件,我們來看這樣的程式碼如何寫。
- <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 標籤
標籤是Vue框架自定義的標籤,它的用途就是可以動態繫結我們的元件,根據資料的不同更換不同的元件。
1.我們先在構造器外部定義三個不同的元件,分別是componentA,componentB和componentC.
- 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選項里加入這三個元件。
- components:{
- "componentA":componentA,
- "componentB":componentB,
- "componentC":componentC,
- }
3.我們在html裡插入component標籤,並繫結who資料,根據who的值不同,呼叫不同的元件。
- <component v-bind:is="who"></component>
這就是我們的元件標籤的基本用法。我們提高以下,給頁面加個按鈕,每點以下更換一個元件。
- <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>