vue在2.6.0中,为具名插槽和作用域插槽引入了新的语法(v-slot指令),之前的slot和slot-scope这两个已经被废弃,但未移除文档。
最近搜了搜百度上边关于插槽相关知识点,内容有点老旧,大多都是2.6.0之前版本的slot,有一些新版的要不就是全篇一堆代码,要不就是跟官方文档一模一样!!!
闲来之余,结合官方文档,详细解读下新版插槽slot:
目录
1、插槽内容
2、插槽默认值
3、具名插槽
4、作用域插槽
5、v-slot的特殊情况
6、具名插槽简写
7、动态插槽名
8、(补充)插槽的解构赋值
通俗来讲,slot作用就是替换自定义标签中的内容,官方称(your profile),slot插槽内可以包含任何模板代码。
吕星辰
上边的代码,当组件渲染的时候,slot将会被替换成组件中的p标签。组件中也可以包含其它组件。
slot插槽默认值:指的是当组件中没有内容,默认值才会被渲染:
上边代码,子组件sonComponent里边没有任何内容,这时,子组件模板中的slot插槽中的内容会被渲染出来。
(注意:当组件中有内容时,slot插槽中的默认内容会被覆盖。)
所谓的具名插槽就是有具体名字的插槽,因开头已经说过,2.6.0版本slot特性已经被废弃,这里就不解释旧版本中的slot了,vue中加了一个新指令v-slot,代替原来的slot;
具体用法:
当我们需要多个插槽,来规定组件中不同的内容在不同位置时,可以用具名插槽:
我是网页底部
我是网页标题
我是网页内容
渲染:
上边代码:子组件sonComponent中有三段代码,这里故意打乱他们的顺序,我想把标题放到网页顶部,内容放到网页中间,底部对应放在网页底部,你只需要在插槽slot上定义特性name,值是自定义的(尽量语义化),与上边template的v-slot绑定的值对应即可。这时你可以定义多个slot插槽,组件中的内容会根据slot顺序依次插入进去,即使模板中的顺序颠倒!任何没有被包裹在带有v-slot指令的template中的内容,都会视为默认插槽内容(通俗点说就是:不被< template v-slot >包裹的内容,都会插入到匿名插槽内);上边组件中p标签没有被template包裹,当组件渲染会被插入到第二个slot匿名插槽中。
******************** 注意:v-slot只能添加在一个template标签上,当然有一种情况除外,下边介绍 **********************
看到文档中作用域插槽时,小编看了半天,一直很蒙B(黑人问号脸),后来自己理解+实践才明白怎么回事。。。
其实也很简单嘛,通俗点说就是,在父组件编译的内容,只能访问到父组件的数据,访问不到子组件的数据。
举个例子:
{{alias}}
页面渲染:
上边代码:在父组件和子组件中我们分别定义了alias数据,结果渲染的是父组件中的alias数据。。。
1、h1标签的内容访问不到子组件的数据,只能访问父组件数据,原因在于:它是在父级模板中编译的。
在父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子模板作用域中编译的。(这两句话可以认真的读十遍!!!)
2、通常情况下,需求是:让插槽可以访问到子组件中的data数据,
我们可以在slot上边绑定一个自定义特性,值是子组件data对象中的数据:
{{slotProp}}
页面渲染:
上边代码:
父组件(根实例)我就不写了。
我们在slot上边绑定了一个自定义特性aliasName , 值是alias(就是子组件data中的数据),在官方文档中讲到,绑定在slot上的特性被称为插槽 prop。在父级作用域中,我们给template上的v-slot加上一个值,这个值用来定义插槽prop的名字。(官方文档这句话看似简单,但是你看了会很蒙,因为它没有列出一个完整的例子来;我用大白话给它翻一下:首先给指令v-slot加上的这个值(slotProp),实际上就是给插槽prop对象起一个名字而已,它是一个对象(看上边页面渲染);这个对象的属性正是绑定在插槽slot上的自定义特性aliasName,值是:子组件data对象中的数据,看到这,相信你会明白官方的那个例子,为什么会用点的方式来取值了吧!!!)
当插槽提供了多个prop的时候:
eg:
{{aliasName}}
页面渲染:
上边代码:不难看出,当出现多个prop时,vue会把所有数据放在一个对象里。
当只有默认插槽时(只有匿名插槽,没有具名插槽),组件的标签才可以被当做插槽的模板来使用。这样我们可以把v-slot直接用在组件上。
eg:
{{slotProp.aliasName}}
上边的写法,还可以去掉:default
{{slotProp.aliasName}}
如果出现多个插槽,务必为所有的插槽使用完整的基于语法。。。
跟v-bind一样,具名插槽的 v-slot : 也可以简写成 #
(也就是把v-slot和后边的冒号去掉)
{{aliasName}}
当只有默认值插槽时,如果你希望简写,必须以明确插槽名的方式书写,如下:
//去掉v-slot和冒号(匿名插槽默认带有一个default)
{{slotProp.aliasName}}
下边写法是无效的!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//去掉v-slot和冒号
{{slotProp.aliasName}}
所谓的动态插槽名就是v-slot:后边的名字可以是动态的;
eg:
//dynamicName是一个动态插槽名
{{aliasName}}
补充:最近看到有朋友留言说关于动态插槽名有点不明白,今天抽出点空在详细说下,首先要明白的是:动态插槽名值是在父组件定义的(子组件定义是取不到的,因为作用域问题,上边已讲过),父组件可以定义不同的值来渲染不同的内容:
举个例子:
{{getName}}
渲染结果:
上边代码,在父组件中定义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正是上文所说的,绑定在插槽slot上的特性就是插槽prop,那怎么解构赋值呢?先来看一个小例子:
{{myAlias}}
上边代码,我们在slot插槽上绑定了一个特性myAlias,上边v-slot的值是采用对象解构赋值的形式,获取对象,这里要解释下,为什么获取的是对象呢?
当插槽slot上边 有prop时(也就是有绑定特性时),数据会被放到一个对象里边,上边是 { myAlias : " lxc " },基于对象解构赋值,属性名要对应,其次要放到一个对象里;所以v-slot : slotname 后边的值 {myAlias} 对应的是 { myAlias : " lxc " } 。。。
当然有多个插槽prop时,解构赋值是最好的选择:
{{myAlias}}-----{{age}}----{{hegiht}}
页面渲染: