面試官:Vue如何在 Jsx 中使用 scopedSlots ?html
本身先想一分鐘。vue
早先我在 Vue.js 你不知道的一些小技巧 一文中簡單介紹過 scopedSlots
的使用場景,但不是很詳細。羣裏也有好多同窗問關於 scopedSlots
如何使用,固然本身也有點小生疏。今天藉此機會從新梳理下,以便往後學習之用。文筆有限,有不對或闡述有誤的地方但願留言斧正!node
本文針對有下面狀況的同窗:git
下面的區別僅僅表明我的理解:es6
slot-scope
是模板語法,scopedSlots
則是編程式語法<template>
中使用 slot-scope
,在 render()
函數中使用 scopedSlots
Tips: 歡迎留言補充~github
假設咱們有一個叫 <base-layout>
的組件,它的模板內容以下:面試
<div class="child-node">
<slot name="header" :text="headerText"></slot>
<slot :text="defaultText"></slot>
<slot name="footer" :text="footerText"></slot>
</div>
複製代碼
能夠看到,div#child-node
容器中有三個插槽,分別是 header
, default
, footer
。正常狀況下咱們會用一個塊級標籤分別把他們包裹,這裏爲了簡單起見我沒有這麼作。接下來咱們在渲染函數(render)中重構上面的代碼:npm
<script>
export default {
data() {
return {
headerText: "child header text",
defaultText: "child default text",
footerText: "child footer text"
};
},
render(h) {
return h("div", { class: "child-node" }, [
// 至關於 <slot name="header" :text="headerText"></slot>
this.$scopedSlots.header({ text: this.headerText }),
// 至關於 <slot :text="defaultText"></slot>
this.$scopedSlots.default(this.defaultText),
this.$scopedSlots.footer({ text: this.footerText })
]);
}
};
</script>
複製代碼
假設咱們有一個叫 <scoped-slots>
的父組件。按照模板語法的定義,咱們可使用 slot-scope 或者 v-slot 獲取插值內容,從而達到自定義內容的效果,這裏咱們使用 Vue@2.6.x 提供的最新語法 v-slot 的簡寫形式,來演示一下如何在父組件中使用:編程
<div class="parent-node">
parent content
<base-layout>
<template #header="{ text }">
<p style="color: red">{{ text }}</p>
</template>
<template #default="text">
<!-- 默認內容是個字符串直接輸出 -->
<p style="color: deeppink">{{ slotProp }}</p>
</template>
<template #footer="{ text }">
<p style="color: orange">{{ text }}</p>
</template>
</base-layout>
</div>
複製代碼
上面代碼輸出的結果是:json
以上只是模板語法的寫法,接下來咱們在渲染函數(render)中利用 scopedSlots 屬性重構上面的代碼:
<script>
import BaseLayout from "./base-layout.vue";
export default {
name: "ScopedSlots",
components: {
BaseLayout
},
render(h) {
return h("div", { class: "parent-node" }, [
this.$slots.default,
h("base-layout", {
scopedSlots: {
// 至關於下面代碼:
// <template #header="props">
// <p style="color:red">
// {{ props.text }}
// </p>
// <template>
header: props => {
return h("p", { style: { color: "red" } }, [props.text]);
},
default: props => {
return h("p", { style: { color: "deeppink" } }, [props]);
},
footer: props => {
return h("p", { style: { color: "orange" } }, [props.text]);
}
}
})
]);
}
};
</script>
複製代碼
一樣的,上面代碼的輸出結果是:
以上就是我要講的 scopedSlots
在 Render 函數中的用法了,你能夠狠狠的戳這裏查看沙箱中的示例。你們不妨跟着 demo 本身敲一遍體會後天然明白。
咱們知道,Vue中的大部分語法在 Jsx 中的寫法是不同的,具體看這裏,本文再也不贅述。但文檔中並無介紹 scopedSlots 的用法,今天咱們來看下如何使用。
使用以前咱們須要安裝解析 Jsx 語法相關的插件:
npm install\
babel-plugin-syntax-jsx\
babel-plugin-transform-vue-jsx\
babel-helper-vue-jsx-merge-props\
babel-preset-env\
--save-dev
複製代碼
接着配置 .babelrc
文件:
{
"presets": ["env"],
"plugins": ["transform-vue-jsx"]
}
複製代碼
最後咱們使用 Jsx 語法重構上面 render 函數中的代碼:
<script>
import BaseLayout from "./base-layout.vue";
export default {
name: "ScopedSlots",
render() {
return (
<div class="parent-node"> parent content <BaseLayout {...{ scopedSlots: { header: props => { return <p style={{ color: "red" }}>{props.text}</p>; }, default: props => { return <p style={{ color: "deeppink" }}>{props}</p>; }, footer: props => { return <p style={{ color: "orange" }}>{props.text}</p>; } } }} /> </div> ); } }; </script>
複製代碼
上面代碼的輸出結果是:
你會發現跟 render 函數相比起來仍是有些不一樣的:
BaseLayout
導入進來能夠直接使用h
參數。由於 babel-plugin-transform-vue-jsx@3.4.0+ 幫你自動注入了{...{xxx}}
語法。低版本的 Babel 須要 babel-plugin-transform-object-rest-spread 作兼容性處理以上就是我要講的 scopedSlots
在 Jsx 中的用法了,你能夠狠狠的戳這裏查看沙箱中的示例。一樣的你們不妨跟着 demo 本身敲一遍體會後天然就明白了。
囉嗦了這麼多,但願看到的同窗或多或少有點收穫吧。不對的地方還請留言指正,不勝感激。俗話說,三人行則必有我師! 但願更多熱衷於 Vue 的小夥伴能聚在一塊兒交流技術!下面是我維護的一個Q羣,歡迎掃碼進羣哦,讓咱們一塊兒交流學習吧。也能夠加我我的微信:G911214255 ,備註 掘金
便可。