zoukankan      html  css  js  c++  java
  • vue的插槽

    vue官网的插槽例子,现记录熟悉一下:

    一、插槽内容

    父组件:

     1 <template>
     2   <div>
     3     <navigation-link url="/profile">
     4       Your Profile
     5     </navigation-link>
     6     <br>
     7     <navigation-link url="/profile">
     8       <Icon type="ios-checkmark" size="16"/>
     9       <span>Your Profile</span>
    10     </navigation-link>
    11   </div>
    12 </template>
    13 <script>
    14   import NavigationLink from '@/components/NavigationLink';
    15   export default {
    16     components:{
    17       NavigationLink
    18     },
    19     data(){
    20       return {
    21       }
    22     }
    23   }
    24 </script>

    子组件:

     1 <template>
     2   <a :href="url" class="nav-link">
     3     <slot></slot>
     4   </a>
     5 </template>
     6 <script>
     7     export default {
     8         name: "NavigationLink",
     9         props: {
    10           href:{
    11             type:String,
    12             default:''
    13           }
    14         },
    15     }
    16 </script>

    渲染的页面:

    上面的代码可以看出,slot就是把组件NavigationLink起始标签之间的内容显示出来,如果子组件没有包含<slot></slot>元素,NavigationLink起始标签之间的内容将没有任何意义

    二、编译作用域

     1 <template>
     2   <div>
     3     <navigation-link url="/profile">
     4       以用户名{{ user.name }}登录
     5     </navigation-link>
     6     <br>
     7     <navigation-link url="/profile">
     8       点击此处将发送到: {{ url }}
     9       <!--这里的 `url` 会是 undefined,因为 "/profile" 是_传递给_ <navigation-link> 的
    10       而不是在 <navigation-link> 组件内部定义的-->
    11     </navigation-link>
    12   </div>
    13 </template>
    14 <script>
    15   import NavigationLink from '@/components/NavigationLink';
    16   export default {
    17     components:{
    18       NavigationLink
    19     },
    20     data(){
    21       return {
    22         user:{
    23           name:'admin'
    24         }
    25       }
    26     }
    27   }
    28 </script>

    渲染的页面:

     规则:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的

    三、后备内容

    以字面理解,就是替补的意思,正式球员在的话,就是替补,正式球员不在,替补上场,同样,组件标签之间如果提供内容,就会渲染提供的内容,否则渲染后备(默认的)内容,后备内容在子组件中设置,与父子传参的子组件props接收父组件传的参数设置默认值有些相似:

    父组件:

     1 <template>
     2   <div>
     3     <submit-button></submit-button>
     4   </div>
     5 </template>
     6 <script>
     7   import SubmitButton from '@/components/SubmitButton';
     8   export default {
     9     components:{
    10       SubmitButton
    11     },
    12     data(){
    13       return {
    14       }
    15     }
    16   }
    17 </script>

    子组件:

     1 <template>
     2   <div>
     3     <button type="submit">
     4       <slot>Submit</slot>
     5     </button>
     6   </div>
     7 </template>
     8 <script>
     9     export default {
    10         name: "SubmitButton"
    11     }
    12 </script>

    渲染页面:

     四、具名插槽

    在一个组件里面,有时我们需要多个插槽,如何区分并正确出我们想要的页面,这时需要用到具名插槽

    父组件

     1 <template>
     2   <div>
     3     <base-layout>
     4       <template v-slot:header>
     5         <h1>这是一篇文章标题</h1>
     6       </template>
     7 
     8       <!--任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容并显示在不带slot的内容中-->
     9       <p>这是一篇文章内容</p>
    10 
    11       <template v-slot:footer>
    12         <p>这是一些文章底部信息</p>
    13       </template>
    14     </base-layout>
    15   </div>
    16 </template>
    17 <script>
    18   import BaseLayout from '@/components/BaseLayout';
    19   export default {
    20     components:{
    21       BaseLayout
    22     },
    23     data(){
    24       return {
    25       }
    26     }
    27   }
    28 </script>

    子组件:

     1 <template>
     2   <div class="container">
     3     <header>
     4       <slot name="header"></slot>
     5     </header>
     6     <main>
     7       <slot></slot>
     8       <!--一个不带 name 的 <slot> 出口会带有隐含的名字“default”-->
     9     </main>
    10     <footer>
    11       <slot name="footer"></slot>
    12     </footer>
    13   </div>
    14 </template>
    15 <script>
    16     export default {
    17         name: "BaseLayout"
    18     }
    19 </script>

    页面的渲染:

     如果父组件默认区域改为

    1 <!--任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容并显示在不带slot的内容中-->
    2 <p>这是一篇文章内容</p>
    3 <!--<template> 中包裹默认插槽的内容,就只会显示这包裹的默认内容,上面的将不会显示-->
    4 <template v-slot:default>
    5    <p>这是一篇文章的另一个内容</p>
    6 </template>

    此时页面显示:

     有此可以看出,还是以配置的v-slot:default为准,配置了这个v-slot:default,父组件中没有包裹在带v-slot的template标签中的内容都会丢失

     五、作用域插槽

    子组件:

     1 <template>
     2     <span>
     3       <!--为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 <slot> 元素的一个特性绑定上去-->
     4       <slot v-bind:user="user">
     5         {{ user.lastName }}
     6       </slot>
     7     </span>
     8 </template>
     9 <script>
    10     export default {
    11         name: "CurrentUser",
    12         data(){
    13           return {
    14             user:{
    15               firstName:'Tom',
    16               lastName:'Green'
    17             }
    18           }
    19         }
    20     }
    21 </script>

    子组件的属性值user.firstName想让父组件获取并覆盖掉插槽后备内容user.lastName,可以将user作为一个属性绑定到 <slot> 上,绑定在 <slot> 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字:在示例中我们将包含所有插槽 prop 的对象命名为 slotProps

    父组件:

     1 <template>
     2   <div>
     3     <current-user>
     4       <template v-slot:default="slotProps">
     5         {{ slotProps.user.firstName }}
     6       </template>
     7     </current-user>
     8   </div>
     9 </template>
    10 <script>
    11   import CurrentUser from '@/components/CurrentUser';
    12   export default {
    13     components:{
    14       CurrentUser
    15     },
    16   }
    17 </script>

    页面显示:

      五(一)、独占默认插槽的缩写写法

         在上述示父组件情况下,当被提供的内容只有默认插槽时,组件的标签current-user才可以被当作插槽的模板template来使用。这样我们就可以把 v-slot 直接用在组件上:

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

      这种写法还可以更简单。就像假定未指明的内容对应默认插槽一样,不带参数的 v-slot 被假定对应默认插槽

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

      说白了,就是父组件里面的写法可以精简为最后那种写法,实现的效果是一样的,只就是缩写写法,但是需要注意的是一旦出现具名插槽,就不能用缩写写法,就要老老实实写完整的基于 <template> 的语法,每个插槽都要指明所用插槽的名称

      五(二)、解构插槽Prop

      父组件:

     1 <template>
     2   <div>
     3     <!--解构user-->
     4     <current-user v-slot="{ user }">
     5       {{ user.firstName }}
     6     </current-user>
     7     <!--将person重命名为people-->
     8     <current-user v-slot="{ person: people }">
     9       {{ people.lastName }}
    10     </current-user>
    11     <!--以下的写法直接编译报错-->
    12     <current-user v-slot="{ user = { firstName: 'Guest' } }">
    13       {{ user.firstName }}
    14     </current-user>
    15     <!--改为这种写法,并不能输出值-->
    16     <current-user #default="{ person = { firstName: 'Guest' } }">
    17       {{ person.firstName }}
    18     </current-user>
    19   </div>
    20 </template>
    21 <script>
    22   import CurrentUser from '@/components/CurrentUser';
    23   export default {
    24     components:{
    25       CurrentUser
    26     },
    27   }
    28 </script>

    子组件:

     1 <template>
     2     <span>
     3       <slot v-bind:user="user" v-bind:person="person">
     4         {{ user.lastName }}
     5       </slot>
     6     </span>
     7 </template>
     8 <script>
     9     export default {
    10         name: "CurrentUser",
    11         data(){
    12           return {
    13             user:{
    14               firstName:'Tom',
    15               lastName:'Green'
    16             },
    17             person:{
    18               lastName:'Smith'
    19             }
    20           }
    21         }
    22     }
    23 </script>

    官网给的覆盖后备内容的解构写法,用于插槽子组件的person的prop 是 undefined 的情形:

    1 <current-user v-slot="{ user = { firstName: 'Guest' } }">
    2   {{ user.firstName }}
    3 </current-user>

    编译报错,去网上百度解决方法,有人说改成简写形式

    1 <current-user #default="{ user = { firstName: 'Guest' } }">
    2   {{ user.firstName }}
    3 </current-user>

    确实不报错了,但是也不输出值'Guest',如果有哪位大佬有解决方法,欢迎评论

    六、动态插槽名

    动态指令参数也可以用在 v-slot 上,来定义动态的插槽名:

    1 <base-layout>
    2   <template v-slot:[dynamicSlotName]>
    3     ...
    4   </template>
    5 </base-layout>

    父组件:

     1 <template>
     2   <div>
     3     <base-layout>
     4       <template v-slot:[header]="headerProp">
     5         <h1>{{headerProp.header.content}}</h1>
     6       </template>
     7       <template v-slot:[def]="defaultProp">
     8         <p>{{defaultProp.def.content}}</p>
     9       </template>
    10       <template v-slot:[footer]="footerProp">
    11         <p>{{footerProp.footer.content}}</p>
    12       </template>
    13     </base-layout>
    14   </div>
    15 </template>
    16 <script>
    17   import BaseLayout from '@/components/BaseLayout';
    18   export default {
    19     components:{
    20       BaseLayout
    21     },
    22     data(){
    23       return {
    24         header:'header',
    25         def:'default',
    26         footer:'footer'
    27       }
    28     }
    29   }
    30 </script>

    子组件:

     1 <template>
     2   <div class="container">
     3     <header>
     4       <slot name="header" v-bind:header="header"></slot>
     5     </header>
     6     <main>
     7       <slot v-bind:def="def"></slot>
     8     </main>
     9     <footer>
    10       <slot name="footer" v-bind:footer="footer"></slot>
    11     </footer>
    12   </div>
    13 </template>
    14 
    15 <script>
    16     export default {
    17         name: "BaseLayout",
    18         data(){
    19           return {
    20             header:{
    21               name:'header',
    22               content:'这是标题'
    23             },
    24             def:{
    25               name:'default',
    26               content:'这是内容'
    27             },
    28             footer:{
    29               name:'footer',
    30               content:'这是底部信息'
    31             }
    32           }
    33         }
    34     }
    35 </script>
    36 
    37 <style scoped>
    38 
    39 </style>

    页面显示:

  • 相关阅读:
    团队与领导力健康检查 | 体检表
    如何改变组织文化
    如何在各种文化背景下成功敏捷
    OKR痛点与误区 | 敏捷家分享007
    Scrum培训感想
    如何讲好故事
    Lc70_爬楼梯
    Lc641_设计循环双端队列
    Lc32_最长有效括号
    Lc239_滑动窗口最大值
  • 原文地址:https://www.cnblogs.com/lhjfly/p/11814284.html
Copyright © 2011-2022 走看看