Vue入門學習之技術分享-2(深刻理解Vue組件)

前言

繼前幾天學習了指令,屬性學習後,這兩天又深刻學習了組件。每次學習事後發一篇文章,本身對知識點的記憶也更加深入了,同時也但願本身的分享可以幫助到其餘人html

正文

使用組件的細節點

is的使用

<!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>組件中的細節點</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <table>
            <tbody>
                <row></row>
                <row></row>
                <row></row>
            </tbody>
        </table>
    </div>
    <script>
        Vue.component('row', {
            template:'<tr><td>this is a row</td></tr>'
        })
        var vm = new Vue({
            el:'#root'
        })
    </script>
</body>
</html>
複製代碼

上述代碼將this is a row封裝成一個名爲row的Vue全局組件,並在tbody中引用了row組件,使用時徹底符合html5頁面規範table裏面有tbody,tbody裏面有tr,頁面顯示出來的結果以下,看起來也沒有任何問題vue

可是頁面檢查查看Elements時你會發現出錯了,正常狀況下tr應該在tbody可是如今卻跟table同級。

這個BUG咱們應該如何解決呢?這個時候咱們就應該用到Vue給咱們提供的is屬性來解決這個問題。在tbody只能寫tr那咱們就寫tr好了,可是咱們寫這個tr並非真的顯示tr而是想把row組件裏面的內容顯示進去。

<tbody>
        <tr is="row"></tr>
        <tr is="row"></tr>
        <tr is="row"></tr>
</tbody>
複製代碼

這個時候在tr後面加一個is屬性讓它等於row就行了,意思就是雖然我是tr可是我實際上是一個row組件,這樣既可以保證tr裏面顯示的是咱們的row組件又保證咱們符合h5的編碼規範,程序不會有BUG。而且建議像ul、ol、select下面也不要直接使用row這個組件,由於有些瀏覽器會顯示bug,因此就用Vue提供的is屬性就行了html5

組件中的data

在組件中使用data以下vuex

Vue.component('row', {
            data:{
                content:'this is arow'
            },
            template: '<tr><td>{{content}}</td></tr>'
        })
複製代碼

頁面渲染報錯數組

這是由於組件中的data必須是一個函數而且須要返回一個對象。之因此這樣是由於子組件不像根組件同樣只調用一次,它在不少地方都會被調用,而在每次調用都不但願和其餘子組件產生衝突或者說每一個子組件都應該有本身的數組。經過一個函數來返回一個對象的目的就是讓每個子組件都擁有獨立的數組存儲,這樣就不會出現多個子組件相互影響的狀況。以下,這樣頁面才能正常顯示,初學Vue的小白,很容易忘記這一點而後頁面瘋狂報錯,因此請記住這一基礎知識點

data() {
                return {
                    content: 'this is a row'
                }
            },
複製代碼

ref的使用

Vue不建議咱們在代碼裏面去操做dom,可是在處理一些及其複雜的動做效果時,你不操做dom光靠Vue的數據綁定,有的時候處理不了這樣的狀況,因此在必要狀況下須要操做dom。那麼咱們如何操做dom呢?咱們須要經過ref這種引用的形式獲取到進行dom的操做。瀏覽器

<!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>組件中的細節點</title>
    <script src="../vue.js"></script>
</head>

<body>
    <div id="root">
        <div 
            ref='hello' 
            @click="handleClick">hello world
        </div>
    </div>
    <script>
        var vm = new Vue({
            el: '#root',
            methods: {
                handleClick: function() {
                    console.log(this.$refs.hello)
                }
            },
        })
    </script>
</body>

</html>
複製代碼

咱們在div上添加了一個ref屬性並命名爲hello,而且綁定了一個名爲handleClick的點擊方法,在Vue實例的methods方法中打印了一串代碼。bash

this.$refs.hello
複製代碼

這個代碼的意思就是整個Vue實例裏面全部的引用裏面的名爲hello的引用,這個引用只的就是被修飾的div的DOM結點,因此下面的this.$refs.hello指向的就是相對應的div的dom結點,打印結果以下markdown

因此在Vue當中咱們能夠經過ref來獲取Dom結點,而後咱們就能夠經過結點獲取innerHTML 接下來咱們用這個功能作一個計數器的栗子。

<!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>組件中的細節點</title>
    <script src="../vue.js"></script>
</head>

<body>
    <div id="root">
        <!-- 當子組件觸發change事件時,父組件能監聽到這個事件並執行handleChange這個方法 -->
        <counter ref="one" @change="handleChange"></counter>
        <counter  ref="two" @change="handleChange"></counter>
        <div>{{total}}</div>
    </div>
    <script>
        Vue.component('counter', {
            template: '<div @click="handleClick">{{number}}</div>',
            data() {
                return {
                    number: 0
                }
            },
            methods: {
                handleClick: function() {
                    this.number ++
                    // 子組件向父組件傳值,這裏的意思是當子組件觸發事件時同時告訴外面觸發一個事件
                    this.$emit('change')
                }
            },
        })
        var vm = new Vue({
            el: '#root',
            data:{
                total: 0
            },
            methods:{
                handleChange: function() {
                    this.total = this.$refs.one.number + this.$refs.two.number
                }
            }
        })
    </script>
</body>

</html>
複製代碼

上述代碼中封裝了一個counter組件實現了一個點擊實現num++的功能,在html引用了兩次counter組件。咱們須要實現的是在父組件中計算兩個counter組件中值的和。這時就須要在子組件上添加ref屬性。而後再父組件中用 this.$refs.(ref名稱)獲取組件並經過.number獲取每一個引用組件各自的number值並相加實現求total的功能。app

父子組子組件傳值

父->子

父組件如何向子組件傳值呢? 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>父子組件傳值</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- count前面加了冒號,傳遞給子組件的就是數組,不加冒號傳遞給子組件的就是字符串,由於加了冒號後,後面的雙引號的內容其實是一個js表達式了就不是一個字符串了 -->
        <counter :count="0"></counter>
        <counter :count="1"></counter>
    </div>

    <script>
        var counter = {
            // 在子組件中寫一個props(用來接收父組件傳遞過來的內容),接收完之後就能夠在子組件中直接使用了
            props:['count'],
            template: '<div>{{count}}</div>'
        }
        var vm = new Vue({
            el: '#root',
            components:{
                counter
            }
        })
    </script>
</body>
</html>
複製代碼

上面栗子,聲明瞭一個局部counter組件並掛載到了vm根實例中並在頁面引用了counter組件,其中父組件經過在counter組件中添加屬性:count="0/1"(count前面加了冒號,傳遞給子組件的就是數組,不加冒號傳遞給子組件的就是字符串,由於加了冒號後,後面的雙引號的內容其實是一個js表達式了就不是一個字符串了)。那麼子組件如何接收父組件的傳值呢?子組件須要在內部寫一個props用來接收父組件傳遞過來的內容。這樣就能在子組件內部使用啦,這時候咱們再修改一會兒組件中的代碼

var counter = {
            // 在子組件中寫一個props(用來接收父組件傳遞過來的內容),接收完之後就能夠在子組件中直接使用了
            props:['count'],
            template: '<div @click="handleClick">{{count}}</div>',
            methods: {
                handleClick: function() {
                    this.count ++
                }
            },
        }
複製代碼

在子組件中添加一個方法實現點擊+1的效果。你會發現頁面上實現正確,可是打開控制檯就有報錯信息了

爲何呢?由於在Vue之中有一個 單項數據流的概念,也就是說 父組件能夠經過屬性的形式向子組件傳遞參數可是子組件只能使用父組件傳遞過來的內容而不能修改子組件傳遞過來的參數。之因此Vue當中有單項數據流的概念, 緣由在於,一旦 子組件接收的內容並 不是基礎類型的數據,而 是一個引用形式數據的時候,你在 子組件改變了父組件傳遞過來的內容時,有可能接收的數據還被其餘的組件所使用,因此當你 改變父組件傳遞過來的數據時還會影響其餘的子組件。那麼如何解決呢?

var counter = {
            // 在子組件中寫一個props(用來接收父組件傳遞過來的內容),接收完之後就能夠在子組件中直接使用了
            props:['count'],
            data() {
                return {
                    // 複製了一份count放到子組件本身的data中
                    number:this.count
                }
            },
            template: '<div @click="handleClick">{{number}}</div>',
            methods: {
                handleClick: function() {
                    this.number ++
                }
            },
        }
複製代碼

咱們須要在子組件的data中自定義一個number複製一份父組件傳遞過來的count,這樣就能夠在組件中使用子組件本身number了。這樣控制檯就不會報錯啦。

子->父

子組件向父組件傳值是經過**$emit()**方法來實現對外暴露的

<!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>父子組件傳值</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <counter :count="3" @inc="handleIncrease"></counter>
        <counter :count="2"  @inc="handleIncrease"></counter>
        <div>{{total}}</div>
    </div>

    <script>
        var counter = {
            props:['count'],
            data() {
                return {
                    // 複製了一份count放到子組件本身的data中
                    number:this.count
                }
            },
            template: '<div @click="handleClick">{{number}}</div>',
            methods: {
                handleClick: function() {
                    this.number = this.number + 2
                    // 每次觸發事件時都告訴外部觸發了一個inc事件,而且攜帶了一個參數(能夠攜帶多個參數)
                    this.$emit('inc',2)
                }
            },
        }
        var vm = new Vue({
            el: '#root',
            data:{
                total: 5
            },
            components:{
                counter
            },
            methods:{
                // 子組件觸發inc事件時傳遞了一個參數,這時就能夠在父組件中的方法中接收這個參數了
                handleIncrease:function(num) {
                    this.total+=num
                }
            }
        })
    </script>
</body>
</html>
複製代碼

代碼中在子組件counter中的handleClick方法中經過this.$emit(inc,2)向父組件暴露了一個inc事件,而且攜帶了一個參數2(不只僅能攜帶一個參數,它能夠攜帶多個參數)。而在父組件中

<counter :count="3" @inc="handleIncrease"></counter>
        <counter :count="2"  @inc="handleIncrease"></counter>
複製代碼

經過handleIncrease來監聽inc事件,在vm根實例中的methods方法中定義handleIncrease方法,因爲子組件向父組件傳遞了參數,因此handleIncrease能夠在方法中接收這個參數並使用。

組件參數校驗與非Props特性

組件的參數校驗

什麼是組件的參數校驗? 父組件向子組件傳遞了內容,那麼子組件有權對這些內容進行約束,這些約束就是參數的校驗。

<!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>組件參數校驗與非Props特性</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <child content="hello world"></child>
    </div>
    <script>
        Vue.component('child', {
            props: {
                // content:String,//子組件接收到的content必須是String類型的,若是不是String類型那麼當子組件用了content值得時候控制檯將會發出警告。
                // 若是須要給定多個類型則須要把類型放入數組中
                // content:[ Number, String ],
                // 固然這些約束還能夠更加複雜,實際上還能夠跟一個對象
                content:{
                    type:String, //type規定類型
                    required:true, //required則表示這個參數是必傳的,若是父組件不傳這個屬性則會報錯
                    default:'default value', //當required爲false時(接收到的屬性值不是必傳的),設置default則會在父組件沒傳值的時候用默認值(default value)代替
                    validator:function(value) {
                        return (value.length > 5 )
                    }
                }
            },
            template:`<div>
                        <p>{{content}}</p>
                    </div>`
        })
        var vm = new Vue({
            el: '#root'
        })
    </script>
</body>
</html>
複製代碼

上面的代碼中父組件向子組件傳遞了一個content屬性。那麼咱們如何在子組件中對它進行約束呢?首先咱們須要把prop定義成一個對象。最簡單的就是隻約束類型而且類型只有一個了。下面的這段代碼的意思是子組件接收到的content必須是String類型的,若是不是String類型那麼當子組件用了content值得時候控制檯將會發出警告。

props: {
    conten:String
    }
複製代碼

若是要給content規定多個類型呢?只須要在後面使用數組就好了

content:[ Number, String ]
複製代碼

固然這些約束還能夠更加複雜,實際上還能夠跟一個對象。能夠看下面這段代碼以及其中的註釋

content:{
                    type:String, //type規定類型
                    required:true, //required則表示這個參數是必傳的,若是父組件不傳這個屬性則會報錯
                    default:'default value', //當required爲false時(接收到的屬性值不是必傳的),設置default則會在父組件沒傳值的時候用默認值(default value)代替
                    validator:function(value) {
                        return (value.length > 5 )
                    }
                }
            },
複製代碼

非Props特性

什麼叫作非Pops特性和Props特性呢? Props特性指的是當你的父組件使用子組件的時候,經過屬性屬性向子組件傳值的時候剛好子組件裏面聲明瞭對父組件傳遞過來的屬性的接收。非Pops特性值的時父組件向子組件傳遞了一個屬性,可是子組件並無聲明接收父組件傳遞過來的內容。

  • 非Props第一個特色:若是在這種狀況下使用了沒接收的值頁面就會報錯,這是由於你的父組件向子組件傳遞了值,可是子組件並無接收父組件傳遞過來的值。
  • 第二個特色:這個屬性會展現在子組件最外層的dom標籤的html屬性裏面

給組件綁定原生事件

先看一段代碼

<!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>給子組件綁定原生事件</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <child @click="handleClick"></child>
    </div>
    <script>
        Vue.component('child', {
            template:`
                <div>
                    Child
                </div>
                `
        })
        var vm = new Vue({
            el:'#root',
            methods: {
                handleClick: function() {
                    alert('點擊了')
                }
            },
        })
    </script>
</body>
</html>
複製代碼

上面的代碼乍一眼看當咱們點擊child組件的dom時,會觸發父組件上的點擊事件方法。可是運行上面的代碼時會發如今父組件中定義的點擊事件是沒有用的。這是怎麼一回事呢?當給一個組件綁定一個事件的時候,實際上這個事件綁定的時一個自定義的事件,也就是說若是你的鼠標點擊觸發的事件,並非綁定的click事件,若是想要觸發自定義的click事件,必須在子組件裏面對須要觸發事件的dom元素進行事件的綁定,這個事件纔是真正的原生事件。添加下面部分代碼

Vue.component('child', {
            template:`
                <div @click="handleChildClick">
                    Child
                </div>
                `,
            methods:{
                handleChildClick: function() {
                    alert("child click")
                }
            }
        })
複製代碼

點擊dom元素時child click 被打印出來了子組件的原生事件被觸發了,而父組件的事件沒有被觸發

自定義事件如何觸發再往上內容以已經用到過,我再這裏再講一遍

this.$emit('click')
複製代碼

只須要在子組件methods中調用$click(由於自定義事件的名稱爲click,這裏的名字必須與自定義事件名稱保持一致),這樣父組件中的事件就能被調用了,這樣當點擊child組件綁定了handleChildClick事件的dom元素就會再打印下面這條消息了

上面的代碼是否是特別煩,每次綁定事件都要傳遞兩次?那麼有沒有更簡單的方法呢?確定是有的。直接在自定義事件後加一個 native修飾符就能夠了。回到最初沒法實現點擊效果的版本

<!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>給子組件綁定原生事件</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- 在組件上加一個native修飾符,表示監聽的是原生的點擊事件 -->
        <child @click.native="handleClick"></child>
    </div>
    <script>
        Vue.component('child', {
            template:`
                <div @click="handleChildClick">
                    Child
                </div>
                `
        })
        var vm = new Vue({
            el:'#root',
            methods: {
                handleClick: function() {
                    alert('點擊了')
                }
            },
        })
    </script>
</body>
</html>
複製代碼

在代碼中的自定義事件上加上**.native**修飾就表示觸發的是原生的點擊事件了,這就是給組件綁定原生事件的方法了

<child @click.native="handleClick"></child>
複製代碼

非父子組件之間的傳值

一個網頁能夠拆分爲不少部分,每個部分就是代碼中的組件

父子組件的傳值問題上面已經講過了(父->子-經過屬性,子->父通-過事件觸發)。那麼如何在非父子組件之間傳值呢?

  • 藉助Vue官方提供的數據層框架vuex來解決這個問題,固然vuex使用起來是有難度的。可能會在以後學完後的項目中運用,若是我學會了的話,這裏就不講了,由於我也不會
  • 使用發布訂閱模式來解決,發佈訂閱模式在Vue中也被稱爲總線。 這裏須要實現一個點擊一個組件的DOM元素,其兄弟組件也跟着變得栗子
<!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>非父子組件間的傳值(Bus/總線/發佈訂閱模式/觀察者模型)</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="app">
        <child content='Yu'></child>
        <child content='Han'></child>
    </div>
    <script>
        // 在Vue的prototype上掛載了一個名字叫作bus的屬性,而且這個屬性指向Vue()的實例,只要咱們以後去調用new.vue或者建立組件的時候,每一個組件都會有bus這個屬性
        // 由於每一個組件或者每一個Vue實例都是經過類來建立的,而我在vue的prototype上掛載了一個bus屬性
        Vue.prototype.bus = new Vue()
        Vue.component('child',{
            props:{
                content:String
            },
            data() {
                return {
                    selfcontent:this.content
                }
            },
            template:'<div @click="handleClick">{{selfcontent}}</div>',
            methods: {
                handleClick:function() {
                    this.bus.$emit('change',this.selfcontent) //由於bus是vue的實例,因此可使用$emit
                }
            },
            // 聲明一個mounted生命鉤子函數
            mounted:function() {
                // 在鉤子函數中this指向會發生改變因此須要作如下工做
                var this_ = this
                this.bus.$on('change',function(msg) {
                    this_.selfcontent = msg  //
                })//由於bus是個實例因此有$on的方法,它就能監聽到bus上面觸發出來的事件(change),而且能接收帶過來的參數
            },
        })
        var vm = new Vue({
            el: '#app'
        })
    </script>
</body>
</html>
複製代碼
  1. 在Vue的prototype上掛載了一個名字叫作bus的屬性,而且這個屬性指向Vue()的實例,只要咱們以後去調用new.vue或者建立組件的時候,每一個組件都會有bus這個屬性由於每一個組件或者每一個Vue實例都是經過類來建立的,而我在vue的prototype上掛載了一個bus屬性
  2. 在組件中使用this.bus.emit拋出一個事件(由於bus是vue的實例,因此可使用emit),而且攜帶須要的參數
this.bus.$emit('change',this.selfcontent)
複製代碼
  1. 聲明一個mounted生命鉤子函數而且定義_this=this,由於鉤子函數中this會發生改變
  2. 使用bus實例上的$on方法監聽組件拋出的change事件並接收參數再對selfcontent 進行修改就能夠了
this.bus.$on('change',function(msg) {
                    this_.selfcontent = msg  //
                })//由於bus是個實例因此有$on的方法,它就能監聽到bus上面觸發出來的事件(change),而且能接收帶過來的參數
複製代碼

在Vue中使用插槽(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>Vue中的插槽(slot)</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="app">
        <child>
            <p>Yu</p>
        </child>
    </div>
    <script>
        Vue.component('child',{
            template:`<div>
            <P>HELLO</P>
            <slot>默認內容</slot>
            </div>`
        })
        var vm = new Vue({
            el: '#app'
        })
    </script>
</body>
</html>
複製代碼

上面的代碼在child組件中插入了p標籤和Yu內容,如何在組件中接收這個內容呢只須要在模板中使用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>Vue中的插槽(slot)</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="app">
        <contentx>
            <div class="header">header</div>
            <div class="footer">footer</div>
        </contentx>
    </div>
    <script>
        Vue.component('contentx',{
            template:`<div>
                            <slot></slot>
                            <div class='content'>content</div>
                            <slot></slot>
                         </div>`
        })
        var vm = new Vue({
            el: '#app'
        })
    </script>
</body>
</html>
複製代碼

上面這段代碼的目的是在頁面上顯示出一個header、一個content、一個footer。結果倒是

爲何呢?由於slot是顯示組件中添加的全部標籤元素。

這時候嘿嘿嘿就須要用到咱們稍微高大上一點的具名插槽了,將上面部分代碼修改爲這樣

<div id="app">
        <contentx>
            <div class="header" slot="header">header</div>
            <div class="footer" slot="footer">footer</div>
        </contentx>
    </div>
    <script>
        Vue.component('contentx',{
            template:`<div>
                            <slot name='header></slot> <div class='content'>content</div> <slot name='footer'></slot> </div>` }) var vm = new Vue({ el: '#app'
        })
複製代碼
  1. 給contentx組件內插入的標籤元素添加一個solt屬性並命名
  2. 在組件模板中使用slot時指明name也就是在1中添加的屬性名。這樣就能夠哪裏要用指哪裏,媽媽不再用擔憂個人學習的。

做用域插槽

當一個組件中某些標籤元素是經過循環自身data中的某個數組來進行渲染的時候,而這個組件又須要給其餘組件使用,這時這個組件中的模板樣式就不能被寫死,由於每一個組件須要循環的次數是不同的。或者組件中的某一部分須要經過外部傳遞進來的時候,這時候就須要用到做用域插槽了

<!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>Vue中的做用域插槽</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="app">
        <child>
            <!-- 必定要在最外層套用一個template,這時固定寫法,同時要寫一個slot-scope="自定義名字" 
             它的意思是當子組件用slot的時候會往slot裏面傳遞一個item數據,這樣就可使用item了,而item是放在slot-scope="自定義名字"當中-->
             <!-- 這個時候每一項應該顯示成什麼,就不禁子組件決定了,而是父組件調子組件的時候給子組件去傳遞對應的模板 -->
            <template slot-scope="props">
                <li>{{props.item}} - hello</li>
            </template>
        </child>
    </div>
    <script>
        Vue.component('child',{
            data() {
                return {
                    list:[1,2,3,4]
                }
            },
            template:`<div>
                         <ul>
                            <slot v-for="item of list" :item=item></slot>
                         </ul>
                    </div>`
        })
        var vm = new Vue({
            el: '#app'
        })
    </script>
</body>
</html>
複製代碼
  1. 在child組件中的模板內的slot中傳遞item出去
  2. 在根組件中使用了child全局組件,並在裏面使用了做用域插槽(必須用template包裹,這是固定寫法),同時用slot-scope聲明要從child組件中接收的數據(item)都放在哪,這裏是props中。
  3. 在template中告訴child組件應該怎樣渲染頁面,這裏是以h1標籤的形式對數據進行展現。

結語

但願這篇文章能對您有所幫助,太困了晚安

相關文章
相關標籤/搜索