吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 660|回复: 0
收起左侧

[学习记录] Vue作用域插槽

[复制链接]
gdoudeng 发表于 2022-3-24 09:54

说在前面

重点理解掌握作用域插槽,默认插槽和具名插槽简单略过。

默认插槽

  1. 子组件
<a
        v-bind:href="url"
        class="nav-link"
>
    <slot>后备内容,当slot为空当时候默认使用这里的内容</slot>
</a>
  1. 父组件

<navigation-link url="/profile">
    Your Profile
</navigation-link>

具名插槽

  1. 子组件

<div class="container">
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</div>

一个不带 name<slot> 出口会带有隐含的名字“default”。

任何没有被包裹在带有 v-slot<template> 中的内容都会被视为默认插槽的内容。

  1. 父组件

<base-layout>
    <template v-slot:header>
        <h1>Here might be a page title</h1>
    </template>

    <template v-slot:default>
        <p>A paragraph for the main content.</p>
        <p>And another one.</p>
    </template>

    <template v-slot:footer>
        <p>Here's some contact info</p>
    </template>
</base-layout>

渲染结果


<div class="container">
    <header>
        <h1>Here might be a page title</h1>
    </header>
    <main>
        <p>A paragraph for the main content.</p>
        <p>And another one.</p>
    </main>
    <footer>
        <p>Here's some contact info</p>
    </footer>
</div>

作用域插槽 (重难点)

老实说,这个一般主要是用在UI框架上,还有你的子组件千变万化,我写了两年业务代码,没一次用上,但是看到别人的UI框架用到了,你也要知道咋回事。

  1. 子组件

<template>
    <ul>
        <li v-for="user in users">
            <slot :user="user">
                {{ user.id }}
            </slot>
            <slot name="first" :user="user">
                {{ user.firstName }}
            </slot>
            <slot name="last" :user="user">
                {{ user.lastName }}
            </slot>
        </li>
    </ul>
</template>

<script>
    export default {
        name: "UserList",
        props: ['users']
    }
</script>
  1. 父组件

<template>
    <div class="hello">
        <user-list :users="users">
        </user-list>
    </div>
</template>

<script>
    import UserList from "@/components/UserList";

    export default {
        name: 'HelloWorld',
        components: { UserList },
        data() {
            return {
                users: [
                    { id: 1, firstName: 'a1', lastName: 'a2' },
                    { id: 2, firstName: 'b1', lastName: 'b2' },
                    { id: 3, firstName: 'c1', lastName: 'c2' },
                ]
            }
        },
    }
</script>

<style scoped>
    ul {
        list-style-type: none;
        padding: 0;
    }

    li {
        display: inline-block;
        margin: 0 10px;
    }
</style>

我们先不在user-list里写任何内容,那么子组件会按照slot的后备内容进行渲染,渲染如下

可以清楚看到子组件就按id ,firstName,lastName来排开了

下面我来对user-list里自定义渲染内容

// 省略不变的代码
<user-list :users="users">
    <template v-slot="slotProps">
        <label class="id-label">{{ slotProps.user.id }}</label>
    </template>
</user-list>

// 省略不变的代码
<style scoped>
    .id-label{
        color: pink;
    }
</style>

看结果

可以看到id变颜色了,这是因为我们对数据的自定义渲染生效了。

看上面的代码,我用了v-slot="slotProps" 这是对默认插槽起作用的,省略了default,同时来了个等号,取出了此时定义在子组件中对数据。

slotProps.user.id 为什么是 .user ? 因为子组件中这三行代码

<slot :user="user">
   {{ user.id }}
</slot>

在默认插槽中,有一个:user="user" 就是这个冒号后面的user决定的slotProps.user ,此时就已经拿到了子组件中的这个user数据了,你可以尽情的对这个数据进行任何的渲染。

最后来一个完整的例子。

父组件

<template>
  <div class="hello">
    <user-list :users="users">
      <template v-slot="slotProps">
        <label class="id-label">{{ slotProps.user.id }}</label>
      </template>

      <template v-slot:first="slotProps">
        <div class="first-label">{{ slotProps.user.firstName }}</div>
      </template>

      <template v-slot:last="slotProps">
        <button>{{ slotProps.user.lastName }}</button>
      </template>
    </user-list>
  </div>
</template>

<script>
import UserList from "@/components/UserList";

export default {
  name: 'HelloWorld',
  components: { UserList },
  data() {
    return {
      users: [
        { id: 1, firstName: 'a1', lastName: 'a2' },
        { id: 2, firstName: 'b1', lastName: 'b2' },
        { id: 3, firstName: 'c1', lastName: 'c2' },
      ]
    }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

.id-label {
  color: pink;
}

.first-label {
  height: 20px;
  width: 20px;
  background: cornflowerblue;
  display: inline-block;
  margin: 0 20px;
}
</style>

最后把源码放上:vue-slot-demo

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 14:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表