手挽手帶你學VUE:二檔 組件開發以及經常使用全局api

視頻教程

因爲思否不支持視頻連接 視頻請移步 http://www.henrongyi.top

你能學到什麼

二檔視頻固然要比一檔視頻難一點,若是前面的內容尚未消化完畢的話,仍是建議你們繼續消化前面的內容,而後再看接下來的部分。這一部分是VUE的核心,講到組件化開發的基礎部分,多學,多練。javascript

生命週期

Vue官網給出的生命週期圖html

<img src='https://cn.vuejs.org/images/l...' >
這張圖裏包含了基本的生命週期,實際上生命週期鉤子函數還有兩個不在圖內(activated,deactivated),這兩個生命週期函數這裏不給你們講,若是你們有興趣能夠自行到VUE官網看文檔,工做中用到他們的機會很少,這邊講也會擾亂你們的學習進程。這裏咱們經過代碼來說解Vue的生命週期vue

<!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>
    <style>
        .active{
            color:red
        }
    </style>
</head>
<body>
    <div id="app">
        <button v-on:click="add">+</button>{{num}}<button @click="minus">-</button>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var app = new Vue({
            el:"#app",
            data:{
               num:1
            },
            methods:{
                add(){
                    this.num++
                },
                minus(){
                     this.num--
                }
            },
            beforeCreate:function(){
                console.log('頁面初始化以後馬上執行');
            },
            created:function(){
                console.log('頁面初始化完成以後created,這裏模板尚未渲染呢!');
            },
            beforeMount:function(){
                console.log('組件掛載以前beforeMount');
            },
            mounted:function(){
                console.log('組件掛載以後mounted');
            },
            beforeUpdate:function(){
                console.log('組件更新前beforeUpdate');
            },
            updated:function(){
                console.log('組件更新後updated');
            },
        //   activated:function(){
        //      console.log('activated');
        //    },
        //    deactivated:function(){
        //        console.log('deactivated');
        //    },    你只須要知道這兩個生命週期是在這個位置進行就行了,別的能夠不要想太多。
            beforeDestroy:function(){
                console.log('組件銷燬以前beforeDestroy');
            },
            destroyed:function(){
                console.log('組件銷燬後destroyed')
            }
        })
    </script>
</body>
</html>

這些生命週期函數大致就演示到這裏,剩下的兩個沒能給你們展現的請你們牢記,咱們開始學組件的時候,就能夠體會到這兩個鉤子函數的用法了。java

組件建立

Vue.component
註冊全局組件
Vue.component("組件名",{ 組件的各類屬性(模板啊,data啊,方法啊,生命週期啊之類的。) }), (視頻裏有一句口誤,應該是小駝峯。手動捂臉)node

這個全局API看過之後,咱們來實現一個組件的hello worldvue-cli

<!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>
</head>
<body>
    <div id="app">
       <shuai-qm></shuai-qm>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.component("shuai-qm",{
            data(){
                return{
                    hello:'hello world'
                }
            },
            template:'<h1>{{hello}}</h1>'
        })
        
        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello Word',
                isTrue:true,
            },
        })
    </script>
</body>
</html>

一個全局組件的hello world就完成了,可是你們是否是以爲全局組件很是不踏實?隨時可能一個變更摧毀咱們的項目?
那不要緊,接下來是局部組建的註冊方法。express

Vue的components屬性npm

咱們在註冊局部組建的時候,須要把局部組建掛載到Vue構造器的components內,注意:全局api不帶s,而這個屬性帶s。不說廢話,咱們先來構造一個。api

<!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>
</head>
<body>
    <div id="app">
    {{message}}
       <shuai-qm></shuai-qm>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello World',
                isTrue:true,
            },
              components:{
                   "shuaiQm":{
                       data(){
                           return{
                               hello:"hello world"
                           }
                       },
                       template:'<h1>{{hello}}</h1>'
                       }
                }
            
        })
    </script>
</body>
</html>

這樣咱們就獲得了一個能夠hello world的局部組件,可是,一堆組建都這個樣子羅列出來的話,會將咱們的項目弄得體無完膚?
因此咱們抽離一下代碼。變成這樣數組

<!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>
</head>
<body>
    <div id="app">
    {{message}}
      <shuai-qm></shuai-qm>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var shuaiQm = {
            data(){
                return{
                    hello:"hello world"
                }
            },
            template:'<h1>{{hello}}</h1>'
            }


        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello World',
                isTrue:true,
            },
            components:{
                   "shuaiQm":shuaiQm,
            }
        })
    </script>
</body>
</html>

是否是用vue-cli開發過的同窗就比較眼熟了?那麼問題又來了,組件裏面的html全都是寫的字符串,都這麼玩下去,要亂死啊,沒問題,咱們繼續抽離。

這裏介紹的就是vue的template用法了,立刻又是一個cli黨眼熟的東西

<!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>
</head>

<template id="shuaiQm">
    <h1>{{hello}}</h1>
</template>

<!-- 上面是html模板的用法,下面是script模板的用法,使用<script>標籤時,type指定爲text/x-template,意在告訴瀏覽器這不是一段js腳本,瀏覽器在解析HTML文檔時會忽略<script>標籤內定義的內容。-->

<!-- 推薦 -->
<script type="x-template" id="shuaiQm2">
    <h2 style="color:blue">{{hello}}</h2>
</script>

<body>
    <div id="app">
    {{message}}
       <shuai-qm></shuai-qm>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var shuaiQm = {
            data(){
                return{
                    hello:"hello world"
                }
            },
            template:"#shuaiQm2"
            }


        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello World',
                isTrue:true,
            },
            components:{
                   "shuaiQm":shuaiQm,
            }
        })
    </script>
</body>
</html>

拆出來之後是否是莫名其妙引發了極度溫馨?固然後面咱們學到使用vue-cli的時候 咱們還會用到新的書寫方法 .vue 文件的方法,這裏就先不給你們多說了。

組件裏面套組件(父子組件)

可能由同窗會問了,組件裏面還能夠嵌套組件嗎?我能夠很負責任地告訴你,徹底沒問題!怎麼寫呢?你若是會在Vue實例的構造器裏引用組件,你就會在別的組件內部引用組件,他們實際上是一個寫法。這邊我使用咱們的第三種模板寫法來給你們書寫。

<!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>
</head>

<script type="x-template" id="father">
  <div>
    <h2 style="color:blue">{{hello}}</h2>
    <childer  />
  </div>
</script>

<script type="x-template" id="childer">
    <h2 style="color:blue">{{hello}}</h2>
</script>

<body>
    <div id="app">
    {{message}}
    <shuai-qm></shuai-qm>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var childer = {
            data(){
                return{
                    hello:"hello i'm dawangraoming"
                }
            },
            template:"#childer"
        }


        var father = {
            data(){
                return{
                    hello:"hello world"
                }
            },
            template:"#father",
            components:{
                "childer":childer
            }
            }




        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello World',
                isTrue:true,
            },
            components:{
                   "shuaiQm":father,
            }
        })
    </script>
</body>
</html>

這裏你們也能夠看到,咱們在 app內部只引用了 shuaiQm這一個組件, shuaiQm又包含他的子組件 childer,所以父子都被渲染出來了。這就是父子組件的寫法。

插槽slot

這時候又有朋友要問了,若是我想在組件裏面繼續書寫html怎麼辦呢? slot插槽就是個很好的東西了,這裏我用代碼給你們演示一下slot插槽的用法。

<!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>
</head>

<script type="x-template" id="shuaiQm2">
    <div style="color:blue">
        <h2>{{hello}}</h2>
        <solt name="solt1">我是插槽solt1</solt>
        <solt name="solt2">我是插槽solt2</solt>
        <!-- 若是插槽不使用的話,內部的默認文字就會展現出來 -->
    </div>
</script>

<body>
    <div id="app">
    {{message}}
       <shuai-qm>
           <span slot="solt1">hello world</span>
       </shuai-qm>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var shuaiQm = {
            data(){
                return{
                    hello:"hello world"
                }
            },
            template:"#shuaiQm2"
            }


        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello World',
                isTrue:true,
            },
            components:{
                   "shuaiQm":shuaiQm,
            }
        })
    </script>
</body>
</html>

插槽只有這一個做用嗎?不,那你就過小看插槽了,接下來要介紹一下插槽的做用域插槽用法。

做用域插槽,聽不懂可跳過,後面還會詳細講解

使用時候子組件標籤Child中要有 template scope=」scopeName」 標籤,再經過scopeName.childProp就能夠調用子組件模板中的childProp綁定的數據,因此做用域插槽是一種子傳父傳參的方式,解決了普通slot在parent中沒法訪問child數據的去問題;
這麼說太複雜了,直接上個例子顯而易見。
若是這裏聽不懂能夠暫時跳過,只須要會用slot插槽的基礎用法便可,在後面講Element項目的時候,我會結合實例給你們講解這個做用域插槽。

<!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>
</head>

<script type="x-template" id="shuaiQm2">
    <div style="color:blue">
        <h2>{{hello}}</h2>
        <slot name="item" v-for="item in items" :text="item.text" :myname="item.myname" >
            slot的默認內容
        </slot>
    </div>
</script>

<body>
    <div id="app">
    {{message}}
       <shuai-qm>
          <template slot="item" scope="props">
            <li>{{props.myname}}</li>
            <li>{{props.text}}</li>
          </template>
       </shuai-qm>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var shuaiQm = {
            data(){
                return{
                    hello:"hello world",
                    items:[{
                      text:"我在子組件內,經過插槽展現在父組件",
                      myname:"Qm",
                    },{
                      text:"我在子組件內,經過插槽展現在父組件",
                      myname:"奇淼",
                    }]
                }
            },
            template:"#shuaiQm2"
            }


        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello World',
                isTrue:true,
            },
            components:{
                   "shuaiQm":shuaiQm,
            }
        })
    </script>
</body>
</html>

prop 傳遞參數給組件(父傳值給子)

講到這裏,已經到了VUE一個須要理解的地方了,父子傳值,咱們先講解一下,如何將值傳遞給子組件,這個總體來講仍是比較簡單。引用咱們的組件的標籤上寫上屬性,而且把參數傳入,這樣咱們在組件內部使用props就能夠得到傳過來的值了,咱們仍是以上面的代碼爲例。

<!DOCTYPE html>
<html lang="zh-cn">
<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>
</head>

<script type="x-template" id="father">
  <div>
    <h2 style="color:blue">{{hello}}</h2>
    {{apptoshuaiqm}}
    <childer :shuai-qmtochilder="shuaiQmGiveMe" />
  </div>
</script>

<script type="x-template" id="childer">
    <div>
        <h2 style="color:blue">{{hello}}</h2>
        {{shuaiQmtochilder}}
    </div>
</script>

<body>
    <div id="app">
    <shuai-qm apptoshuaiqm="我是app傳過來的值" ></shuai-qm>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var childer = {
          props:['shuaiQmtochilder'],
            data(){
                return{
                    hello:"hello i'm dawangraoming",
                }
            },
            template:"#childer"
        }


        var father = {
            props:["apptoshuaiqm"],// 這裏你們必定要注意,請徹底使用小寫傳參
            data(){
                return{
                    hello:"hello world",
                    shuaiQmGiveMe:"我是從shuaiQm傳過來的值"
                }
            },
            template:"#father",
            components:{
                "childer":childer
            }
            }




        var app = new Vue({
            el:"#app",
            data:{
                message:'Hello World',
                isTrue:true,
            },
            components:{
                   "shuaiQm":father,
            }
        })
    </script>
</body>
</html>

這一段代碼注意,再給html上面添加屬性的時候,咱們是不能夠直接添加駝峯命名的,由於html不會區分大小寫,因此咱們建議屬性的命名方式是徹底小寫或者橫線命名的方式。若是咱們使用橫線命名來傳遞參數的話,在接收的時候,橫線後面的首字母大寫,變成小駝峯來接受,不然使用的時候它會被渲染成NaN,這是爲何呢?別忘了咱們一檔講過的,在插值表達式內,是支持簡單計算的,- 會被看成減號處理,這裏我會在視頻中給你們詳細講解。

子組件傳值給父組件

學到這裏,若是你們已經有些迷茫,如今請先停下,喘口氣,這裏難度已經慢慢加大。我也會放慢講解的速度。
若是咱們想要獲取到子組件內部的值,該怎麼辦呢?有什麼辦法可以讓咱們回去到內部的值呢?在這裏,先給你們插播一個JS寫法,我以爲這有助於理解子傳父值。

function thief (gold) {
    console.log(gold)
}

function richMan (){
    var money = 1000086
    thief(money)
}

richMan()

咱們想要在vue中作到子傳參給父,那咱們的父組件就要像子組件伸出小偷之手。我在代碼中爲你們書寫一下

<!DOCTYPE html>
<html lang="zh-cn">
<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>
</head>

<script type="x-template" id="shuaiQm">
  <div>
   
  </div>
</script>

<body>
    <div id="app">
      {{qmGold}}
    <shuai-qm :father="thief"></shuai-qm>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

        var shuaiQm = {
            props:["father"],
            data(){
                return{
                    money:"10000",
                }
            },
            template:"#shuaiQm",
            created() {
              this.father(this.money)
            },
            }



        var app = new Vue({
            el:"#app",
            data:{
              qmGold:0,
            },
            components:{
                   "shuaiQm":shuaiQm,
            },
            methods:{
              thief(gold){
                this.qmGold = gold
              }
            }
        })
    </script>
</body>
</html>

這樣 你理解子傳參給父了嗎?

其他會用到的全局API

Vue.directivet
Vue.directive 咱們用來編寫全局指令,它也有本身的生命週期

// 註冊
Vue.directive('my-directive', {
  bind: function () {},
  inserted: function () {},
  update: function () {},
  componentUpdated: function () {},
  unbind: function () {}
})

/*
bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置。

inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不必定已被插入文檔中)。

update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前。指令的值可能發生了改變,也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 (詳細的鉤子函數參數見下)。

componentUpdated:指令所在組件的 VNode 及其子 VNode 所有更新後調用。

unbind:只調用一次,指令與元素解綁時調用。

接下來咱們來看一下鉤子函數的參數 (即 el、binding、vnode 和 oldVnode)。

在這些鉤子函數內部,均可以接受三個參數,咱們來看看文檔中的寫法。
el:指令所綁定的元素,能夠用來直接操做 DOM 。

binding:一個對象,包含如下屬性:
    name:指令名,不包括 v- 前綴。
    value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值爲 2。
    oldValue:指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用。不管值是否改變均可用。
    expression:字符串形式的指令表達式。例如 v-my-directive="1 + 1" 中,表達式爲 "1 + 1"。
    arg:傳給指令的參數,可選。例如 v-my-directive:foo 中,參數爲 "foo"。
    modifiers:一個包含修飾符的對象。例如:v-my-directive.foo.bar 中,修飾符對象爲 { foo: true, bar: true }。
vnode:Vue 編譯生成的虛擬節點。
oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。

這裏我會在視頻中結合官方樣例講解
*/

上面咱們羅列了這麼多它的特性,不過真正開發中,咱們最經常使用的只有 bind 和 update 這兩個時期
咱們能夠簡寫爲

Vue.directive('color', function (el, binding) {
        el.style.backgroundColor = binding.value
    })

下面咱們來舉個例子

<!DOCTYPE html>
<html lang="zh-cn">
<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>
</head>

<script type="x-template" id="shuaiQm">
  <div>
   
  </div>
</script>

<body>
    <div id="app">
      <div v-color="color">
          我來測試測試directive
      </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.directive("color",function(el,binding){
            el.style.color = binding.value
        })

        var app = new Vue({
            el:"#app",
            data:{
                color:"red"
            }
        })
    </script>
</body>
</html>

好了咱們能夠看到加上v-color的這個div內部的文字變紅了

Vue.set

Vue.set官網給出的用法是 Vue.set( target, key, value ) 向響應式對象中添加一個屬性,並確保這個新屬性一樣是響應式的,且觸發視圖更新。它必須用於向響應式對象上添加新屬性,由於 Vue 沒法探測普通的新增屬性
這麼聽起來是有些籠統的,我給你們用代碼展現一下它在咱們平常開發中常常出現的場景。

<!DOCTYPE html>
<html lang="zh-cn">
<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>
</head>

<body>
    <div id="app">
      <ul>
        <li v-for="(item,ket) in list" :key="key">{{item.hello}}</li>
      </ul>
      <button @click="addList">+</button>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

        var app = new Vue({
            el:"#app",
            data:{
                list:[{hello:"hello world"},{hello:"hello two"}]
            },
            methods:{
                addList(){
                   this.list[0] = {hello:"ttt"}
                    console.log(this.list)
                }
            }
        })
    </script>
</body>
</html>

在上述代碼中,咱們經過this.list[0]直接修改了數組中的第0項目對象,那麼視圖是沒有更新的,可是數據確實變動了,這是爲何呢?由於Vue是經過Object.defineProperty()來進行數據的監聽,它的機制致使了它沒法直接檢測出數組中這種狀況的變化。這時候咱們就須要使用Vue.set了

<!DOCTYPE html>
<html lang="zh-cn">
<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>
</head>

<body>
    <div id="app">
      <ul>
        <li v-for="(item,ket) in list" :key="key">{{item.hello}}</li>
      </ul>
      <button @click="addList">+</button>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

        var app = new Vue({
            el:"#app",
            data:{
                list:[{hello:"hello world"},{hello:"hello two"}]
            },
            methods:{
                addList(){
                   this.list[0] = {hello:"ttt"}
                    console.log(this.list)
                }
            }
        })
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-cn">
<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>
</head>

<body>
    <div id="app">
      <ul>
        <li v-for="(item,ket) in list" :key="key">{{item.hello}}</li>
      </ul>
      <button @click="addList">+</button>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

        var app = new Vue({
            el:"#app",
            data:{
                list:[{hello:"hello world"},{hello:"hello two"}]
            },
            methods:{
                addList(){
                //    this.list[0] = {hello:"ttt"}
                    Vue.set(this.list,0, {hello:"我強制改變了!"})
                    // this.$set(this.list,0,{hello:"我強制改變了!"})  在methods 中能夠寫成 this.$set 
                    console.log(this.list)
                }
            }
        })
    </script>
</body>
</html>

看 是否是強制將它改變了呢? 有了Vue.set 數據就都再也不得瑟了

相關文章
相關標籤/搜索