Vue-slot插槽

1、插槽内容 

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!--使用 slots 进行内容分发-->
<div id="blog-post-demo">
   <navigation-link url="/profile">
    Your Profile
  </navigation-link>

</div>
<script>
  /*使用 slots 进行内容分发
  * 通过 Vue 的 <slot> 自定义元素,实现在组件内插入内容
  * */
   Vue.component('navigation-link', {
    props: ['url'],
    template: `
      <a
        v-bind:href="url"
        class="nav-link"
      >
      <slot></slot>
    </a>
  `
  })

    new Vue({
        el: '#blog-post-demo',

    })
</script>

在 slot 位置,可以包含任何模板代码,也包括 HTML:

甚至,slot 位置也能包含其他组件: 

如果 <navigation-link> 完全没有 <slot> 元素,则 slot 位置传递的所有内容都会被直接丢弃。

2、命名插槽(named slot)

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="blog-post-demo">
  <!--为了给命名插槽提供内容,我们可以在父组件模板的 <template> 元素上使用 slot 特性(译注:这样可以将父组件模板中 slot 位置,
  和子组件 slot 元素产生关联,便于插槽内容对应传递):-->
  <base-layout>
    <!--
    <template slot="header">
      <h1>这里是一个页面标题</h1>
    </template>

    <p>main 内容的一个段落。</p>
    <p>main 内容的另一个段落。</p>

    <template slot="footer">
      <p>这里是一些联系信息</p>
    </template>
    -->
    <!--也可以对某个普通元素,直接使用 slot 特性:-->
    <h1 slot="header">这里是一个页面标题</h1>

    <p>main 内容的一个段落。</p>
    <p>main 内容的另一个段落。</p>

    <p slot="footer">这里是一些联系信息</p>
  </base-layout>

</div>
<script>
/*
* 在某些场景中,需要用到多个插槽
* 对于这种场景,<slot> 元素有一个特殊的 name 特性,可以用于定义除默认插槽以外的多余插槽:
*
* */
  Vue.component('base-layout', {
    template: `
      <div class="container">
        <header>
          <slot name="header"></slot>
        </header>
        <main>
          <slot></slot>
        </main>
        <footer>
          <slot name="footer"></slot>
        </footer>
      </div>
  `
  })

  new Vue({
    el: '#blog-post-demo',

  })
</script>

还有一个未命名插槽(unnamed slot),这是默认插槽,它是用于放置所有不匹配内容的插槽位置。 

3、默认插槽内容(default slot content)

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="blog-post-demo">

  <submit-button>
    Upload
  </submit-button>

</div>
<script>
/*
我们可以在 <slot> 元素内部指定一个默认内容。
用户也可以传入slot内容,覆盖默认内容
*/
  Vue.component('submit-button', {
    template: `
      <button type="submit">
        <slot>SubmitDefault</slot>
      </button>
  `
  })

  new Vue({
    el: '#blog-post-demo',

  })
</script>

4、编译时的作用域(compilation scope)

当你在 slot 内部想要使用当前作用域下的数据,例如:

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

这些插槽内容,可以访问与插槽模板之外其余部分模板,完全相同的实例属性(也就是处于同一“作用域”)。然而插槽内容无法访问 <navigation-link> 组件内部的作用域。例如,试图访问传入此组件内部的 url,就会无法正常运行。牢记准则:

父组件模板的内容,全部在父组件作用域内编译;子组件模板的内容,全部在子组件作用域内编译。

5、作用域插槽 

在某些场景中,需要提供一个具有「可以访问组件内部数据的可复用插槽(reusable slot)」的组件。例如,一个简单的 <todo-list> 组件,可能包含如下模板:

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

但是在我们应用程序的某些部分中,我们想要将 todo items 中的每一项,都渲染为不同于 todo.text 的内容。这就是引入作用域插槽的原因。

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="blog-post-demo">
  <todo-list v-bind:todos="todos">
    <!--通过 slot-scope 特性访问子组件数据-->
    <!-- 将 `slotProps` 作为插槽内容所在作用域(slot scope)的引用名称 -->
    <template slot-scope="slotProps">
      <!-- 为 todo items 定义一个模板, -->
      <!-- 通过 `slotProps` 访问每个 todo 对象。 -->
      <span v-if="slotProps.todo.isComplete">✓</span>
      {{ slotProps.todo.text }}
    </template>
  </todo-list>
</div>
<script>

  Vue.component('todo-list', {
    props: ['todos'],
    /*
    * 我们为每个 todo 提供一个 slot 元素,然后,将 `todo` 对象作为 slot 元素的一个 prop 传入。
    * */
    template: `
      <ul>
        <li
          v-for="todo in todos"
          v-bind:key="todo.id"
        >
        <slot v-bind:todo="todo">
          {{ todo.text }}
        </slot>
        </li>
      </ul>
  `
  })

  new Vue({
    el: '#blog-post-demo',
    data: {
      todos: [
        {id: 1, text: 'text1内容'},
        {id: 2, text: 'text2内容', isComplete: true},
        {id: 3, text: 'text3内容'}
      ]
    }
  })
</script>

在 2.5.0+,slot-scope 不再局限于 <template> 元素,而是可以在任何元素或任何组件中的插槽内容上使用。

5.1解构slot-scope

slot-scope 的值,实际上可以接收任何有效的 JavaScript 表达式,可以出现在函数定义中的参数所在位置。

<todo-list v-bind:todos="todos">
  <template slot-scope="{ todo }">
    <span v-if="todo.isComplete">✓</span>
    {{ todo.text }}
  </template>
</todo-list>

这是让作用域插槽用法,变得思路清晰的好方法。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值