vue插槽slot的理解与使用

释放双眼,带上耳机,听听看~!

一、个人理解及插槽的使用场景

刚开始看教程我的疑惑是为什么要用插槽,它的使用场景是什么,很多解释都是“父组件向子组件传递dom时会用到插槽”,这并不能很好的解决我的疑惑。既然你用了子组件,你为什么要给她传一些dom,直接去定义复用的子组件不就好了。后来想想觉得一个复用的组件在不同的地方只有些许变化,如果去重写子组件是很不明智的一件事,当然也可以将不同之处都写在子组件里,然后通过父组件传来的标识进行选择显示。其实质是对子组件的扩展,通过slot插槽向组件内部指定位置传递内容,即将<slot></slot>元素作为承载分发内容的出口;

二、用于理解的例子

目前还没接触到使用插槽解决实际问题很好的例子,只能这样去为了理解插槽而用,可能并没有很好的利用到插槽的好处。

 

在父组件定义想要传入子组件作为插槽的内容,App.vue


<
template> <div id=\"app\"> <div> <input type=\"text\" v-model=\"info\"> <button @click=\"handleClick\">添加</button> </div> <todolist v-for=\"item in list\" :key=\"item\" :message=\"msg\"> <template v-slot:item=\"itemProps\" > <!-- tips1:<span>即为插槽内容         tips2:item是插槽的名字,为具名插槽,可对应插入到子组件中具体的插槽位置 tips3:itemProps可以获取到子组件(即插槽 prop)传出来的状态(值),    插槽 prop 的对象命名为 itemProps,可任意命名,itemProps变量存在于 <template> 作用域中  --> <span :style=\"{fontSize: \'20px\', color: itemProps.checked ? \'red\': \'blue\'}\">{{item}}</span> </template> </todolist> </div> </template> <script> import todolist from \'./components/todolist.vue\'; export default { name: \'App\', components: { todolist }, data(){ return { msg: \'4-2-05\', info: \'\', list: [], } }, methods: { handleClick() { // 获取到input输入的东西,然后加入到数组中 this.list.push(this.info); this.info = \'\' } }, } </script> <style> </style>

在子组件利用<slot></slot>元素作为承载分发内容的出口,父组件的插槽内容将在其中显示,todolist.vue

<template>
  <div>
    {{message}}
  <li class=\"item\">
    <input type=\"checkbox\" v-model=\"checked\">
    <slot name=\"item\" v-bind=\"{checked}\" ></slot>
    <!--插槽内容能够访问子组件中才有的数据是很有用的,又因为父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的
    所以得想办法获取到子组件的数据。-->
    <!--给子组件绑定一个动态参数,checked作为一个 <slot> 元素的特性绑定上去,绑定在 <slot> 元素上的特性被称为插槽 prop-->
  </li>
  </div>
</template>

<script>
  export default {
    props: [\'item\',\'message\'],
    // 因为父组件在插槽内容里使用item, 即此句代码<span>{{item}}</span>
    // 相当于需要传递给子组件的内容,也就是通常的父子组件通信,所以在子组件需要通过props来获取
    data() {
      return {
        checked: false,
      }
    },
    created() {
      console.log(this.message);
    }
  }
</script>

<style scoped>
  .item {
    color: red;
  }
  li{
    list-style: none;
  }
</style>

三、具体知识点

1、具名插槽

上面的例子只使用了一个slot插槽,但有时我们在一个组件里可能会多处使用插槽,我们希望在不同的插槽处插入不同的内容,此时便需要进行区分,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义插槽的名字,在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用

 v-slot 指令,并以 v-slot 的参数的形式写出插槽的名称,使其一一对应。

 <slot name=\"header\"></slot>
 <slot name=\"content\"></slot>
 <slot ></slot>
//一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

2、作用域插槽

为了使父组件的插槽内容可以使用子组件的数据,可以在 <slot> 元素上绑定想要传递的数据,此特性被称为插槽 prop。同时在父级作用域中,给 v-slot 带一个值来定义我们提供的插槽 prop 的名字,便可获取到。但此内容只在 <template>作用域内可用。

四、自 2.6.0 起有所更新的语法变化

1、带有slot特性的具名插槽

2、带有slot-scope特性的作用域插槽

五、突发奇想的调换

因为看到一个别人写的关于slot的帖子,他应该是写错了插槽在子父组件的内容,这也就相当于从子组件传一个插槽内容给父组件。仔细想想这思路有问题,既然都引用了子组件,父组件便可以访问到子组件的所有内容,现在却非要通过插槽来传递,多此一举。 然后我就试了一下将插槽内容卸载子组件里,果然出现了报错,如下:

  - <template v-slot> can only appear at the root level inside the receiving the component(slot的只能出现在接受组件的根级别) 也就是只能在父组件使用。  

人已赞赏
随笔日记

详解docker中容器devicemapper设备的挂载流程

2020-11-9 4:09:27

随笔日记

自定义Appium

2020-11-9 4:09:29

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索