vue2 vs vue3 插槽

Vue2与Vue3插槽对比解析
本文探讨了Vue2和Vue3中插槽的使用,重点在于作用域插槽和具名插槽。在Vue2中,插槽用于在子组件中展示父组件的内容,分为匿名和具名插槽。Vue3中,引入了v-slot指令,使得插槽的使用更加直观,并且不再支持slot-scope。示例展示了如何在不同版本的Vue中使用插槽,以传递和展示数据。


前言:插槽的使用其实是很简单,你只需要明白两点:

1.插槽是使用在子组件中的。

2.插槽是为了将父组件中的子组件模板数据正常显示

vue2.0的插槽
话不多说直接上案例:

<div id="app">
    <div class="father">
        <h3>这里是父组件</h3>
        <child>
           <span>我是插槽插入的内容</span>
        </child>
    </div>
</div>
<template id="child">
    <div class="child">
        <h3>这里是子组件</h3>
        <slot></slot>
    </div>
</template>
<script>
    var vm = new Vue({
        el: '#app',
        data: {},
        components: {
            child: {
                template: '#child'
            }
        }
 
    });
 
</script>


上面的代码所展示的效果就是你会发现在 <h3>这里是子组件</h3> 会多一行 <span>我是插槽插入的内容</span>
如果你在子组件里面不写 <slot></slot> 的话你会发现你无论在父组件里面写多少标签都不会被渲染到子标签中。

<font color=red>这就是传说中的插槽了,怎么样是不是很简单?</font>

上面的案例是匿名插槽,下面我们来看一下 “具名插槽”

<div id="app">
    <div class="father">
        <h3>这里是父组件</h3>
        <child>
            <span slot="demo1">菜单1</span>
            <span>菜单2</span>
            <span slot="demo3">菜单3</span>
        </child>
    </div>
</div>
<template id="child">
    <div class="child">
        <h3>这里是子组件</h3>
        <slot></slot>
        <slot name="demo3"><slot>
    </div>
</template>
<script>
    var vm = new Vue({
        el: '#app',
        data: {},
        components: {
            child: {
                template: '#child'
            }
        }
    });
</script>


具名插槽其实就是在父组件中添加一个 slot='自定义名字' 的属性,
然后在子组件中的<slot><slot> 里面添加 <name='自定义名字' 即可
如果父组件中有一部分没有添加 slot 属性,则此处就是默认的插槽,在子组件中的<slot></slot> 直接就是使用的父组件的默认插槽部分

作用域插槽

父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
不过,我们可以在父组件中使用slot-scope 特性从子组件获取数据
前提是需要在子组件中使用:data=data 先传递data 的数据

<div id="app">
    <div class="father">
        <h3>这里是父组件</h3>
        <child>
            <div slot-scope="user">
                {{user.data}}
            </div>
        </child>
    </div>
</div>
<script>
    Vue.component('child', {
        template:'' +
            '<div class="child">\n' +
            '    <h3>这里是子组件</h3>\n' +
            '    <slot  :data="data"></slot>\n' +
            '  </div>',
        data: function () {
            return {
                data: ['zhangsan', 'lisi', 'wanwu', 'zhaoliu', 'tianqi', 'xiaoba']
            }
        }
    });
    var vm = new Vue({
        el: '#app',
    });
</script>


页面显示的结果如下:

这里是父组件

这里是子组件

['zhangsan', 'lisi', 'wanwu', 'zhaoliu', 'tianqi', 'xiaoba']

vue3.0中插槽的使用
匿名插槽用法不变

下面我们来看一下具名插槽的写法

// 子组件
<div class="hello">
    我是一个封装的组件
     <slot name="num"></slot>
  </div>
  
  
// 父组件
<HelloWorld v-model="masg" v-slot:num>
    <div>我是插槽插入的</div>
</HelloWorld>
 
// 父组件的另外一个写法
<HelloWorld v-model="masg">
    <template v-slot:num>
         <div>我是插槽插入的</div>
    </template>
</HelloWorld>


Vue3(其实从2.6开始)中引入了一个新的指令 v-slot,用来表示具名插槽和默认插槽。
在 v2.5 之后屏蔽了 slot-scope,
v-slot引入使其插槽更接近指令化。

下面我们来看一下作用域插槽的用法

// 子组件
<div class="hello">
    我是一个封装的组件
     <slot :num="num"></slot>
</div>
 
<script>
import { ref } from 'vue';
export default {
  name: 'HelloWorld',
  props: {
    // msg: String,
    modelValue: String
  },
 setup(prop,context){
   const num = ref(10);
   return { num }
 }
}
</script>
 
// 父组件
<HelloWorld>
  <template v-slot="{num}">
     <div>{{num}}</div>
  </template>
</HelloWorld>
 
// 也可以改成下面的写法
<HelloWorld v-slot="{num}">
   <div>{{num}}</div>
</HelloWorld>
 
 
和 v-bind和v-on相似,缩写只有在存在参数时才生效,这就意味着v-slot没有参数时不能使用#=,对于默认插槽,可以使用#default来代替v-slot
 
 
// 上面我们写过具名插槽可以这么写
 
<HelloWorld v-model="masg">
    <template #num>
         <div>我是插槽插入的</div>
    </template>
</HelloWorld>
 
// 或者如上面的作用域插槽也可以改成下面的写法
 
<HelloWorld>
  <template #default="{num}">
     <div>{{num}}</div>
  </template>

<think> 我们被要求回答关于Vue2Vue3插槽的使用方法。根据提供的引用,我们可以总结如下: 在Vue中,插槽(Slot)是一种强大的功能,允许我们在组件中预留位置,以便在使用组件时插入自定义内容。插槽分为默认插槽(匿名插槽具名插槽,以及作用域插槽(可以传递数据)。 ### Vue2中的插槽使用 1. **默认插槽**: 在子组件中,使用`<slot>`标签作为占位符。在父组件中,将内容放在子组件标签内部,这些内容就会填充到默认插槽中。 示例(子组件): ```html <div> <h2>子组件标题</h2> <slot></slot> <!-- 默认插槽 --> </div> ``` 父组件使用: ```html <child-component> 这里是插入到默认插槽的内容 </child-component> ``` 2. **具名插槽**: 当有多个插槽时,可以使用具名插槽。在子组件中,使用`<slot name="插槽名">`。在父组件中,使用`<template v-slot:插槽名>`或`#插槽名`(Vue2.6.0+)来指定内容插入到哪个插槽。 示例(子组件): ```html <div> <slot name="header"></slot> <slot></slot> <!-- 默认插槽 --> <slot name="footer"></slot> </div> ``` 父组件使用: ```html <child-component> <template v-slot:header> 这里是头部内容 </template> 这里是默认插槽的内容 <template v-slot:footer> 这里是底部内容 </template> </child-component> ``` 3. **作用域插槽**: 作用域插槽允许子组件将数据传递给父组件中的插槽内容。在子组件的`<slot>`标签上绑定属性(称为插槽prop)。在父组件中,使用`v-slot:插槽名="变量名"`来接收子组件传递的数据。 示例(子组件): ```html <div> <slot name="content" :item="item"></slot> </div> ``` 父组件使用: ```html <child-component> <template v-slot:content="slotProps"> 子组件传递的数据: {{ slotProps.item }} </template> </child-component> ``` ### Vue3中的插槽使用 Vue3插槽的基本概念与Vue2一致,但有一些语法上的变化优化。 1. **默认插槽**: 使用方式与Vue2相同。 2. **具名插槽**: Vue3中,具名插槽的使用方式与Vue2基本相同,但有一个区别:在Vue3中,`v-slot`只能用于`<template>`标签(Vue2中也可以用在普通标签上),并且默认插槽可以使用`v-slot:default`或`#default`。 示例(父组件): ```html <child-component> <template v-slot:header> 头部内容 </template> <!-- 默认插槽内容 --> <template v-slot:default> 默认插槽内容 </template> <!-- 或者省略default,直接写内容(注意:Vue3中要求默认插槽内容也必须包裹在template中,除非使用独占默认插槽的缩写) --> <template #footer> 底部内容 </template> </child-component> ``` 注意:在Vue3中,一个不带`name`的`<slot>`会带有隐含的名字“default”。 3. **作用域插槽**: 用法与Vue2类似,但Vue3中作用域插槽的使用更加简洁,并且支持解构。 示例(子组件): ```html <div> <slot name="content" :item="item"></slot> </div> ``` 父组件使用: ```html <child-component> <template #content="slotProps"> 子组件传递的数据: {{ slotProps.item }} </template> </child-component> ``` 或者使用解构: ```html <child-component> <template #content="{ item }"> 子组件传递的数据: {{ item }} </template> </child-component> ``` 4. **独占默认插槽的缩写**: 当只有一个默认插槽时,可以直接在组件标签上使用`v-slot`来接收作用域插槽的数据。 示例(父组件): ```html <child-component v-slot="slotProps"> 默认插槽内容,接收子组件数据: {{ slotProps.item }} </child-component> ``` 或者解构: ```html <child-component v-slot="{ item }"> 默认插槽内容,接收子组件数据: {{ item }} </child-component> ``` ### 注意事项 - 在Vue2中,作用域插槽语法2.6.0版本之后统一使用`v-slot`指令,取代了之前的`slot``slot-scope`。 - Vue3中不再支持`slot``slot-scope`属性,必须使用`v-slot`指令(或其缩写`#`)。 - 在Vue3中,当使用作用域插槽时,如果同时有默认插槽具名插槽,则必须使用`<template>`分别指定,并且默认插槽必须使用`v-slot:default`或`#default`。 ### 示例代码对比 引用[5]中提到了一个在Vue3中使用作用域插槽的示例(在el-table-column中使用): ```html <el-table-column prop="role" header-align="center" align="center" label="用户角色"> <template #default="scope"> <el-tag type="success" v-if="scope.row.role === 3">管理员</el-tag> <el-tag type="success" v-else-if="scope.row.role === 2">领导</el-tag> <el-tag type="success" v-else-if="scope.row.role === 1">老师</el-tag> <el-tag type="danger" v-else>学生</el-tag> </template> </el-table-column> ``` 这里使用了`#default="scope"`来接收作用域插槽传递的数据。 综上所述,Vue2Vue3插槽的核心概念一致,主要区别在于语法细节,特别是作用域插槽的写法。在Vue3中,更推荐使用`v-slot``#`缩写,并且支持解构等特性,使得代码更加简洁。 如果您需要更详细的代码示例或进一步解释,请随时告知。 §§相关问题§§ 1. Vue2Vue3的作用域插槽在使用上有哪些具体区别? 2.Vue3中使用插槽时,如何避免常见错误? 3. Vue3插槽机制做了哪些优化? </think> ### Vue2Vue3 插槽使用方法详解 #### **一、默认插槽(匿名插槽)** **Vue2 使用方式**: ```html <!-- 子组件 Child.vue --> <template> <div> <slot></slot> <!-- 默认插槽占位符 --> </div> </template> <!-- 父组件 --> <Child> 默认内容直接写在这里 <!-- 自动注入默认插槽 --> </Child> ``` **Vue3 使用方式**: ```html <!-- 子组件 --> <template> <div> <slot></slot> <!-- 默认插槽(隐含名称为 default) --> </div> </template> <!-- 父组件 --> <Child> <template #default> <!-- 显式使用 #default --> Vue3 默认内容 </template> </Child> ``` #### **二、具名插槽** **Vue2 使用方式**: ```html <!-- 子组件 --> <template> <div> <slot name="header"></slot> <slot name="footer"></slot> </div> </template> <!-- 父组件 --> <Child> <template v-slot:header> <!-- 或简写 #header --> 页头内容 </template> <template v-slot:footer> 页脚内容 </template> </Child> ``` **Vue3 使用方式**: ```html <!-- 父组件 --> <Child> <template #header> <!-- 简写语法 --> <h2>Vue3 页头</h2> </template> <template #footer> <p>Vue3 页脚</p> </template> </Child> ``` #### **三、作用域插槽(核心区别)** **Vue2 使用方式**: ```html <!-- 子组件 --> <template> <div> <slot :item="itemData"></slot> <!-- 数据传递 --> </div> </template> <!-- 父组件 --> <Child> <template v-slot:default="slotProps"> <!-- 接收数据 --> 子组件数据: {{ slotProps.item }} </template> </Child> ``` **Vue3 使用方式**: ```html <!-- 子组件 (不变) --> <template> <slot :item="itemData"></slot> </template> <!-- 父组件 --> <Child> <template #default="{ item }"> <!-- 解构语法 --> <el-tag :type="item.role === 3 ? &#39;success&#39; : &#39;danger&#39;"> <!-- 引用[5]案例 --> {{ item.name }} </el-tag> </template> </Child> ``` #### **四、关键差异总结** | 特性 | Vue2 | Vue3 | |--------------|-------------------------------|-------------------------------| | **作用域插槽** | `v-slot:default="scope"` | `#default="{ prop }"`(支持解构)| | **具名插槽** | `v-slot:header` | `#header`(简写更简洁) | | **默认插槽** | 内容直接写在组件标签内 | 需显式使用`#default` | | **动态插槽名**| 不支持 | 支持`#[dynamicSlotName]` | | **语法兼容** | `slot` `slot-scope` 已废弃 | 仅支持 `v-slot` / `#` 语法 | #### **五、使用建议** 1. **作用域插槽数据流**: 父组件模板中的插槽内容只能访问父组件数据(词法作用域规则)[^4],如需子组件数据需通过作用域插槽传递。 2. **Vue3 最佳实践**: ```html <!-- 独占默认插槽缩写 --> <Child v-slot="{ item }"> 直接使用 {{ item }} </Child> <!-- 动态插槽名 --> <template #[dynamicSlot]> 动态内容 </template> ``` 3. **常见问题规避**: - 当同时使用多个插槽时,Vue3 要求默认插槽必须显式声明`#default` - 作用域插槽接收数据时,Vue3 推荐使用解构语法简化代码 > 示例参考:在 Vue3 的 `el-table-column` 中正确使用作用域插槽[^5]: > ```html > <el-table-column label="角色"> > <template #default="scope"> <!-- 必须用 #default 接收 --> > <el-tag v-if="scope.row.role === 3">管理员</el-tag> > </template> > </el-table-column> > ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦若烟雨在人间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值