您好,登錄后才能下訂單哦!
今天小編給大家分享一下Vue中的插槽、內容分發、具名插槽應用實例分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
Vue中組件的數據可以通過props進行傳遞,或者通過事件的方式進行獲取傳遞,但當需要接收模板內容(任意合法的模板內容,代碼片段、Vue組件)時,就需要使用插槽來實現了。當然也可以通過函數式編程間接實現。
可以將插槽理解為js中的函數進行編譯
// 父元素傳入插槽內容
FancyButton('Click me!')
// FancyButton 在自己的模板中渲染插槽內容
function FancyButton(slotContent) {
return `<button class="fancy-btn">
${slotContent}
</button>`
}
最好的封裝方式是將共性抽取到組件中,將不同點暴露為插槽 - 抽取共性,保留不同
父組件模板的所有東西都會在父組件作用域中編譯,子組件模板的所有東西都會在子組件作用域內編譯 - 編譯作用域
常規的slot可以用于自定義組件的模板,但只是限制于固定的模板,無法自定義內部的具體的某一項,即常規的slot無法實現對組件循環體的每一項進行不同的內容分發,此時可以通過slot-scope進行實現,本質上和slot一樣,不同點在于可以進行參數傳遞
//普通的組件定義
<ul>
<li v-for="book in books" :key="book.id">
{{ book.name }}
</li>
</ul>
//slot-scope組件定義
<ul>
<li v-for="book in books" :key="book.id">
<slot :book="book" name="bookInfo">
<!-- 默認內容 -->
{{ book.name }}
</slot>
</li>
</ul>
//父組件使用
<book-list :books="books">
<template slot-scope="slotProps" slot="bookInfo">
<span v-if="slotProps.book.sale">限時優惠</span>
{{ slotProps.book.name }}
</template>
</book-list>
使用slot-scope時,當父組件使用該API,對應的插槽會替換模板中的slot進行展示
在組件中定義多個插槽出口可以兼容多個不同需求的兼容性,使得多個插槽內容傳入到各自的插槽出口中;當插槽中配置了
name
屬性時,此插槽就被稱為具名插槽(named slots),沒有提供name的插槽會隱式命名為「default」
v-slot
可以簡寫為#
,其值對應于插槽中的name
對應的值;
當在一個組件中同時存在默認插槽和具名插槽時,所有位于頂級的非template
節點都被隱式的視為默認插槽的內容,因此可以省略默認插槽的template
節點標簽;
<Com>
<!-- 隱式的默認插槽 -->
<!-- <p>A paragraph for the main content.</p>
<p>And another one.</p> -->
<template #default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
</Com>
普通的插槽,是無法獲取其他作用域下的數據的,即
父組件模板中的表達式只能訪問父組件的作用域;子組件模板中的表達式只能訪問子組件的作用域
但在某些情況下,插槽中的內容想要同時使用父組件和子組件內的數據,可以通過像組件傳遞數據props
那樣,讓子組件在渲染時將一部分數據提供給插槽,這樣在組件外部(父組件)中就可以使用子組件中的數據了-通過slot
的方式
子組件傳入插槽的 props 作為了 v-slot
指令的值,可以在插槽內的表達式中訪問,其中name是Vue特意保留的attribute,不會作為props進行傳遞
數據傳遞
//子組件
<template>
<slot :shopInfo="shopInfo" :userInfo="userInfo"></slot>
</template>
數據接收
//父組件 - 使用方
<MyCom v-slot="{shopInfo,userInfo}">
{{ shopInfo }} {{ userInfo }}
</MyCom>
<MyCom>
<template v-slot:header="shopInfo">
{{ shopInfo }}
</template>
<template #default="introduction">
{{ introduction }}
</template>
<template #footer="userInfo">
{{ userInfo }}
</template>
</MyCom>
具名插槽接收
默認插槽接收
使用slot-scope時,用最后一個slot-scope替換模板中的slot
<cpm>
<!-- 不顯示 -->
<div>555</div>
<!-- 不顯示 -->
<div slot-scope="scope">
<div>{{scope.name}}</div>
</div>
<!-- 顯示 -->
<div slot-scope="scope">
<div>{{scope}}</div>
<div>{{scope.name}}</div>
<div>{{scope.age}}</div>
</div>
</cpm>
使用作用域插槽時,可以實現既可以復用子組件slot,又可以使得slot的內容不一致,它允許使用者傳遞一個模板而不是已經渲染好的元素給插槽,所謂作用域是指模板雖然在父級作用域中渲染的,但是卻可以拿到子組件的數據
常規的v-bind需要攜帶參數key值進行傳遞,例如v-bind:info = '123'
;但是有時候會省略這個key值,直接進行傳遞數據,如v-bind = 'item'
,這種用法會將整個對象的所有屬性都綁定到當前元素上,適用于需要綁定的屬性過多的場景
// data: {
// shapes: [
// { name: 'Square', sides: 4 },
// { name: 'Hexagon', sides: 6 },
// { name: 'Triangle', sides: 3 }
// ],
// colors: [
// { name: 'Yellow', hex: '#F4D03F', },
// { name: 'Green', hex: '#229954' },
// { name: 'Purple', hex: '#9B59B6' }
// ]
// }
<my-list title="Shapes" :items="shapes">
<template scope="shape">
<div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div>
</template>
</my-list>
<my-list title="Colors" :items="colors">
<template scope="color">
<div>
<div class="swatch" :style="{ background: color.hex }"></div>
{{ color.name }}
</div>
</template>
</my-list>
<div id="my-list">
<div class="title">{{ title }}</div>
<div class="list">
<div v-for="scope in items">
<slot v-bind="scope"></slot>
</div>
</div>
</div>
Vue.component('my-list', {
template: '#my-list',
props: [ 'title', 'items' ]
});
遞歸組件就是指組件在模板中調用自己,由于是組件自身調用,就不能像常規組件定義一樣,可以省略組件的name配置,組件的遞歸需要依賴于自身的name配置(name還用于遍歷組件的name選項來查找組件的實例);
滿足條件
需要給組件設置一個name屬性
需要有一個明確的結束條件
<template>
<div>
<my-component :count="count + 1" v-if="count
<= 5"></my-component>
</div>
</template>
<script>
export default {
name:'my-component',
props: {
count: {
type: Number,
default: 1
}
}
}
</script>
有時候我們需要根據一些條件,動態的切換/選擇某個組件,在函數式組件中,沒有上下文的概念,常用于程序化的在多個組件中選擇一個,可以間接的解決動態切換組件的需求,缺點是基于js對象進行開發,不方便開發;
Vue官方提供了一個內置組件<component>
和is的屬性,用來解決上述的問題
<component :is="component"></component>
//component 就是js import進的組件實例,其值可以是標簽名、組件名、直接綁定一個對象等
為了使得組件具有緩存作用,可以使用的內置組件,這樣只要不離開當前頁面,切換到其他組件后deforeDestory不會執行,因此組件具有了緩存功能
常規的組件components是直接通過引用定義好的組件進行展示的,也可以直接在當前組件內定義,然后通過配置components進行渲染
<div id="app">
<cpn v-show="isShow"></cpn>
</div>
<template id="com">
<div>
<h3>Lbxin</h3>
<p>class - 11</p>
</div>
</template>
<script>
var app = new Vue({
el: '#app',
data: {
isShow: true
},
components: {
cpn: {
template: '#com',
data() {
isShow: false
}
}
}
})
</script>
<slot>
簡介HTML的slot元素,是Web Components技術套件的一部分,是Web組件內的一個占位符,該占位符可以在后期使用自己的標記語言進行填充,這樣可以創建單獨的DOM樹,并將其與其他的組件組合在一起 -- MDN
常見的填充Web組件的shadow DOM的模板有template和slot
模板 - Templates
<template id="my-paragraph">
<p>My paragraph</p>
</template>
let template = document.getElementById('my-paragraph');
let templateContent = template.content;
document.body.appendChild(templateContent);
customElements.define('my-paragraph',
class extends HTMLElement {
constructor() {
super();
let template = document.getElementById('my-paragraph');
let templateContent = template.content;
const shadowRoot = this.attachShadow({mode: 'open'})
.appendChild(templateContent.cloneNode(true));
}
})
// 自定義標簽使用
<my-paragraph></my-paragraph>
后續的樣式邏輯也需要加在template中,方便通過后續的相關邏輯(如template.content
獲取到然后打入到指定的容器中)
可以配合Web Component一起使用,實現純js自定義的組件
需要在網頁上重復的使用相同的標記結構時,為了避免CV的操作可以通過模板的方式進行實現
需要注意的是模板 - Template 和其內部的內容是不會在DOM中呈現的,可以通過js進行訪問并添加到DOM中,從而在界面上進行展示
Web Component簡介
類型一:Autonomous custom elements
是獨立的元素,它不繼承其他內建的 HTML 元素,可以直接通過標簽的方式進行HTML使用<popup-info>
,也可以通過js的方式進行使用document.createElement("popup-info")
類型二:Customized built-in elements
繼承自基本的 HTML 元素。在創建時,你必須指定所需擴展的元素,使用時,需要先寫出基本的元素標簽,并通過 is
屬性指定 custom element 的名稱;<p is="word-count">
或document.createElement("p", { is: "word-count" })
參數一:表明創建元素的名稱,其注冊的名稱不能簡單的單詞,需要由短劃線進行拼接
參數二:用于定義元素行為的類
參數三:一個包含extends屬性配置的配置對象,可選,指定了所創建的自定義元素是繼承于哪個內置的元素,可以繼承任何內置的元素;
customElements.define(
'word-count',
WordCount,
{ extends: 'p' }
);
可以使用ES2015的類實現
class WordCount extends HTMLParagraphElement {
constructor() {
// 必須首先調用 super 方法
super();
// 元素的功能代碼寫在這里
...
}
}
Web Component的一個很重要的屬性就是封裝 - 可以將標記結構、樣式和行為影藏起來,并于界面上的其他代碼隔離開來,保證代碼的獨立性
Web Component標準非常重要的一個特性是,使得開發者可以將HTML頁面的功能封住成custom elements(自定義標簽)
customElements 接口用來實現一個對象,允許開發者注冊一個custom elements的信息,返回已注冊的自定義標簽的信息;
customElements.define方法用來注冊一個custom element,接收三個參數
自定義標簽的類型
參考文獻 - MDN
shadow DOM簡介
shadow DOM主要是將一個隱藏的、獨立的DOM樹附加到常規的DOM樹上,是以shadow DOM節點為起始根節點,在這個根節點的下方,可以是任意的元素,和普通的DOM元素一致
Shadow host:一個常規 DOM 節點,Shadow DOM 會被附加到這個節點上。
Shadow tree:Shadow DOM 內部的 DOM 樹。
Shadow boundary:Shadow DOM 結束的地方,也是常規 DOM 開始的地方。
Shadow root: Shadow tree 的根節點。
圖解Shandow DOM
如常見的video標簽,其內部的一些控制器和按鈕等都是通過Shandow DOM進行維護的,開發者可以通過這個API進行自己獨立的邏輯控制
基本用法
let shadow1 = elementRef.attachShadow({mode: 'open'});
let shadow2 = elementRef.attachShadow({mode: 'closed'});
let myShadowDom = shadow1.shadowRoot; // 具體內容
let myShadowDom = shadow2.shadowRoot; //null
let shadow = this.attachShadow({mode: 'open'});
// 將一個shadow DOM添加到一個元素上之后就可以使用DOM API進行操作訪問了
當需要將一個shadow DOM添加到自定義的標簽上時,可以在自定義的構造函數中添加如下邏輯;
Element.attachShadow()方法可以將一個shadow DOM添加到任何一個元素上,接收一個配置對象參數,該對象有一個mode
的屬性,值可以是open - 可以通過外部js獲取 Shadow DOM和closed - 外部不可以通過js進行獲取 Shadow DOM
以上就是“Vue中的插槽、內容分發、具名插槽應用實例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。