vue的v-solt总结,老是忘,非常详细,每个都有全部代码

本文深入探讨Vue.js中的插槽概念,包括具名插槽、作用域插槽、默认插槽的使用方法及其实例,讲解如何在父组件中向子组件传递内容和数据,并展示插槽内容解构赋值及简写语法。

参考

官网文档

具名插槽

vue 2.6+废弃
在Test.vue中使用BaseLayout 组件,在向具名插槽提供内容的时候,我们可以在一个父组件的 元素上使用 slot 特性

<template>
  <div class="test">
    <base-layout>
      <template slot="header">
        <h1>header</h1>
      </template>

      <p>main1</p>
      <p>main2</p>

      <template slot="footer">
        <h1>footer</h1>
      </template>
    </base-layout>
  </div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
  name: "",
  components: { BaseLayout },
  data() {
    return {};
  },
  methods: {},
  mounted() {}
};
</script>
<style lang="less" scoped></style>

或者直接用在一个普通的元素上:Test.vue内容

<template>
  <div class="test">
    <base-layout>
      <h1 slot="header">header</h1>
      <p>main1</p>
      <p>main2</p>

      <template slot="footer">
        <h1>footer</h1>
      </template>
    </base-layout>
  </div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
  name: "",
  components: { BaseLayout },
  data() {
    return {};
  },
  methods: {},
  mounted() {}
};
</script>
<style lang="less" scoped></style>

BaseLayout .vue组件

<template>
  <!-- 组件 -->
  <div class="container">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>
<script>
export default {
  name: "",
  components: {},
  data() {
    return {};
  },
  methods: {},
  mounted() {}
};
</script>
<style lang="less" scoped></style>

在这里插入图片描述
访问Test.vue页面内容如下
在这里插入图片描述

我们可以使用 v-slot 指令改写上面的Test.vue

<template>
  <div class="test">
    <base-layout>
      <!-- <h1 v-slot:header>header</h1> -->
      <p>main1</p>
      <p>main2</p>

      <template v-slot:footer>
        <h1>footer</h1>
      </template>
    </base-layout>
  </div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
  name: "",
  components: { BaseLayout },
  data() {
    return {};
  },
  methods: {},
  mounted() {}
};
</script>
<style lang="less" scoped></style>

注意:<h1 v-slot:header>header</h1>这种写法是错误的,v-solt只能用在template上面

插槽的名字现在通过 v-slot:slotName 这种形式来使用

Tips: 没有名字的 <slot> 隐含有一个 "default" 名称
例如,上面的默认插槽,如果你想显示调用的话,可以这样:

<template>
  <div class="test">
    <base-layout>
      <template v-slot:header>
        <h1>header</h1>
      </template>
      <template v-slot:default>
        <p>main1</p>
        <p>main2</p>
      </template>

      <template v-slot:footer>
        <h1>footer</h1>
      </template>
    </base-layout>
  </div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
  name: "",
  components: { BaseLayout },
  data() {
    return {};
  },
  methods: {},
  mounted() {}
};
</script>
<style lang="less" scoped></style>

总结:父组件中具名插槽slot="header"内容会进入子组件对应的名字中<slot name="header"></slot>

作用域插槽

父组件中访问子组件的插槽绑定的值

父组件 Test.vue中

<template>
  <div id="app">
    <!-- 子组件 -->
    <user v-slot:default="slotProps">
      <!-- 插槽内容 -->
      {{ slotProps.user.firstName }}
    </user>
  </div>
</template>

<script>
import User from "./User.vue";

export default {
  name: "app",
  components: {
    User
  }
};
</script>

<style></style>

子组件User.vue中

<template>
  <div>
    <!-- 作用域插槽:插槽prop -->
    <slot :user="user">
      <!-- 后备内容 -->
      {{ user.lastName }}
    </slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      user: {
        firstName: "张",
        lastName: "三"
      }
    };
  }
};
</script>
<style></style>

结果:
在这里插入图片描述

在这个栗子中,我们选择 slotProp作为我们的slot props名字,但你可以使用你喜欢的任何名字。

  • 父组件 Test.vue还可以这么写,将v-slot:default="slotProps"改为v-slot="slotProps"上面
<template>
  <div id="app">
    <!-- 子组件 -->
    <user v-slot="slotProps">
      <!-- 插槽内容 -->
      {{ slotProps.user.firstName }}
    </user>
  </div>
</template>

<script>
import User from "./User.vue";

export default {
  name: "app",
  components: {
    User
  }
};
</script>

<style></style>
  • 父组件 Test.vue还可以这么写,将v-solt写在template上面
<template>
  <div id="app">
    <!-- 子组件 -->
    <user>
      <template v-slot:default="slotProps">
        <!-- 插槽内容 -->
        {{ slotProps.user.firstName }}
      </template>
    </user>
  </div>
</template>

<script>
import User from "./User.vue";

export default {
  name: "app",
  components: {
    User
  }
};
</script>

<style></style>

  • 父组件 Test.vue还可以这么写,v-slot:default="slotProps"改为v-slot="slotProps"
<template>
  <div id="app">
    <!-- 子组件 -->
    <user>
      <template v-slot="slotProps">
        <!-- 插槽内容 -->
        {{ slotProps.user.firstName }}
      </template>
    </user>
  </div>
</template>

<script>
import User from "./User.vue";

export default {
  name: "app",
  components: {
    User
  }
};
</script>

<style></style>

单个默认插槽的缩写形式

总结上面的作用域插槽。在上述情况下,当且仅当提供了默认插槽内容时,我们可以使用 v-slot 直接作用在组件上:

<current-user v-slot:default="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

我们可以简化上面的的默认插槽写法:

<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

请注意了,默认插槽的缩写语法不能与具名插槽混用:

<!-- 控制台将报警告:-->
<!-- To avoid scope ambiguity, the default slot should also use <template> syntax when there are other named slots. -->
<!-- 意思就是说,为了避免作用域模糊 -->
<!-- 当有其他具名插槽时,默认插槽也应当使用 '<template>' 模板语法 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

于是,上面的代码,我们改写成:

<current-user>
 <!-- 两种写法均可 -->
  <!--<template v-slot="slotProps">
    {{ slotProps.user.firstName }}
  </template>-->
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>

  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>

插槽内容的解构赋值

作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:

function (slotProps) {
  // 插槽内容
}

这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop

父组件Test.vue

<template>
  <div id="app">
    <!-- 子组件 -->
    <user v-slot="{ user }">
      <!-- 插槽内容 -->
      {{ user }}
      <br />
      {{ user.firstName }}
    </user>
  </div>
</template>

<script>
import User from "./User.vue";

export default {
  name: "app",
  components: {
    User
  }
};
</script>

<style></style>

这时候访问Test.vue显示的内容为
在这里插入图片描述

子组件 User.vue

<template>
  <div>
    <!-- 作用域插槽:插槽prop -->
    <slot :user="user">
      <!-- 后备内容 -->
      {{ user.lastName }}
    </slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      user: {
        firstName: "张",
        lastName: "三"
      }
    };
  }
};
</script>
<style></style>

**父组件Test.vue<user v-slot="{ user }">里面的user必须和子组件User.vue中<slot :user="user">:user**保持一致,例如
Test.vue

<template>
  <div id="app">
    <!-- 子组件 -->
    <user v-slot="{ person }">
      <!-- 插槽内容 -->
      {{ person }}
      <br />
      {{ person.firstName }}
    </user>
  </div>
</template>

<script>
import User from "./User.vue";

export default {
  name: "app",
  components: {
    User
  }
};
</script>

<style></style>

User.vue

<template>
  <div>
    <!-- 作用域插槽:插槽prop -->
    <slot :person="user">
      <!-- 后备内容 -->
      {{ user.lastName }}
    </slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      user: {
        firstName: "张",
        lastName: "三"
      }
    };
  }
};
</script>
<style></style>

结果
在这里插入图片描述

  • 这样可以使模板更简洁,尤其是在该插槽提供了多个 prop 的时候。它同样开启了 prop 重命名等其它可能,例如将 person重命名为 people:

Test.vue

<template>
  <div id="app">
    <!-- 子组件 -->
    <user v-slot="{ person: people }">
      <!-- 插槽内容 -->
      {{ people }}
      <br />
      {{ people.firstName }}
    </user>
  </div>
</template>

<script>
import User from "./User.vue";

export default {
  name: "app",
  components: {
    User
  }
};
</script>

<style></style>

User.vue

<template>
  <div>
    <!-- 作用域插槽:插槽prop -->
    <slot :person="user">
      <!-- 后备内容 -->
      {{ user.lastName }}
    </slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      user: {
        firstName: "张",
        lastName: "三"
      }
    };
  }
};
</script>
<style></style>

结果在这里插入图片描述

  • 你甚至可以定义后备内容,用于插槽 prop 是 undefined 的情形:

命名插槽简写

这个简单一些,就不去写实例了

2.6.0+ 新增
v-onv-bind类似,v-slot 也有一个简写,即使用 #代替 v-slot。例如, v-slot:header 简写成 #header:

<base-layout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template #footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

和其他指令一样,只有在提供参数时才能使用简写形式,下面的写法是无效的:

<!-- 将会触发一个控制台警告 -->
<current-user #="{ user }">
  {{ user.firstName }}
</current-user>

也就是说,如果你想使用简写语法,则务必指定插值的名字:

<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值