vue插槽(2.6.0最新版)

vue在2.6.0中,为具名插槽和作用域插槽引入了新的语法(v-slot指令),之前的slot和slot-scope这两个已经被废弃,但未移除文档。

最近搜了搜百度上边关于插槽相关知识点,内容有点老旧,大多都是2.6.0之前版本的slot,有一些新版的要不就是全篇一堆代码,要不就是跟官方文档一模一样!!!

闲来之余,结合官方文档,详细解读下新版插槽slot:

以下我从8个方面介绍插槽的用法:(之前遗漏掉了插槽解构赋值,今天补上!)

目录

1、插槽内容

2、插槽默认值

3、具名插槽

4、作用域插槽

5、v-slot的特殊情况

6、具名插槽简写

7、动态插槽名

8、(补充)插槽的解构赋值

 

插槽内容:

通俗来讲,slot作用就是替换自定义标签中的内容,官方称(your profile),slot插槽内可以包含任何模板代码。

<div id="app">
    <son-component>
        <p>吕星辰</p>
    </son-component>
</div>
<script>
 var sonComponent = {
    template:`
        <div>
            <slot></slot>
        </div>
    `
 }
</script>

上边的代码,当组件渲染的时候,slot将会被替换成组件中的p标签。组件中也可以包含其它组件。

 

插槽默认值:

slot插槽默认值:指的是当组件中没有内容,默认值才会被渲染:

<div id="app">
   <son-component>
   </son-component>
</div>

<script>
var sonComponent = {
   template:`
    <div>
       <slot>我是插槽的默认值</slot>
    </div>
    `
}
</script>

上边代码,子组件sonComponent里边没有任何内容,这时,子组件模板中的slot插槽中的内容会被渲染出来。

(注意:当组件中有内容时,slot插槽中的默认内容会被覆盖。)

 

具名插槽:

所谓的具名插槽就是有具体名字的插槽,因开头已经说过,2.6.0版本slot特性已经被废弃,这里就不解释旧版本中的slot了,vue中加了一个新指令v-slot,代替原来的slot;

具体用法:

当我们需要多个插槽,来规定组件中不同的内容在不同位置时,可以用具名插槽:

<div id="app">
    <son-component>
        <template v-slot:footer>
            <h2>我是网页底部</h2>
        </template>

        <template v-slot:title>
            <h1>我是网页标题</h1>
        </template>

        <p>我是网页内容</p>
    </son-component>
</div>
<script>
 var sonComponent = {
    template:`
        <div>
            <slot name="title"></slot>
            <slot></slot>
            <slot name="footer"></slot>
        </div>
    `
 }
</script>

渲染:

           上边代码:子组件sonComponent中有三段代码,这里故意打乱他们的顺序,我想把标题放到网页顶部,内容放到网页中间,底部对应放在网页底部,你只需要在插槽slot上定义特性name值是自定义的(尽量语义化)与上边template的v-slot绑定的值对应即可这时你可以定义多个slot插槽组件中的内容会根据slot顺序依次插入进去即使模板中的顺序颠倒任何没有被包裹在带有v-slot指令的template中的内容都会视为默认插槽内容(通俗点说就是:不被< template v-slot >包裹的内容,都会插入到匿名插槽内);上边组件中p标签没有被template包裹,当组件渲染会被插入到第二个slot匿名插槽中。

     ******************** 注意:v-slot只能添加在一个template标签上,当然有一种情况除外,下边介绍 **********************

例:

在移动端ui框架vant中,有好多基于具名插槽的例子,例如:下边loading插槽,就是一个具名插槽!

作用域插槽:

看到文档中作用域插槽时,小编看了半天,一直很蒙B(黑人问号脸),后来自己理解+实践才明白怎么回事。。。

其实也很简单嘛,通俗点说就是,在父组件编译的内容,只能访问到父组件的数据访问不到子组件的数据。

举个例子:

<div id="app">
    <son-component>
        <h1>{{alias}}</h1>
    </son-component>
</div>
<script>
//子组件
  var sonComponent = {
    template:`
        <div>
            <slot>插槽的默认内容</slot>
        </div>`,
    data(){
        return {
            alias:"我是子组件"
        }
    }
  }
//根实例(父组件)
  var vm = new Vue({
    el: "#app",
    data: {
        alias:"我是父组件"
    },
    components:{
        sonComponent
    }
  })
</script>

页面渲染:

上边代码:在父组件和子组件中我们分别定义了alias数据,结果渲染的是父组件中的alias数据。。。

1、h1标签的内容访问不到子组件的数据,只能访问父组件数据,原因在于:它是在父级模板中编译的。

在父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子模板作用域中编译的。(这两句话可以认真的读十遍!!!)

2、通常情况下,需求是:让插槽可以访问到子组件中的data数据,

    我们可以在slot上边绑定一个自定义特性,值是子组件data对象中的数据:

<div id="app">
    <son-component>
        <template v-slot:title="slotProp">
            <h1>{{slotProp}}</h1>
        </template>
    </son-component>
</div>

<script>
  var sonComponent = {
    template:`
        <div>
            //绑定属性aliasName,alias是子组件data对象中的数据
            <slot name="title" :aliasName="alias">插槽的默认内容</slot>
        </div>
    `,
    data(){
        return {
            alias:"我是子组件"
        }
    }
  }
</script>

页面渲染:

上边代码:

父组件(根实例)我就不写了。

我们在slot上边绑定了一个自定义特性aliasName , 值是alias(就是子组件data中的数据),在官方文档中讲到,绑定在slot上的特性被称为插槽 prop。在父级作用域中,我们给template上的v-slot加上一个值,这个值用来定义插槽prop的名字。(官方文档这句话看似简单,但是你看了会很蒙,因为它没有列出一个完整的例子来;我用大白话给它翻一下:首先给指令v-slot加上的这个值(slotProp),实际上就是给插槽prop对象起一个名字而已,它是一个对象(看上边页面渲染);这个对象的属性正是绑定在插槽slot上的自定义特性aliasName,值是:子组件data对象中的数据,看到这,相信你会明白官方的那个例子,为什么会用点的方式来取值了吧!!!)

 

当插槽提供了多个prop的时候:

eg:

<div id="app">
    <son-component>
        <template v-slot:self="aliasName">
            <h1>{{aliasName}}</h1>
        </template>
    </son-component>
</div>

<script>
 var sonComponent = {
    template:`
        <div>
            <slot name="self" :alias="alias" :age="age">插槽的默认内容</slot>
        </div>
    `,
    data(){
        return {
            alias:"lxc",
            age:20
        }
    }
 }
</script>

页面渲染:

上边代码:不难看出,当出现多个prop时,vue会把所有数据放在一个对象里。

 

v-slot的特殊情况

当只有默认插槽时(只有匿名插槽,没有具名插槽),组件的标签才可以被当做插槽的模板来使用。这样我们可以把v-slot直接用在组件上。

eg:

<div id="app">
    <!-- 只有默认插槽时, 即不带name的<slot>,会带有一个隐含的名字“default”-->
    <son-component v-slot:default="slotProp">
       <h1>{{slotProp.aliasName}}</h1>
    </son-component>
</div>
<script>
 var sonComponent = {
    template:`
        <div>
            <slot :aliasName="alias">插槽的默认内容</slot>
        </div>
    `,
    data(){
        return {
            alias:"我是子组件"
        }
    }
 }
</script>

上边的写法,还可以去掉:default

<div id="app">
    <son-component v-slot="slotProp">
       <h1>{{slotProp.aliasName}}</h1>
    </son-component>
</div>

如果出现多个插槽,务必为所有的插槽使用完整的基于<template v-slot:xxx>语法。。。

 

具名插槽的简写

跟v-bind一样,具名插槽的 v-slot :  也可以简写成 #  

(也就是把v-slot和后边的冒号去掉)

<div id="app">
    <son-component>
        <template #self="aliasName">
            <h1>{{aliasName}}</h1>
        </template>
    </son-component>
</div>

当只有默认值插槽时,如果你希望简写,必须以明确插槽名的方式书写,如下:

<div id="app">
    //去掉v-slot和冒号(匿名插槽默认带有一个default)
    <son-component #default="slotProp">
       <h1>{{slotProp.aliasName}}</h1>
    </son-component>
</div>

下边写法是无效的!!!!!!!!!!!!!!!!!!!!!!!!!!!!

<div id="app">
    //去掉v-slot和冒号
    <son-component #="slotProp">
       <h1>{{slotProp.aliasName}}</h1>
    </son-component>
</div>

 

动态插槽名

所谓的动态插槽名就是v-slot:后边的名字可以是动态的;

eg:

<son-component>
    //dynamicName是一个动态插槽名
  <template v-slot:[dynamicName]="aliasName">
     <h1>{{aliasName}}</h1>
  </template>
</son-component>

补充:最近看到有朋友留言说关于动态插槽名有点不明白,今天抽出点空在详细说下,首先要明白的是:动态插槽名值是在父组件定义的(子组件定义是取不到的,因为作用域问题,上边已讲过),父组件可以定义不同的值来渲染不同的内容:

举个例子:

<div id="app">
    <son>
        <!-- 下边alias是一个动态值,根据父组件中的不同值,来渲染不同的内容,getName则是对象的结构赋值 -->
        <template v-slot:[alias]={getName}>
            <h1>{{getName}}</h1>
        </template>
    </son>
</div>
<script>
//子组件
    let son = {
        template:`
            <div>
              <slot name="header" :getName="showName_1">header_默认内容</slot><br>
              <slot name="content" :getName="showName_2">content_默认内容</slot><br>
              <slot name="footer" :getName="showName_3">footer_默认内容</slot>                    
            </div>`,
        data(){
            return{
              showName_1:'my name is header',
              showName_2:'my name is content',
              showName_3:'my name is footer',
            }
        }
    }
//父组件
    let vm = new Vue({
        el:"#app",
        data:{
            alias:'header'
        },
        components:{
            son
        }
    })
</script>

渲染结果:

上边代码,在父组件中定义alias值为header,它会去子组件中找与之对应的插槽prop名字,渲染到页面;当我们把父组件中alias值修改为content :

··· ···

//父组件
    let vm = new Vue({
        el:"#app",
        data:{
            alias:'content'
        },
        components:{
            son
        }
    })

渲染结果如下:

把父组件中alias值修改为footer:

··· ···

//父组件
    let vm = new Vue({
        el:"#app",
        data:{
            alias:'footer'
        },
        components:{
            son
        }
    })

渲染结果如下:

以上就是动态插槽名的用法,至于如何用在项目中去,还是要靠自己慢慢探索!!!

 

(补充!!!)解构插槽prop

想必大家都能猜出来是什么意思,就是解构插槽的prop,prop正是上文所说的,绑定在插槽slot上的特性就是插槽prop,那怎么解构赋值呢?先来看一个小例子:

<div id="app">
  <son-component>
	<template v-slot:slotname="{myAlias}">
	   {{myAlias}}
	</template>
  </son-component>
</div>
<script>
let sonComponent = {
  template: `<div>
	          <slot name="slotname" :myAlias=alias>默认值</slot>
		</div>`,
  data(){
	return {
	   alias:"lxc"
	}
  },

};
</script>

上边代码,我们在slot插槽上绑定了一个特性myAlias,上边v-slot的值是采用对象解构赋值的形式,获取对象,这里要解释下,为什么获取的是对象呢?

当插槽slot上边 有prop时(也就是有绑定特性时),数据会被放到一个对象里边,上边是 { myAlias : " lxc " },基于对象解构赋值,属性名要对应,其次要放到一个对象里;所以v-slot : slotname 后边的值  {myAlias} 对应的是  { myAlias : " lxc " } 。。。

当然有多个插槽prop时,解构赋值是最好的选择:

<div id="app">
  <son-component>
    <template v-slot:slotname="{myAlias,age,hegiht}">
	  {{myAlias}}-----{{age}}----{{hegiht}}
    </template>
  </son-component>
</div>

<script>
let sonComponent = {
   template: `
      <div>
        <slot 
           name="slotname" 
           :myAlias=alias
           :age=age
           :height=height
           >
              默认值
         </slot>
       </div>`,
	data(){
	   return {
		  alias:"lxc",
		  age:20,
		  height:170
		}
    }
}
</script>

页面渲染:

 

  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值