浅析VUE里的插槽

一、插槽

  插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示、以及怎样显示由父组件来决定。实际上,一个slot最核心的两个问题这里就点出来了,是显示不显示怎样显示

  Vue中使用slot的一个重要原因,就是为了达到组件的复用,子组件的某些元素直接由调用他的父组件决定。

  由于插槽是一块模板,所以,对于任何一个组件,从模板种类的角度来分,其实都可以分为非插槽模板插槽模板两大类。

  非插槽模板指的是html模板,指的是‘div、span、ul、table’这些,非插槽模板的显示与隐藏以及怎样显示由插件自身控制;

  插槽模板是slot,它是一个空壳子,因为它显示与隐藏以及最后用什么样的html模板显示由父组件控制。但是插槽显示的位置确由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板将来就显示在哪块

1、单个插槽 | 默认插槽 | 匿名插槽

  首先是单个插槽,单个插槽是vue的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽,因为它不用设置name属性。

  单个插槽可以放置在组件的任意位置,但是就像它的名字一样,一个组件中只能有一个该类插槽。相对应的,具名插槽就可以有很多个,只要名字(name属性)不同就可以了。

  直接拿官网的例子来展示。

// 子组件 <navigation-link>
<a v-bind:href="url" class="nav-link">
  <slot></slot>
</a>

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

// 最终会渲染为
<a v-bind:href="url" class="nav-link">
  <!-- 添加一个 Font Awesome 图标 -->
  <span class="fa fa-user"></span>
  Your Profile
</a>

2、具名插槽

  具名插槽其实就是指定了名字的插槽,代码会被渲染到指定的位置。具名插槽可以在一个组件中出现N次,出现在不同的位置。

  继续上面的例子:子组件指定具名插槽和默认插槽,则父节点中slot的元素会按位置渲染。

// 子组件
<template>
  <a v-bind:href="url" class="nav-link">
    <slot name="up"></slot>
    <p>我是分割线</p>
    <slot></slot>
  </a>
</template>
<script>
export default {
  props: {
    url: {
      type: String
    }
  },
  data() {
   return { specData: 我的内容来自子节点};
  }
};
</script>
// 父组件
<template>
  <navigation-link url="/profile">
    <!-- 添加一个 Font Awesome 图标 -->
    <span class="fa fa-user"></span>
    Your Profile
    <span>{{specData}}</span>

    <p slot="up">
      <span>我是up</span>
    </p>

  </navigation-link>
</template>

<script>
import navigationLink from ./child.vue;

export default {
  created(){
  },
  data() {
    return { specData: 我必须由父节点来传递,我的内容来自父节点};
  },
  components: { navigationLink },
}
</script>
// 最终渲染为:
<a href="/profile" class="nav-link">
  <p>
    <span>我是up</span>
  </p>
  <p>我是分割线</p>
  <span class="fa fa-user"></span>
  Your Profile
  <span>我必须由父节点来传递,我的内容来自父节点</span>
</a>

  可见,多了一个name,其实我们就可以定制显示的位置,和默认的匿名插槽混用也不会有影响,这个在需要渲染多个插槽时十分有效。

3、Vue的编译作用域

  在提到作用域插槽之前,必须确保已经了解Vue的编译作用域。

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

  其实仔细看上面的例子,父子组件都赋值了specData,但是渲染的是父组件的内容便了解了,其实写错了也没事,Vue会给你及时提示的。

4、作用域插槽 | 带数据的插槽

  最后,就是我们的作用域插槽,这个稍微难理解一点,官方叫它作用域插槽,实际上,对比前面两种插槽,我们可以叫它带数据的插槽。

  作用域插槽就是子组件通过给slot上绑定参数,达到给父组件传递进来的模板赋值的效果

  我们前面说了,插槽最后显示不显示是看父组件有没有在child下面写模板,像下面那样。

<child>
   html模板
</child>

  写了,插槽就总得在浏览器上显示点东西,东西就是html该有的模样,没写,插槽就是空壳子,啥都没有。

  我们再来对比,作用域插槽和单个插槽和具名插槽的区别,因为单个插槽和具名插槽不绑定数据,所以父组件是提供的模板要既包括样式又包括内容和数据,而作用域插槽,父组件只需要提供一套样式(在确实用作用域插槽绑定的数据的前提下),数据就是使用子组件传递过来的数据。

// 父组件
<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <!--第一次使用:直接显示数据-->
    <child>
      <template slot-scope="user">
       {{user.data}}
      </template>

    </child>

    <!--第二次使用:不使用其提供的数据, 作用域插槽退变成匿名插槽-->
    <child>
      我就是模板
    </child>
  </div>
</template>

// 子组件
<template>
  <div class="child">
    <h3>这里是子组件</h3>
    // 作用域插槽
    <slot :data="data"></slot>
  </div>
</template>
export default {
    data: function(){
      return {
        data: [‘zhangsan‘,‘lisi‘,‘wanwu‘,‘zhaoliu‘,‘tianqi‘,‘xiaoba‘]
      }
    }
}

  其中slot-scope=user其实是一个对象,里面包含的属性是子组件中传给<slot>的prop,在上面的例子中就是user=={data: [‘zhangsan‘,‘lisi‘,‘wanwu‘,‘zhaoliu‘,‘tianqi‘,‘xiaoba‘]},所以可以通过user.data获取到子组件的data。

 

浅析VUE里的插槽

上一篇:pcl之自定义pointT类型


下一篇:Sleuth简介