• Vue插槽详解 | 什么是插槽?


    file

    作者 | Jeskson

    来源 | 达达前端小酒馆

    什么是插槽?插槽的指令为v-slot,它目前取代了slot和slot-scope,插槽内容,vue实例一套内容分发的api,将slot元素作为承载分发内容的出口。

    组件的书写:

    <my-link url="/profile">
    dada
    </my-link>
    

    运用组件模板,可以在里面书写:

    <a v-bind:href="url" class="css-link">
    <slot></slot>
    </a>
    
    <slot></slot>会替换dada
    

    插槽内可以写任何模板代码:

    <my-link url="/profile">
    <span class=“weixin"> </span>
    dada
    </my-link>
    
    <my-link url="/profile">
    <my-icon name="user"></my-icon>
    dada
    <my-link>
    // 添加图标组件
    

    如果my-link没有包含一个slot元素,之间的任何内容都会消失。

    什么是插槽,它是vue提出的一个概念,插槽用于决定将所携带的内容,插入到指定的某个位置,使得模块分块,具有模块化特质。

    插槽怎么用?

    // 父组件
    <template>
    <div>
    我是父组件
    <slotda>
    <p style="color:red">我是父组件得插槽内容</p>
    </slotda>
    <div>
    </template>
    

    在父组件中引用子组件中写入想要得显示内容

    子组件slotda

    <template>
    <div class="slotda">
     <div>我是slotda组件</div>
     <slot></slot>
     </idv>
    </template>
    

    在子组件中写入slot,所在位置就是父组件要显示得内容

    // 父组件
    <template>
    <div>
    我是父组件
    <slotda>
    <p style="color:red">我是父组件插槽内容</p>
    <slotdd></slotdd>
    </div>
    </template>
    

    子组件

    <template>
    <div class="slotdd">
    我是slotdd组件
    </div>
    </template>
    

    具名插槽

    <template>
    <div class="slotdadada">
     <div>slotdadada</div>
     <slot name="header"></slot>
     <slot></slot>
     <slot name="footer"></slot>
    </div>
    </template>
    
    子组件
    

    父组件

    <template>
    <div>
    我是父组件
    <slotdadada>
     <p>dada</p>
     <template slot="header">
     <p>da</p>
     </template>
     <p slot="footer">我是footer</p>
    </slotdadada>
    </div>
    </template>
    

    插槽默认内容

    // 父组件
    <template>
    <div>
    我是父组件
    <slotdd></slotdd>
    </div>
    </template>
    

    子组件

    <template>
    <div class="slotdd">
     <slot>ddd</slot>
     </div>
    </template>
    

    作用域

    <template>
    <div>
    我是父组件
    <slot-d>
    <p>{{name}}</p>
    </slot-d>
    </div>
    </template>
    
    <script>
    export default {
     data() {
      return {
       name: 'dada'
      }
    }}
    </script>
    

    子组件

    <template>
    <div class="slot-d">
    <slot></slot>
    </div>
    </template>
    

    插槽可以是任意内容:

    插槽就是Vue实现的一套内容分发的API,将元素作为承载分发内容的出口。

    没有插槽的情况下,在组件标签内些一些内容是不起任何作用的,当我在组件中声明了slot元素后,在组件元素内写的内容就会跑到它这里了!

    <div id="app">
    <child-component></child-component>
    </div>
    
    </script>
    Vue.component('child-component', {
     template: `
     <div>Hello,World!</div>
     `
     })
     let vm = new Vue({
     el: '#app',
     data:{
     }
    })
    </script>
    

    file

    <child-component>你好</child-component>
    

    组件之间得内容没有显示,使用插槽就有显示了,看看如何用:

    Vue.component('child-component',{
            template:`
                <div>
                Hello,World!
                <slot></slot>
                </div>
            `
        })
    

    file

    具名插槽,就是给这个插槽起个名字,slot属性对应的内容都会和组件中name一一对应。

    child-component,没有名字得就是默认得。

    <div id="app">
        <child-component>
            <template slot="girl">
                购物、逛街
            </template>
            <template slot="boy">
                帅气
            </template>
            <div>
                我是人
                我是默认的插槽
            </div>
        </child-component>
    </div>
    
    <script>
        Vue.component('child-component',{
            template:`
                <div>
                <h4>这个世界有男人和女人</h4>
    
                <slot name="girl"></slot>
    
                <div style="height:1px;background-color:red;"></div>
    
                <slot name="boy"></slot>
    
                <div style="height:1px;background-color:red;"></div>
    
                <slot></slot>
                </div>
            `
        })
        let vm = new Vue({
            el:'#app',
            data:{
            }
        })
    </script>
    

    作用域插槽,在组件上的属性,可以在组件元素内使用!

    在template元素上添加属性slot-scope

    <div id="app">
        <child>
            <template slot-scope="a">
          <!-- {"say":"你好"} -->
                {{a}}
            </template>
        </child>
    </div>
    
    Vue.component('child',{
            template:`
                <div>
                    <slot say="你好"></slot>
                </div>
            `
        })
    
    <div id="app">
        <child :lists="nameList">
            <template slot-scope="a">
                {{a}}
            </template>
        </child>
    </div>
    
    Vue.component('child',{
            props:['lists'],
            template:`
                <div>
                    <ul>
                        <li v-for="list in lists">
                            <slot :bbbbb="list"></slot>
                        </li>
                    </ul>
                </div>
            `
        })
    

    在一个组件中使用 标签,就是定义一个插槽。

    如果组件中没包含任何被传入的东西都会被抛弃。

    <div class="container">
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
    
    <base-layout>
      <template slot="header">
        <h1>d</h1>
      </template>
    
      <p>dd.</p>
      <p>dd.</p>
    
      <template slot="footer">
        <p> ddd </p>
      </template>
    </base-layout>
    
    <base-layout>
      <h1 slot="header">H</h1>
    
      <p>A.</p>
      <p>A.</p>
    
      <p slot="footer">H</p>
    </base-layout>
    

    在没有指定slot属性的时候 都会放在slot没有name属性的插槽当中。

    编译作用域

    插槽中的内容不能访问父级作用域

    <navigation-link url="/profile">
      Logged in as {{ user.name }}
    </navigation-link>
    // 部分不能访问 url
    

    父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。

    <ul>
      <li
        v-for="todo in todos"
        v-bind:key="todo.id"
      >
        {{ todo.text }}
      </li>
    </ul>
    

    合成组件:

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

    然后你在 <navigation-link> 的模板中可能会写为:

    Vue.component('navigation-link', {
        template: `
          <a
            v-bind:href="url" rel="external nofollow"
            class="nav-link"
          >
          <slot></slot>
          </a>
        `
      });
    

    当组件渲染的时候,这个 元素将会被替换为“Your Profile”。

    file

    插槽内可以包含任何模板代码

    <navigation-link url="/profile">
     <!-- 添加一个 Font Awesome 图标 -->
     <span class="fa fa-user"></span>
     Your Profile
    </navigation-link>
    

    也可以是组件:

    <navigation-link url="/profile">
     <!-- 添加一个图标的组件 -->
     <font-awesome-icon name="user"></font-awesome-icon>
     Your Profile
    </navigation-link>
    

    但是如果在navigation-link中没有包含一个slot元素,都会让之间得内容都消失得。

    具名插槽

    需要多个插槽

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

    作用域插槽

    
    Vue.component('todo-list',{
        template:`
        <ul>
          <li
            v-for="todo in todos"
            v-bind:key="todo.id">
            {{ todo.text }}
          </li>
        </ul>
        `
      });
      
      <ul>
     <li
      v-for="todo in todos"
      v-bind:key="todo.id"
     >
      <!-- 我们为每个 todo 准备了一个插槽,-->
      <!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
      <slot v-bind:todo="todo">
       <!-- 回退的内容 -->
       {{ todo.text }}
      </slot>
     </li>
    </ul>
    

    看代码后,插槽内容基本了解。对于编译作用域:

    <navigation-link url="/profile">
      Logged in as {{ user.name }}
    </navigation-link>
    

    该插槽和模板得其他地方一样都可以访问相同的实例属性,就是相同的”作用域“,但不能访问navigation-link标签的作用域。

    <navigation-link url="/profile">
      Clicking here will send you to: {{ url }}
      <!--
      这里的 `url` 会是 undefined,因为 "/profile" 是
      _传递给_ <navigation-link> 的而不是
      在 <navigation-link> 组件*内部*定义的。
      -->
    </navigation-link>
    

    我了解了呢。
    后备内容

    <button type="submit">
      <slot></slot>
    </button>
    
    <button type="submit">
      <slot>Submit</slot>
    </button>
    
    <submit-button></submit-button>
    
    <button type="submit">
      Submit
    </button>
    

    作用域插槽

    <span>
      <slot>{{ user.lastName }}</slot>
    </span>
    
    <current-user>
      {{ user.firstName }}
    </current-user>
    
    然而上述代码不会正常工作,因为只有 <current-user> 
    组件可以访问到 user 而我们提供的内容是在父级渲染的。
    
    <span>
      <slot v-bind:user="user">
        {{ user.lastName }}
      </slot>
    </span>
    

    绑定在 元素上的特性被称为插槽 prop

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

    默认插槽的缩写语法不能和具名插槽混用

    <!-- 无效,会导致警告 -->
    <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:default="slotProps">
        {{ slotProps.user.firstName }}
      </template>
    
      <template v-slot:other="otherSlotProps">
        ...
      </template>
    </current-user>
    

    解构插槽 Prop

    function (slotProps) {
      // 插槽内容
    }
    
    <current-user v-slot="{ user }">
      {{ user.firstName }}
    </current-user>
    
    <current-user v-slot="{ user: person }">
      {{ person.firstName }}
    </current-user>
    

    动态插槽名

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

    ❤️ 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论]

    作者Info:

    【作者】:Jeskson
    【原创公众号】:达达前端小酒馆。
    【福利】:公众号回复 “资料” 送自学资料大礼包(进群分享,想要啥就说哈,看我有没有)!
    【转载说明】:转载请说明出处,谢谢合作!~

    大前端开发,定位前端开发技术栈博客,PHP后台知识点,web全栈技术领域,数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。谢谢支持,承蒙厚爱!!!


    若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


    请点赞!因为你们的赞同/鼓励是我写作的最大动力!

    欢迎关注达达的CSDN!

    这是一个有质量,有态度的博客

    前端技术栈

  • 相关阅读:
    geoServer的安装
    类设计原则
    零散知识点
    JavaScript setTimeOut()方法的一些疑点自己记录
    贴吧表情雨
    Laravel中tosql()是如何返回sql
    关于new static 与 new self的区别(后续有新发现,会继续更新)
    Lumen、Laravel开发问题记录
    文件实时对比,将数据组装入库(SQLITE)
    PHPSTUDY下升级mysql后无法启动
  • 原文地址:https://www.cnblogs.com/dashucoding/p/12026391.html
Copyright © 2020-2023  润新知