zoukankan      html  css  js  c++  java
  • Vue3手册译稿

    插槽

    本章节需要掌握组件基础

    插槽内容

    Vue实现一套优秀的内容分发接口,基于WEB组件草案,使用<slot>标签提供内容分发服务。
    这允许你像这样构成一个组件:

    <todo-button>
      Add todo
    </todo-button>
    

    todo-button模板应该这样写:

    <!-- todo-button 组件模板 -->
    <button class="btn-primary">
      <slot></slot>
    </button>
    

    组件被渲染时,<slot></solt>将会被替换为:Add todo:

    <!-- 渲染后的 HTML -->
    <button class="btn-primary">
      Add todo
    </button>
    

    插槽替换为字符仅仅是基本功能,它可以包含任何模板代码,如HTML代码:

    <todo-button>
      <!-- 添加Font Awesome图标 -->
      <i class="fas fa-plus"></i>
      Add todo
    </todo-button>
    

    甚至其他组件:

    <todo-button>
      <!-- 使用一个组件来加一个图标 -->
      <font-awesome-icon name="plus"></font-awesome-icon>
      Add todo
    </todo-button>
    

    如果组件模板没有任何插槽,提供任何内容都会被拒绝:

    <!-- todo-button 组件模板-->
    <button class="btn-primary">
      Create a new item
    </button>
    
    <todo-button>
      <!-- 下面文字不会被渲染 -->
      Add todo
    </todo-button>
    

    渲染域

    如果你想在组件内使用data,例如:

    <todo-button>
      Delete a {{ item.name }}
    </todo-button>
    

    插槽有权限访问有共同实例属性(如相同域)的其余模板。

    插槽没有权限访问<todo-button>域,下例中访问action将不会工作:

    <todo-button action="delete">
      Clicking here will {{ action }} an item
      <!--
      `action`将会提示未定义, 因为这个内容来自于`<todo-button>`, 不会定义在`<todo-button>` 组件内。
      -->
    </todo-button>
    

    记住这条规则:

    所有父模板都编译在父组件域,所有子模板都编译在子组件域。

    备用内容

    有些情形给插槽一个备用内容(如默认值)是比较有用的,当没有任何内容提供给插槽时,将会使用备用内容渲染。例如下面的<submit-button>组件:

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

    大部分时候我们都希望将button中的插槽渲染成Submit,将Submit设置为备用内容,我们可以将它放到<slot></slot>中间:

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

    当使用这个组件且不为插槽提供内容时:

    <submit-button></submit-button>
    

    会被渲染为:

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

    但如果我们提供了内容:

    <submit-button>
      Save
    </submit-button>
    

    渲染结果则为:

    <button type="submit">
      Save
    </button>
    

    具名插槽

    使用多个插槽是经常用到的,如下面的<base-layout>组件模板:

    <div class="container">
      <header>
        <!-- 想把头内容放在这里 -->
      </header>
      <main>
        <!-- 想把主要内容放在这里 -->
      </main>
      <footer>
        <!-- 想把脚内容放到这里 -->
      </footer>
    </div>
    

    这种情形,插槽有一个特殊的属性name,它可以为每个插槽定义一个唯一的ID,这样你就可以决定哪些内容渲染到哪个地方了:

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

    没有指定name的插槽的名字是default
    模板中使用具名插槽,我们需要使用v-slot指令,v-slot参数就是插槽的名字:

    <base-layout>
      <template v-slot:header>
        <h1> 这里可能是标题</h1>
      </template>
    
      <template v-slot:default>
        <p> 主要内容段落</p>
        <p>另一段内容</p>
      </template>
    
      <template v-slot:footer>
        <p>一些联系方式</p>
      </template>
    </base-layout>
    

    现在所有模板内的元素都被传递到相应的插槽里,最终渲染结果可能如下:

    <div class="container">
      <header>
        <h1>这里可能是标题</h1>
      </header>
      <main>
        <p> 主要内容段落</p>
        <p>另一段内容</p>
      </main>
      <footer>
        <p>一些联系方式</p>
      </footer>
    </div>
    

    注意:v-slot只能放在template内(有一种例外)

    作用域插槽

    有时,只有在子组件内部可以访问data内容是有用的。一个常用的例子就是使用组件渲染一个数组项,我们想定制数组项的渲染方式。
    例如我们有一个组件,里面包含一个todo-items列表:

    app.component('todo-list', {
      data() {
        return {
          items: ['Feed a cat', 'Buy milk']
        }
      },
      template: `
        <ul>
          <li v-for="(item, index) in items">
            {{ item }}
          </li>
        </ul>
      `
    })
    

    我们想把`{{ item }}`` 用一个插槽替换,以在父组件来定制:

    <todo-list>
      <i class="fas fa-check"></i>
      <span class="green">{{ item }}</span>
    </todo-list>
    

    但这不会工作,因为只有<todo-list>组件才能够访问item和父组件提供的插槽内容。
    要想让父组件提供的插槽内容能够使用item,我们可以添加<slot>标签并绑定成属性:

    <ul>
      <li v-for="( item, index ) in items">
        <slot :item="item"></slot>
      </li>
    </ul>
    

    一个插槽可以绑定多个属性:

    <ul>
      <li v-for="( item, index ) in items">
        <slot :item="item" :index="index" :another-attribute="anotherAttribute"></slot>
      </li>
    </ul>
    

    属性绑定到<slot>叫做slot props。现在在父组件域,我们可以使用v-slot绑定值来定义一个slot props名字:

    <todo-list>
      <template v-slot:default="slotProps">
        <i class="fas fa-check"></i>
        <span class="green">{{ slotProps.item }}</span>
      </template>
    </todo-list>
    


    在这个例子中,我们选择命名一个包含全部slot props的对象slotProps,你可以使用任何名称随你喜欢。

    单默认插槽缩写语法

    如上例,单个默认插槽,组件模板可以使用组件标签。这允许我们直接在组件上使用v-slot

    <todo-list v-slot:default="slotProps">
      <i class="fas fa-check"></i>
      <span class="green">{{ slotProps.item }}</span>
    </todo-list>
    

    可以更简短,就像没有指定内容分配给默认插槽,无参数的v-solt指向默认插槽:

    <todo-list v-slot="slotProps">
      <i class="fas fa-check"></i>
      <span class="green">{{ slotProps.item }}</span>
    </todo-list>
    

    注意默认插槽的缩写语法不能混合具名插槽,这会导致作用域名不唯一:

    <!--不合法, 会出现告警 -->
    <todo-list v-slot="slotProps">
      <i class="fas fa-check"></i>
      <span class="green">{{ slotProps.item }}</span>
    
      <template v-slot:other="otherSlotProps">
        slotProps is NOT available here
      </template>
    </todo-list>
    

    无论何时有多个插槽时,需要为所有插槽使用完整的模板语法:

    <todo-list>
      <template v-slot:default="slotProps">
        <i class="fas fa-check"></i>
        <span class="green">{{ slotProps.item }}</span>
      </template>
    
      <template v-slot:other="otherSlotProps">
        ...
      </template>
    </todo-list>
    

    解构插槽props

    内部原理是,作用域插槽是插槽内含有一个参数的函数实现:

    function (slotProps) {
      // ... slot content ...
    }
    

    这意味着v-slot的值可以接受任何合法的JavaScript表达式,函数定义可以出现在参数位置。所以你可以使用ES2005结构脱离特定的插槽props,像这样:

    <todo-list v-slot="{ item }">
      <i class="fas fa-check"></i>
      <span class="green">{{ item }}</span>
    </todo-list>
    

    这可以使用模板看起来更清爽,特别是插槽有多个props时。这也开启了其它可能性,比如重命名props,e.g. item转成todo

    <todo-list v-slot="{ item: todo }">
      <i class="fas fa-check"></i>
      <span class="green">{{ todo }}</span>
    </todo-list>
    

    你甚至可以定义一个备用,在有些场景下插槽prop未定义时。

    <todo-list v-slot="{ item = 'Placeholder' }">
      <i class="fas fa-check"></i>
      <span class="green">{{ item }}</span>
    </todo-list>
    

    动态具名插槽

    动态指令参数同样也适用于v-slot,允许你使用动态插槽名:

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

    具名插槽简写

    v-on(@),v-bind(:)一样,v-slot也可以简写,用#号替换参数前(v-slot:)的所有内容。例如,v-slot:header 可以重写为#header

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

    但是,和其他指令一样,缩写仅适用于提供了参数的情形。这意味着下面的例子是不合法的:

    <!-- 这会触发一个警告 -->
    
    <todo-list #="{ item }">
      <i class="fas fa-check"></i>
      <span class="green">{{ item }}</span>
    </todo-list>
    

    取而代之你必须为简写的插槽指定一个名字:

    <todo-list #default="{ item }">
      <i class="fas fa-check"></i>
      <span class="green">{{ item }}</span>
    </todo-list>
    
  • 相关阅读:
    开发DBA(APPLICATION DBA)的重要性
    SQL有外连接的时候注意过滤条件位置
    程序与bug
    Dalvik虚拟机进程和线程的创建过程分析
    Dalvik虚拟机简要介绍和学习计划
    Dalvik虚拟机的运行过程分析
    JRE和JDK的概念
    myeclipse6.0.1(内置了eclipse)安装及其配置
    JDK 环境变量如何设置
    jdk1.5和tomcat5.5免安装的环境配置
  • 原文地址:https://www.cnblogs.com/zhouyu629/p/14575846.html
Copyright © 2011-2022 走看看