2025年Vue.js 你需要知道的 scopedSlots

Vue.js 你需要知道的 scopedSlots面试官 Vue 如何在 Jsx 中使用 scopedSlots 自己先想一分钟 早先我在 Vue js 你不知道的一些小技巧 一文中简单介绍过 scopedSlots 的使用场景 但不是很详细 群里也有好多同学问关于 scopedSlots 如何使用 当然自己也有点小生疏

大家好,我是讯享网,很高兴认识大家。

面试官:Vue如何在 Jsx 中使用 scopedSlots ?

自己先想一分钟。

早先我在 Vue.js 你不知道的一些小技巧 一文中简单介绍过 scopedSlots 的使用场景,但不是很详细。群里也有好多同学问关于 scopedSlots 如何使用,当然自己也有点小生疏。今天借此机会重新梳理下,以便日后学习之用。文笔有限,有不对或阐述有误的地方希望留言斧正!

谁可以看?

本文针对有下面情况的同学:

  • 经常使用 Render 函数 和 Jsx 语法开发组件的同学
  • 基础薄弱想进一步提升的同学

你会学到什么?

  • ScopedSlots 的使用

和 slot-scope 的区别?

下面的区别仅仅代表个人理解:

  • 作用相同:都是作用域插槽
  • 场景不同:slot-scope 是模板语法,scopedSlots 则是编程式语法
  • 使用不同:在 <template> 中使用 slot-scope,在 render() 函数中使用 scopedSlots

Tips: 欢迎留言补充~

在渲染函数中如何使用?

假设我们有一个叫 <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)中重构上面的代码:

讯享网<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> 复制代码

上面代码输出的结果是:

以上只是模板语法的写法,接下来我们在渲染函数(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 自己敲一遍体会后自然明白。

在 Jsx 中如何使用?

我们知道,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 导入进来可以直接使用
  • render 函数省略了 h 参数。因为 babel-plugin-transform-vue-jsx@3.4.0+ 帮你自动注入了
  • 使用拓展运算符的解构赋值{...{xxx}} 语法。低版本的 Babel 需要 babel-plugin-transform-object-rest-spread 做兼容性处理

以上就是我要讲的 scopedSlots 在 Jsx 中的用法了,你可以狠狠的戳这里查看沙箱中的示例。同样的大家不妨跟着 demo 自己敲一遍体会后自然就明白了。

参考

  • babel-plugin-transform-vue-jsx
  • Vue#JSX
  • Vue#Slot

结尾!

啰嗦了这么多,希望看到的同学或多或少有点收获吧。不对的地方还请留言指正,不胜感激。俗话说,三人行则必有我师! 希望更多热衷于 Vue 的小伙伴能聚在一起交流技术!下面是我维护的一个Q群,欢迎扫码进群哦,让我们一起交流学习吧。也可以加我个人微信:G ,备注 掘金 即可。

小讯
上一篇 2025-03-07 22:34
下一篇 2025-03-17 07:39

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/20973.html