Vue插槽、ref和$refs用法


1.vue插槽

1.插槽的作用:以局部組件為例

  插槽就是Vue實現的一套內容分發的API,將<slot></slot>元素作為承載分發內容的出口。插槽內可以是任意內容。

(1)不帶插槽的情況:

        <div id="app">
            <vue>
                <h2>我是里面的內容</h2></vue>
        </div>

        <script>
            var Child = {
                template: '<div><h1>自定義組件!</h1></div>'
            }

            // 創建根實例
            new Vue({
                el: '#app',
                components: {
                    // <vue> 將只在父模板可用
                    'vue': Child
                }
            })
        </script>

結果:組件標簽內的元素不會顯示

 

(2)帶插槽的情況:標簽內部的元素會被置於<slot></slot>的位置

        <div id="app">
            <vue>
                <h2>我是里面的內容</h2></vue>
        </div>

        <script>
            var Child = {
                template: '<div><h1>自定義組件!</h1><slot></slot></div>'
            }

            // 創建根實例
            new Vue({
                el: '#app',
                components: {
                    // <vue> 將只在父模板可用
                    'vue': Child
                }
            })
        </script>

結果:

 

 2.編譯作用域

  父級模板里的所有內容都是在父級作用域中編譯的;子模板里的所有內容都是在子作用域中編譯的。

  插槽跟模板的其它地方一樣可以訪問相同的實例屬性 (也就是相同的“作用域”),而不能訪問 插槽上的屬性。

如下:slot內部可以訪問到vue實例的msg屬性,訪問不到組件的message屬性。

        <div id="app">
            <vue message="message123">
                <h2>{{msg}}</h2>
                <h2 v-if="typeof  message != 'undefined'">{{message}}</h2>
                <h2 v-else>訪問不到message屬性</h2>
            </vue>
        </div>

        <script>
            var Child = {
                template: '<div><h1>自定義組件!</h1><h2>{{message}}</h2><br/><slot></slot></div>',
                // 聲明 props屬性
                props: ['message'],
            }

            // 創建根實例
            new Vue({
                el: '#app',
                components: {
                    // <vue> 將只在父模板可用
                    'vue': Child
                },
                data: {
                    msg: '這是msg'
                }
            })
        </script>

結果:

 

 3.帶有 slot-scope 特性的作用域插槽

  在組件上的屬性,可以在組件元素內使用!

(1)  在 <template> 上使用特殊的 slot-scope 特性,可以接收傳遞給插槽的 prop

        <div id="app">
            <child>
                <template slot-scope="a">
                    {{a}}
                    <br /> {{a.username}}
                </template>
            </child>
        </div>
        <script>
            Vue.component('child', {
                template: `
            <div>
                <slot username="張三"></slot>
            </div>
        `

            })

            let vm = new Vue({
                el: '#app'
            })
        </script>

結果:

 

 解釋:

(1)組件中的<slot username="張三"></slot>定義了一個屬性,

(2)slot-scope 聲明了被接收的 a 對象會作為 a 變量存在於 <template> 作用域中。你可以像命名 JavaScript 函數參數一樣隨意命名 a

(3)slot-scope 特性也可以直接用於非 <template> 元素 (包括組件):

            <child>
                <h3 slot-scope="a">{{a}}=={{a.username}}</h3>
            </child>

結果:

 

 (2)獲取組件上值

        <div id="app">
            <child componentmsg="123456">
                <h3 slot-scope="a">{{a}}</h3>
            </child>
        </div>
        <script>
            Vue.component('child', {
                props: ['componentmsg'],
                template: `
            <div>
                <slot :slotmsg="componentmsg"></slot>
            </div>
        `
            })

            let vm = new Vue({
                el: '#app'
            })
        </script>

結果:

 (3)獲取vue實例屬性:(組件的屬性動態獲取實例的屬性)

        <div id="app">
            <child :componentmsg="vueMsg">
                <h3 slot-scope="a">{{a}}</h3>
            </child>
        </div>
        <script>
            Vue.component('child', {
                props: ['componentmsg'],
                template: `
            <div>
                <slot :slotmsg="componentmsg"></slot>
            </div>
        `
            })

            let vm = new Vue({
                el: '#app',
                data: {
                    vueMsg: '這是實例屬性'
                }
            })
        </script>

結果:

 

補充:自 2.6.0 起有所更新。上面使用 slot-scope 特性的語法已經廢棄。2.6以后做法如下:綁定在 <slot> 元素上的特性被稱為插槽 prop。現在在父級作用域中,我們可以給 v-slot 帶一個值來定義我們提供的插槽 prop 的名字: 

        <div id="app">
            <child :user="user">
                <template v-slot:default="slotProps"> {{ slotProps.user.firstName }}</template>
            </child>
        </div>
        <script>
            Vue.component('child', {
                props: ['user'],
                template: `
            <div>
                <slot v-bind:user="user"></slot>
            </div>
        `
            })

            let vm = new Vue({
                el: '#app',
                data: {
                    user: {
                        lastname: '張',
                        firstName: '三'
                    }
                }
            })
        </script>

結果:

 4..具名插槽

  有時候我們可能需要多個插槽。slot有一個特殊的屬性,name可以用於定義額外的插槽。

例如:不帶名稱的默認都會被放在無名稱的slot內。

        <div id="app">
            <vue>
                <template slot="h1s">
                    <p>這里是h1的內容</p>
                </template>
                <template slot="h2s">
                    <b><p>這里是h2的內容</p></b>
                </template>
                <p slot="h1s">這里是其他內容</p>
                <p>這里是其他內容</p>
            </vue>
        </div>

        <script>
            var Child = {
                template: '<div><h1><slot name="h1s"></slot></h1><h2><slot name="h2s"></slot></h2><br/><hr/><slot></slot></div>'
            }

            // 創建根實例
            new Vue({
                el: '#app',
                components: {
                    // <vue> 將只在父模板可用
                    'vue': Child
                },
                data: {
                    msg: '這是msg'
                }
            })
        </script>

結果:

補充:上面是vue2.6之前的寫法,vue2.6之后有所區別:

(1)一個不帶 name 的 <slot> 出口會帶有隱含的名字“default”。

(2)在向具名插槽提供內容的時候,我們可以在一個 <template> 元素上使用 v-slot 指令,並以 v-slot 的參數的形式提供其名稱

(3)任何沒有被包裹在帶有 v-slot 的 <template> 中的內容都會被視為默認插槽的內容。

(4)注意 v-slot 只能添加在 <template> 上

        <div id="app">
            <vue>
                <template v-slot:h1s>
                    <p>這里是h1的內容</p>
                </template>
                <template v-slot:h2s>
                    <b><p>這里是h2的內容</p></b>
                </template>
                <!--v-slot:default可以不寫,默認都是default插槽的-->
                <template v-slot:default>
                    <b><p>這里是其他內容</p></b>
                </template>
            </vue>
        </div>

結果:

 

縮寫:2.6.0 新增

跟 v-on 和 v-bind 一樣,v-slot 也有縮寫,即把參數之前的所有內容 (v-slot:) 替換為字符 #。例如 v-slot:h1s 可以被重寫為 #h1s:

            <vue>
                <template #h1s>
                    <p>這里是h1的內容</p>
                </template>
                <template #h2s>
                    <b><p>這里是h2的內容</p></b>
                </template>
                <!--v-slot:default可以不寫,默認都是default插槽的-->
                <template #default>
                    <b><p>這里是其他內容</p></b>
                </template>
            </vue>

 

5.動態插槽名

  vue2.6新增了動態參數,可以用方括號括起來的 JavaScript 表達式作為一個指令的參數。

例如:

<a v-on:[eventName]="doSomething"> ... </a>

  在這個示例中,當 eventName 的值為 "focus" 時,v-on:[eventName] 將等價於 v-on:focus。

 

動態指令參數也可以用在 v-slot 上,來定義動態的插槽名:

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout><base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>

 

2.ref和$ref的使用

  ref被用來給組件或子元素注冊引用信息,引用信息將會注冊在父組件的$ref屬性上。

  vm.$refs是一個只讀屬性,返回值是一個對象,持有注冊過 ref 特性 的所有 DOM 元素和組件實例。。

 

  如果在普通的dom上使用,引用指向的就是DOM對象 ,$refs相對document.getElementById的方法,會減少獲取dom節點的消耗。;如果用在子組件上,引用指向組件實例。

例如:

        <div id="app">
            <p ref="pref">p內容</p>
            <child ref="child">
                <template>插槽內容</template>
            </child>
        </div>
        <script>
            Vue.component('child', {
                template: `
            <div>
                <p ref="pref1">p1內容</p>
                <slot></slot>
            </div>
        `
            })

            let vm = new Vue({
                el: '#app',
            })

            console.log(vm.$refs.pref)
            console.log(vm.$refs.child)
            console.log(vm.$refs.child.$refs.pref1)
        </script>

結果:

 

持有注冊過 ref 特性 的所有 DOM 元素和組件實例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM