Vue.js 教程

Vue.js 插槽命名

Vue.js  从 2.6.0 版本起,已废弃的使用 slot 属性语法。

有时我们需要多个插槽,例如:对于一个带有如下模板的 <base-layout> 组件,我们需要在 <header>、<main> 和 <footer> 中添加插槽:

<div class="container">
   <header>
       <!-- 我们希望把页头放这里 -->
   </header>
   <main>
       <!-- 我们希望把主要内容放这里 -->
   </main>
   <footer>
       <!-- 我们希望把页脚放这里 -->
   </footer>
</div>

对于这样的情况,站在使用 <base-layout> 组件的角度,我们该如何区分这些插槽呢?幸运的是 <slot> 元素有一个特殊 name 属性。该属性可以用来为插槽定义唯一名称,如下:

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

注意:一个不带 name 属性的 <slot> 插槽会带有隐含的默认名字 “default”。

<base-layout> 组件定义如上,我们该怎样去使用它呢?在向指定名称的插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并通过 v-slot 指令指定具体插槽的名称,如下:

<base-layout>
   <!-- 这是提供给名为 header 插槽的默认值 -->
   <template v-slot:header>
       <h1>Here might be a page title</h1>
   </template>

   <!-- 默认插槽,名为 default 插槽的默认值 -->
   <p>A paragraph for the main content.</p>
   <p>And another one.</p>

   <!-- 这是提供给名为 footer 插槽的默认值 -->
   <template v-slot:footer>
       <p>Here's some contact info</p>
   </template>
</base-layout>

现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。

然而,如果你希望更明确一些,仍然可以在一个 <template> 中包裹默认插槽的内容,如下:

<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>

上面的任何一种写法都会渲染出如下 HTML:

<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>

注意:v-slot 只能添加在 <template> 上 (只有一种例外情况),这一点和已经废弃的 slot 属性不同。

插槽命名缩写

Vue.js 中 2.6.0 新增。跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header,例如:

<base-layout>
   <template #header>...</template>
   
   <p>A paragraph for the main content.</p>
   <p>And another one.</p>
   
   <template #footer>...</template>
</base-layout>

然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:

<!-- 这样会触发一个警告 -->
<current-user #="{ user }">
   {{ user.firstName }}
</current-user>

如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:

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

动态插槽名

Vue.js 中 2.6.0 新增。动态指令参数也可以用在 v-slot 上,来定义动态的插槽名,例如:

<base-layout>
 <template v-slot:[dynamicSlotName]>
   ...
 </template>
</base-layout>

完整示例

<html>
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Vue</title>
   <!-- 使用 CDN 引入 Vue 库 -->
   <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> -->
   <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.js"></script>
</head>
<body>

   <div id="app">
       <base-layout>
           <!-- 这是提供给名为 header 插槽的默认值 -->
           <template v-slot:header>
               <h1>Here might be a page title</h1>
           </template>

           <!-- 默认插槽,名为 default 插槽的默认值 -->
           <p>A paragraph for the main content.</p>
           <p>And another one.</p>

           <!-- 这是提供给名为 footer 插槽的默认值 -->
           <template v-slot:footer>
               <p>Here's some contact info</p>
           </template>
       </base-layout>
   </div>

   <script type="text/javascript">
       Vue.component('base-layout', {
           template: `
               <div>
                   <header style="background:red;">
                       <slot name="header"></slot>
                   </header>
                   <main style="background:green;">
                       <slot></slot>
                   </main>
                   <footer style="background:blue;">
                       <slot name="footer"></slot>
                   </footer>
               </div>
           `
       });

       var app = new Vue({
           el: "#app",
           data: {}
       });
   </script>

</body>
</html>

运行效果如下图:

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号