Vue插槽原理与用法详解

本文实例讲述了Vue插槽原理与用法。分享给大家供大家参考,具体如下:

1 插槽内容

Vue 实现了一套内容分发的 API,这套 API 基于当前的 Web Components 规范草案,将 <slot> 元素作为承载分发内容的出口。

它允许你像这样合成组件:

<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>
    `
  });

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

插槽内可以包含任何模板代码,包括 HTML:

<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> 元素,则任何传入它的内容都会被抛弃。

2 具名插槽

有些时候我们需要多个插槽。例如,一个假设的 <base-layout> 组件多模板如下:

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

对于这样的情况,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

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

在向具名插槽提供内容的时候,我们可以在一个父组件的 <template> 元素上使用 slot 特性:

<base-layout>
 <template slot="header">
  <h1>Here might be a page title</h1>
 </template>
 <p>A paragraph for the main content.</p>
 <p>And another one.</p>
 <template slot="footer">
  <p>Here's some contact info</p>
 </template>
</base-layout>

另一种 slot 特性的用法是直接用在一个普通的元素上:

<base-layout>
 <h1 slot="header">Here might be a page title</h1>
 <p>A paragraph for the main content.</p>
 <p>And another one.</p>
 <p slot="footer">Here's some contact info</p>
</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>

3 默认插槽的内容

有的时候为插槽提供默认的内容是很有用的。例如,一个 <submit-button> 组件可能希望这个按钮的默认内容是“Submit”,但是同时允许用户覆写为“Save”、“Upload”或别的内容。

你可以在 <slot> 标签内部指定默认的内容来做到这一点。

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

如果父组件为这个插槽提供了内容,则默认的内容会被替换掉。

4 编译作用域

当你想在插槽内使用数据时,例如:

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

该插槽可以访问跟这个模板的其它地方相同的实例属性 (也就是说“作用域”是相同的)。但这个插槽不能访问 <navigation-link> 的作用域。例如尝试访问 url 是不会工作的。牢记一条准则:

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

5 作用域插槽

2.1.0+ 新增

有的时候你希望提供的组件带有一个可从子组件获取数据的可复用的插槽。例如一个简单的 <todo-list> 组件的模板可能包含了如下代码:

Vue.component('todo-list',{
    template:`
    <ul>
      <li
        v-for="todo in todos"
        v-bind:key="todo.id">
        {{ todo.text }}
      </li>
    </ul>
    `
  });

但是在我们应用的某些部分,我们希望每个独立的待办项渲染出和 todo.text 不太一样的东西。这也是作用域插槽的用武之地。

为了让这个特性成为可能,你需要做的全部事情就是将待办项内容包裹在一个 <slot> 元素上,然后将所有和其上下文相关的数据传递给这个插槽:在这个例子中,这个数据是 todo 对象:

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

现在当我们使用 <todo-list> 组件的时候,我们可以选择为待办项定义一个不一样的<template> 作为替代方案,并且可以通过 slot-scope 特性从子组件获取数据:

<todo-list v-bind:todos="todos">
  <!--插槽作用域的名字是 slotProps-->
  <template slot-scope="slotProps">
    <!-- 为指定的待办项定义一个模板-->
    <span v-if="slotProps.todo.isComplete">✓</span>
    {{ slotProps.todo.text }}
  </template>
</todo-list>

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

解构 slot-scope

如果一个 JavaScript 表达式在一个函数定义的参数位置有效,那么这个表达式实际上就可以被 slot-scope 接受。也就是说你可以在支持的环境下 单文件组件或现代浏览器),在这些表达式中使用 ES2015 解构语法。例如:

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

这会使作用域插槽变得更干净一些。

希望本文所述对大家vue.js程序设计有所帮助。

(0)

相关推荐

  • Vue中的slot使用插槽分发内容的方法

    本文题材来自:https://cn.vuejs.org/v2/guide/components.html#%E4%BD%BF%E7%94%A8%E6%8F%92%E6%A7%BD%E5%88%86%E5%8F%91%E5%86%85%E5%AE%B9 <slot></slot>标签,简单来说就是占位符,它会帮你占好位置,等你需要的时候直接将html传入,它会帮你显示出来. 也有人说:props可以将数据从父组件传入子组件,slot可以将html从父组件传入子组件.那么如何实现呢?

  • Vue作用域插槽slot-scope实例代码

    vue中的插槽有三种:单个插槽.具名插槽.作用域插槽,这个在官网上能看到 (https://cn.vuejs.org/v2/guide/components.html#单个插槽) 作用域插槽简单来说就是父组件只管显示样式,数据由子组件来提供.比如上面的代码,el-table-column内的template是传递给其内部solt的显示内容,但是scope的值是由el-table-column内部solt绑定的数据返回的.这个数据具体是什么由el-table-column中指定,类似: <slot

  • vue中slot(插槽)的介绍与使用

    什么是插槽? 插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性.插槽显不显示.怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制 Vue slot 原理 在web-components中有slot的概念,https://developers.google.com/web/fundamentals/web-components/shadowdom. <slot> 元素 Shado

  • 如何理解Vue的作用域插槽的实现原理

    本文介绍了如何理解Vue的作用域插槽的实现原理,分享给大家,也给自己留个笔记 举个例子,比如我写了一个可以实现条纹相间的列表组件,发布后,使用者可以自定义每一行的内容或样式(普通的slot就可以完成这个工作).而作用域插槽的关键之处就在于,父组件能接收来自子组件的slot传递过来的参数,具体看案例和注释. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"

  • 从组件封装看Vue的作用域插槽的实现

    作用域插槽不是那么直观的一个概念.Vue文档使用了一段描述性的话来解释作用域插槽: 有的时候你希望提供的组件带有一个可从子组件获取数据的可复用的插槽 -- 但是在我们应用的某些部分,我们希望每个独立的待办项渲染出和 todo.text 不太一样的东西.这也是作用域插槽的用武之地. 但在我看来,至少是第一次读到的时候,这段话相当不好理解.插槽不是分发内容到子组件吗,为什么还要从子组件中获取数据?不是已经有了通过emit事件的方法从子组件向父组件传递数据吗,为什么需要它?作用域插槽到底是来干嘛的?-

  • 详解Vue组件之作用域插槽

    写作用域插槽之前,先介绍一下Vue中的slot内容分发: 如果<child-component></child-component>标签之间没有插入那两个p标签的话,页面会显示子组件模板中定义的"<p>父组件如果没有插入内容,我将被显示</p>"这一则内容,但如果<child-component></child-component>标签之间有插入内容的话,则子组件模板中的<slot></slot&

  • 详解Vue组件插槽的使用以及调用组件内的方法

    组件传参 通过给组件传递参数, 可以让组件变得更加可扩展, 组件内使用props接收参数 export default { props: ['options'], data(){ return {} } } 但是这个方法有局限性, 例如我写了一个对话框组件, 对话框的内容是自定义的 如果我只是显示文字的话, 我可以简单的将字符串传进去props: ['message'] 但是如果需要在其中添加一个按钮的话, 这种方法就显得很笨重了, 所以我们用另一种办法 插槽 slot 插槽 slot的使用就像

  • 详解vue slot插槽的使用方法

    官方文档其实已经讲得很详细,我根据文档,把官方的小案例实现了一下,这样更直观 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"><

  • 使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)

    写在前面 之前写过一篇关于vue实现dialog会话框组件的文章http://www.jb51.net/article/139218.htm 讲到了如何实现一个vue对话框组件,其中涉及到了父组件和子组件的通信,这个不用多说,看我之前的文章就能明白,文章最后也说到了,我们可以使用slot插槽来编写组件,slot用来分发内容到子组件中,从而实现组件的高度复用,编写的组件更加灵活. 还是结合对话框的例子,使用slot来实现对话框组件 注册一个名叫dialog-tip的全局组件 Vue.compone

  • Vue插槽原理与用法详解

    本文实例讲述了Vue插槽原理与用法.分享给大家供大家参考,具体如下: 1 插槽内容 Vue 实现了一套内容分发的 API,这套 API 基于当前的 Web Components 规范草案,将 <slot> 元素作为承载分发内容的出口. 它允许你像这样合成组件: <div id="app1"> <navigation-link url="/profile"> Your Profile </navigation-link>

  • 关于vue中 $emit的用法详解

    1.父组件可以使用 props 把数据传给子组件. 2.子组件可以使用 $emit 触发父组件的自定义事件. vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运行 fn: 例如:子组件: <template> <div class="train-city"> <span @click='select(`大连`)'>大连</span> </div&

  • Vue 中mixin 的用法详解

    说下我对vue中mixin的一点理解 vue中提供了一种混合机制--mixins,用来更高效的实现组件内容的复用.最开始我一度认为这个和组件好像没啥区别..后来发现错了.下面我们来看看mixins和普通情况下引入组件有什么区别? 组件在引用之后相当于在父组件内开辟了一块单独的空间,来根据父组件props过来的值进行相应的操作,单本质上两者还是泾渭分明,相对独立. 而mixins则是在引入组件之后,则是将组件内部的内容如data等方法.method等属性与父组件相应内容进行合并.相当于在引入后,父

  • Vue中$refs的用法详解

    说明:vm.$refs 一个对象,持有已注册过 ref 的所有子组件(或HTML元素) 使用:在 HTML元素 中,添加ref属性,然后在JS中通过vm.$refs.属性来获取 注意:如果获取的是一个子组件,那么通过ref就能获取到子组件中的data和methods <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>D

  • Java switch关键字原理及用法详解

    这篇文章主要介绍了Java中 switch关键原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的一个主要原因就在于它的作用能被if-else代替,况且switch对类型的限制,也阻碍了switch的进一步使用. 先看看switch的语法

  • python 标准库原理与用法详解之os.path篇

    os中的path 查看源码会看到,在os.py中有这样几行 if 'posix' in _names: name = 'posix' linesep = '\n' from posix import * #省略若干代码 elif 'nt' in _names: from nt import * try: from nt import _exit __all__.append('_exit') except ImportError: pass import ntpath as path #...

  • Java基础之Stream流原理与用法详解

    目录 一.接口设计 二.创建操作 三.中间操作 四.最终操作 五.Collect收集 Stream简化元素计算 一.接口设计 从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式:依旧先看核心接口的设计: BaseStream:基础接口,声明了流管理的核心方法: Stream:核心接口,声明了流操作的核心方法,其他接口为指定类型的适配: 基础案例:通过指定元素的值,返回一个序列流,元素的内容是字符串,并转换为Long类型,最终计算求和结果并

  • vue中$emit的用法详解

    目录 vue2.x vue3.x 子组件 父组件 vue2.x 1.父组件可以使用 props 把数据传给子组件.2.子组件可以使用 $emit,让父组件监听到自定义事件 . vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运行 fn: 例如:子组件: <template> <div class="train-city"> <h3>父组件传给子组件的toCity:

  • angular2中Http请求原理与用法详解

    本文实例讲述了angular2中Http请求原理与用法.分享给大家供大家参考,具体如下: 提供HTTP服务 HttpModule并不是Angular的核心模块. 它是Angular用来进行Web访问的一种可选方式,并位于一个名叫@angular/http的独立附属模块中. 编辑app.module.ts import { HttpModule, JsonpModule } from '@angular/http'; @NgModule({ imports: [ HttpModule, Jsonp

  • JavaScript对象字面量和构造函数原理与用法详解

    本文实例讲述了JavaScript对象字面量和构造函数.分享给大家供大家参考,具体如下: 对象中只有两种属性:(一种比较细的分法) 属性(数据属性)比如:名字,年龄,性别,出版社,地址等信息: 方法(封装代码的属性:函数 ,在这也是一种属性). 在JS中对象的字面量和构造函数是非常的重点,其实在其他的语言中,是没有对象字面量的. 一.对象的字面量的语法: { 属性名: 属性值, 属性名: 属性值, 方法名: 你们函数 } 这个大括号括起来的整个代码块就是叫做对象. var p1 = { } ①访

随机推荐