Vue v-slot插槽的更新使用

一、前言

v-slot指令自 Vue 2.6.0 起被引入,提供更好的支持 slotslot-scope 特性的 API 替代方案。v-slot 完整的由来参见这份 RFC
在接下来所有的 2.x 版本中 slotslot-scope 特性仍会被支持,但已经被官方废弃且不会出现在 Vue 3 中

因此以下原本的写法在未来将会被废弃

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

二、插槽的分类

  1. 匿名插槽(或默认插槽): 只能有一个
  2. 具名插槽: slot使用name命名
  3. 作用域插槽: 父组件用于接收子组件内数据

Foo.vue 父组件

<template>
  <div class="tmpl">
    <h1>父子组件与兄弟组件通信</h1>
    <h3>子组件通信为 {{childMsg}}</h3>
    <my-bar :message="parentMsg" v-on:showMsg="getMsg">
       <template #default>
          <ul>
            <li>匿名插槽内容11</li>
            <li>匿名插槽内容22</li>
            <li>匿名插槽内容33</li>
          </ul>
        </template>
    </my-bar>
    <my-baz>
        <template v-slot:header="items">
          <p>具名插槽 header</p>
          <p>作用域插槽: {{items.user.name}}</p>
        </template>
        <template v-slot:default>
          <p>匿名插槽内容</p>
        </template>
        <template v-slot:footer>
          <p>具名插槽 footer</p>
        </template>
    </my-baz>
  </div>
</template>

<script>
import MyBar from '@/components/Foo/Bar.vue'
import MyBaz from '@/components/Foo/Baz.vue'
export default {
  name: 'Foo',
  components: {
    MyBar, MyBaz
  },
  data () {
    return {
      parentMsg: 'abc123',
      childMsg: ''
    }
  },
  methods: {
    getMsg: function (data) {
      this.childMsg = data
    }
  }
}
</script>

<style scoped>
h1 {
  font-weight: normal;
}
</style>

匿名插槽 Bar.vue 子组件

<template>
  <div class="tmpl">
    <h1>父组件传值为 {{message}}</h1>
    <input type="text" placeholder="请输入子组件内容" v-model="param">
    <button @click="sendParam">通信父组件</button>
    <slot></slot>
  </div>
</template>

<script>
import EventHandler from '@/assets/js/EventHandler.js'
export default {
  name: 'Bar',
  props: {
    message: {
      type: String,
      default: '默认为空'
    }
  },
  data () {
    return {
      param: ''
    }
  },
  methods: {
    sendParam: function () {
      var param = this.param
      this.$emit('showMsg', param)
      EventHandler.$emit('showMsg', param)
    }
  }
}
</script>

<style scoped>
h1 {
  font-weight: normal;
}
.tmpl {
  border: 1px solid #333;
  padding: 30px;
}
</style>

具名&作用域插槽 Baz.vue 子组件

<template>
  <div class="tmpl">
    <h1>Baz</h1>
    <h1>兄弟组件通信为{{brotherMsg}}</h1>
    <slot name="header" :user="user">
      {{ user.name }}
    </slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script>
import EventHandler from '@/assets/js/EventHandler.js'
export default {
  name: 'Baz',
  mounted () {
    var that = this
    EventHandler.$on('showMsg', function (data) {
      that.brotherMsg = data
    })
  },
  data () {
    return {
      brotherMsg: '',
      user: {
        name: '李四',
        age: 15
      }
    }
  }
}
</script>

<style scoped>
h1 {
  font-weight: normal;
}
.tmpl {
  border: 1px solid #333;
  padding: 30px;
  margin-top: 30px;
}
</style>
插槽示例

三、简写技巧

具名插槽的缩写

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header

<template v-slot:footer>
  <p>具名插槽 footer</p>
</template>
<!-- 等价于 -->
<template #footer>
  <p>具名插槽 footer</p>
</template>
...
...
<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容