插槽就是Vue實現的一套內容分發的API,將<slot></slot>元素做爲承載分發內容的出口。插槽內能夠是任意內容。vue
(1)不帶插槽的狀況:api
<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>
結果:組件標籤內的元素不會顯示app
(2)帶插槽的狀況:標籤內部的元素會被置於<slot></slot>的位置dom
<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>
結果:函數
父級模板裏的全部內容都是在父級做用域中編譯的;子模板裏的全部內容都是在子做用域中編譯的。spa
插槽跟模板的其它地方同樣能夠訪問相同的實例屬性 (也就是相同的「做用域」),而不能訪問 插槽上的屬性。3d
以下:slot內部能夠訪問到vue實例的msg屬性,訪問不到組件的message屬性。code
<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>
結果:component
在組件上的屬性,能夠在組件元素內使用!對象
(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>
結果:
有時候咱們可能須要多個插槽。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>
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>
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 元素和組件實例。