久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

通過UI庫深入了解Vue的插槽的使用技巧(片尾有彩蛋)

 昵稱10087950 2022-07-20 發(fā)布于江蘇
作者 | 自然框架
出品 | 腳本之家(ID:jb51net)

Vue官網(wǎng)對(duì)于插槽的介紹比較簡略,,插槽本身也比較“燒腦”,,很容易看暈,我就一直沒看懂,,直到 使用了element-plus的組件的插槽,。其實(shí)我們可以換一個(gè)角度來理解插槽,就會(huì)豁然開朗了,。

技術(shù)棧

  • vite
  • vue3
  • element-plus

從父子組件的傳值開始

父子組件傳值可以通過 prosp + emit 來實(shí)現(xiàn),,雖然 props 可以傳遞各種類型,但是卻不能傳遞組件(包括HTML),,這樣靈活度就差了一些,。那么怎么辦呢?為了提高靈活性,,Vue 提供了插槽功能,。

插槽可以分為:插槽、具名插槽,、作用域插槽如果不明所以的話,,可以換一種名稱:匿名插槽、命名插槽、可傳參插槽,。

匿名插槽

如何理解插槽呢,?可以先看看div,div是一個(gè)容器,,里面可以放各種HTML標(biāo)簽,,同時(shí)也可以放各種組件。

那么我們可以把div內(nèi)部的標(biāo)簽,、組件視為插槽內(nèi)容,,同理,我們也可以把 select 內(nèi)部的 option 也視為插槽內(nèi)容,。

我們可以用匿名插槽的方式,,寫一個(gè)my-div的組件。

  • 子組件 ./comp/my-div.vue
<div style="margin: 10px;padding: 10px; border:1px solid orange;">
匿名插槽:
插槽前<br><br>
<slot>沒有設(shè)置插槽</slot>
<br><br>
插槽后
</div>

子組件設(shè)置一個(gè) slot 標(biāo)簽,,slot 可以理解為是一種“插值”,,表示父組件的插槽在這個(gè)位置被渲染,然后在其前后可以加入子組件自己的內(nèi)容,。

slot 里面是“備用內(nèi)容”,,如果父組件沒有設(shè)置插槽的話,“備用內(nèi)容”會(huì)被渲染,,否則會(huì)被忽略,。

  • 父組件

我們看一看在父組件里面的使用情況:

import myDiv from'./comp/my-div.vue'
  匿名插槽<br>
設(shè)置文本框作為插槽內(nèi)容:
<my-div>
<input type="text" placeholder="父組件的插槽">
</my-div>
<br>
沒有設(shè)置插槽內(nèi)容:
<br>
<my-div></my-div>
  • 看看效果
圖片
匿名插槽

這樣就實(shí)現(xiàn)了一個(gè)簡單的具有插槽功能的組件,當(dāng)然這個(gè)組件是為了插槽而插槽,,并沒有沒有實(shí)際意義,。

那么插槽在實(shí)際項(xiàng)目里可以有哪些作用呢?我們可以參考一下UI庫的組件,,他們有很多插槽的實(shí)際應(yīng)用,,比如 el-input、el-table等,。

具名插槽,。

“具名”是個(gè)啥意思?感覺用“命名插槽”更好理解一些,。

  • 如果一個(gè)組件只有一個(gè)插槽,,那么不用寫名稱,Vue會(huì)使用默認(rèn)名稱:default ,。
  • 如果一個(gè)組件有多個(gè)插槽的話,,那么就需要起名來區(qū)分不同的插槽。

el-input 提供了prefix,、suffix,、prepend,、append四個(gè)插槽,就是采用了命名插槽的方式,。

我們來看一下官網(wǎng)的例子:

<el-input v-model="input1" placeholder="Please input">
<template #prepend>Http://</template>
</el-input>
<el-input v-model="input2" placeholder="Please input">
<template #append>.com</template>
</el-input>
  • # 是 v-lot: 的簡寫形式,,類似于 “v-bind:” 簡寫為 “:”,“v-on:” 簡寫為 “@”
  • prepend 在文本框的前面放置一個(gè)插槽,,比如 http://
  • append 在文本框的后面方式一個(gè)插槽,,比如 .com

這樣可以方便輸入U(xiǎn)RL地址。其實(shí)如果 append 放置一個(gè) el-autocomplete 的話,,可以更靈活的設(shè)置域名后綴,。

手寫一個(gè)命名插槽

還是手寫一個(gè)命名插槽,看一下子組件的實(shí)現(xiàn)方式,。

  • 子組件  ./comp/my-div-name.vue
<div style="margin: 10px;padding: 10px; border:1px solid rgba(61, 67, 155, 0.692);">
<slot name="header">我來組成頭部</slot>
插槽中間內(nèi)容
<slot name="footer">我來組成結(jié)尾</slot>
</div>

實(shí)現(xiàn)具名插槽的方式很簡單,,用 name 屬性設(shè)置插槽的名稱即可。

  • 父組件的調(diào)用
import myDivName from'./comp/my-div-name.vue'
<my-div-name>
<template v-slot:header>
<h1>這是頭部</h1>
</template>
<template #footer>
<p>這是結(jié)尾</p>
</template>
</my-div-name>

父組件需要用 template 限定具名插槽內(nèi)容的范圍,,我們來看看效果:

圖片
具名插槽

作用域插槽

插槽是父組件的,,不是子組件的,父組件可以完全操作插槽里的組件,。但是子組件只能規(guī)定插槽的渲染位置,,其他的就不能操作了,這樣的話還是有些不夠靈活,,于是出現(xiàn)了作用域插槽。

作用域插槽的目的是解決父組件,、子組件,、插槽之間的數(shù)據(jù)通訊的問題。

還是看看UI庫組件 el-table 的插槽 ,。

父組件設(shè)置列表數(shù)據(jù),,傳遞給子組件,子組件渲染 table 表格,。為了更靈活,,組件提供了自定義列的功能,采用的就是作用域的插槽,。

看一下官網(wǎng)示例:

<el-table :data="tableData" style="width: 100%">
<el-table-column label="Date" width="180">
<template #default="scope">
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
</table>
  • scope 就是子組件傳遞出來的數(shù)據(jù)集合,,包含row、column,、$index等屬性,。
const tableData = reactive([
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
}
])

  • tableData:父組件定義數(shù)據(jù)列表,通過 data 屬性傳遞給子組件,。

這里的 scope 的數(shù)據(jù)流程是這樣的:父組件 =》子組件 =》插槽,。

為啥要繞一圈呢,?雖然父組件可以直接給插槽設(shè)置值,但是由于 tr 是循環(huán)出來的,,父組件無法獲知循環(huán)到哪一行了,,所以需要子組件告知循環(huán)行數(shù),這個(gè)信息就是通過作用域插槽來實(shí)現(xiàn)的,,我們可以做一個(gè)簡單的示例,。

手?jǐn)]一個(gè)簡單的作用域插槽

  • 子組件 ./comp/my-table.vue
  <div>
<table>
<tr>
<th>標(biāo)題一</th>
<th>標(biāo)題二</th>
<th>自定義</th>
</tr>
<tr v-for="(item, index) in data"
:key="index"
>
<td>{{item.t1}}</td>
<td>{{item.t2}}</td>
<td>
<slot name="td"
:row="item"
:$index="index"
></slot>
</td>
</tr>
</table>
</div>

第三列設(shè)置一個(gè)具名插槽,通過row,、$index 傳遞數(shù)據(jù),。

const props = defineProps({
data: Array
})

設(shè)置一個(gè)屬性,接收列表數(shù)據(jù),。

  • 父組件調(diào)用
import myTable from'./comp/my-table.vue'

const data = reactive([
{ t1: '11', t2: '12', t3: '13' },
{ t1: '21', t2: '22', t3: '23' },
{ t1: '31', t2: '32', t3: '33' }
])
<my-table :data="data">
<template #td="scope">
自定義列:{{scope}}
</template>
</my-table>

可以看到數(shù)據(jù)的傳遞,。

子組件的插槽,先起個(gè)名字,,就叫做“td”好了,,不要糾結(jié)名稱,俺有起名困難癥,。

然后用 row 屬性傳遞行的數(shù)據(jù),,用 $index 傳遞遍歷到第幾行的數(shù)據(jù)。

這樣一個(gè)簡單的作用域插槽就搞定了,。當(dāng)然只是一個(gè)示例,,還是沒有啥實(shí)際意義。

那么有實(shí)際意義的是什么樣子的呢,?還記得標(biāo)題嗎,?我可不是標(biāo)題黨,彩蛋馬上就來,。

片尾彩蛋

現(xiàn)在流行用 json 來渲染組件,,還是用 el-table 舉例,我們可以定義一個(gè) json,,來描述表格列的情況,,比如:

{
"itemMeta": [
{
"prop": "name",
"label": "姓名",
"width": 140,
"align": "center",
"header-align": "center"
},
{
"prop": "age",
"label": "年齡",
"width": 140,
"align": "center",
"header-align": "center"
},
{
"prop": "mobile",
"label": "電話",
"width": 140,
"align": "center",
"header-align": "center"
},
{
"prop": "url",
"label": "URL",
"width": 140,
"align": "center",
"header-align": "center"
}
]
}

然后遍歷 el-table-colmun 設(shè)置屬性,這樣就可以實(shí)現(xiàn)動(dòng)態(tài)渲染 table 的功能,。這樣雖然很方便,,但是自定義列呢?如果不支持插槽的話,,那么靈活性就差了一些,。

魚和熊掌能不能兼得呢?既然都寫到這里了,,那么肯定可以兼得,。

做一個(gè)默認(rèn)規(guī)則

自定義列的插槽名稱格式:td_{字段名稱},。也就是說 td_開頭的視為自定義列的插槽,加上前綴可以避免和 el-table 自帶的具名插槽沖突,。

然后封裝一下 el-table

建立一個(gè)組件 ./comp/my-table-json.vue

import { useSlots } from'vue'

const props = defineProps({
colInfo: Object,
data: Array
})

// 獲取插槽信息
const slots = useSlots()
// 獲取列的描述信息
const colInfo = props.colInfo

// 檢查插槽,,設(shè)置名稱
colInfo.forEach(col => {
const _slotName = 'td_' + col.prop
if (typeof slots[_slotName] === 'function') {
// 有插槽
col.slotName = _slotName
} else {
// 沒有插槽
col.slotName = ''
}
})

定義屬性,接收數(shù)據(jù)和列的描述,。然后獲取插槽的信息,,設(shè)置列是否需要加載插槽。

<el-table :data="data" style="width: 100%">
<template
v-for="(item, index) in colInfo"
:key="index"
>

<!--不帶插槽的列-->
<el-table-column
v-if="item.slotName == ''"
v-bind="item"
>

</el-table-column>
<!--帶插槽的列-->
<el-table-column
v-else
v-bind="item"
>

<template #default="scope">
<slot :name="item.slotName" v-bind="scope"></slot>
</template>
</el-table-column>
</template>
</el-table>

遍歷列的描述信息,,判斷是否需要加載插槽,,如果需要插槽的話,設(shè)置插槽并且傳遞 scope 數(shù)據(jù),。

父組件的調(diào)用

父組件就簡單多了,。

  UI庫的 table 的二次封裝
不用自定義列:
<my-table-json :data="data" :colInfo="colInfo">
</my-table-json>

使用自定義列:
<my-table-json :data="data" :colInfo="colInfo">
<template #td_url="{ row }">
<a :href="row.url" target="blank">{{row.name}}</a>
</template>
<template #td_mobile="scope">
手機(jī):{{scope.row.mobile}}
</template>
</my-table-json>

不需要自定義列的話,代碼可以更簡潔,;需要自定義列的話,,也支持用插槽的方式實(shí)現(xiàn)。

import myTableJson from'./comp/my-table-json.vue'
import meta from'./grid.json'

const colInfo = reactive(meta.itemMeta)

const data = reactive([
{
name: '阿蒙',
age: 18,
mobile: '1399999991',
url: 'https://naturefw./nf-rollup-ui-controller'
},
{
name: '小李',
age: 18,
mobile: '1399999992',
url: 'https://naturefw./nf-rollup-ui-controller/meta-base'
},
{
name: '路飛',
age: 18,
mobile: '1399999993',
url: 'https://naturefw./nf-rollup-ui-controller/meta-base'
}
])

這樣就不用手?jǐn)] el-table-column 了,,交給子組件即可,,同時(shí)還可以滿足自定義列的需求。

是不是即簡潔又靈活,。這個(gè)彩蛋還滿意吧,。

看看效果:

圖片
json渲染 + 作用域插槽

在線演示

https://naturefw./nf-rollup-ui-controller/test-slot

源碼

https:///naturefw/nf-rollup-ui-controller/tree/master/src/views/test/slot

本文作者:自然框架

個(gè)人網(wǎng)址:jyk.cnblogs.com


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多