vue插槽用法,vue插槽有什么作用
vue.js的灵魂是组件,组件的灵魂是槽。在插槽的帮助下,我们可以最大限度地重用组件。本文主要详细总结了slot的实现机制,在某些场景下是有用的。
目录
I .样本代码II。透过现象看本质。执行原则四。父组件编译阶段五、父组件生成和渲染方法六。父组件生成VNode VII。子组件状态初始化。子组件编译阶段IX。子组件生成和渲染方法十、使用技巧10.1。命名为插槽10.2。范围插槽
一、样例代码
!-子组件昏迷-
模板
div class=demo
插槽插槽
插槽名称=测试/插槽
slot name= scopedSlots test= demo /slot
/div
/模板
!-父组件-
昏迷
Span这是默认插槽/span
Template slot=test 这是一个命名的插槽/模板。
template slot= scoped slots slot-scope= scope 这是作用域插槽(旧版本){{scope.test}}/template
template v-slot:scoped slots= scope props slot-scope= scope 这是作用域插槽(新版本){{scopeProps.test}}/template
/昏迷
二、透过现象看本质
slot的作用是实现内容分发,这需要两个条件:
占位符
内容分发
组件内部定义的槽标签可以理解为一个占位符,父组件中的槽内容就是要分发的内容。槽处理的本质是把指定的内容放在指定的位置。不用说,从这篇文章中,我们可以了解到:
插槽的实现原理
如何在render方法中使用插槽
三、实现原理
vue组件的实例化顺序为:父组件状态初始化(数据、计算、观察.)-模板编译-生成render方法-实例化render watcher -调用render方法生成VNode -修补VNode,转换为真实DOM -实例化子组件-重复同样的过程-将子组件生成的真实DOM挂载到父组件生成的真实DOM上,挂载到页面上-移除旧节点。
从上述过程中,可以推断出:
1.父组件模板在子组件之前被解析,因此父组件将首先获得插槽模板内容。
2.子组件模板是后面解析的,所以当子组件调用render方法生成VNode时,可以通过某种手段获取槽的VNode节点。
3.作用域槽可以获得子组件中的变量,因此作用域槽的VNode生成是动态的,也就是说,需要实时地将其引入到子组件的作用域中。
整个槽加工阶段大致分为三个步骤:
编辑和翻译
生成渲染模板
生成VNode
以下面的代码为例简单概述一下槽操作的过程。
div id=应用程序
试验
模板槽=你好
123
/模板
/测试
/div
脚本
新Vue({
埃尔: #app ,
组件:{
测试:{
模板:“h1”
插槽名称=hello/slot
/h1
}
}
})
/脚本
四、父组件编译阶段
编译是将模板文件解析成AST语法树,AST语法树将插槽模板解析成如下数据结构:
{
标签:“测试”,
ScopedSlots: {//范围插槽
//slotName: ASTNode,
//.
}
儿童:[
{
标签:“模板”,
//.
parent: parentASTNode,
Children: [childASTNode ],//槽内容的子节点,即文本节点123。
SlotScope:未定义,//作用域插槽绑定值
SlotTarget: \hello\ ,//命名的插槽名称
SlotTargetDynamic: false //是动态绑定槽吗?
//.
}
]
}
五、父组件生成渲染方法
根据AST语法树,解析生成渲染方法字符串,父组件生成的最终结果如下所示。这个结构和我们直接写render方法是一致的,本质都是生成VNode,只不过_c或者h是这个的缩写。$createElement。
用(这个){
return _c(div ,{attrs:{id:app}},
[_c(测试,
[
_c(template ,{slot:hello},[_v(\n 123\n )])],2)
],
1)
}
六、父组件生成VNode
调用render方法生成vnode,vnode的具体格式如下:
{
标签:“div”,
父:未定义,
数据:{//存储VNode配置项
属性:{ id: #app }
},
context: componentContext,//组件作用域
榆树:未定义,//真实数字正射影像图元素
儿童:[
{
标签:“vue-组件-1-测试",
子级:未定义,//组件为页面最小组成单元,插槽内容放放到子组件中解析
父:未定义,
组件选项:{ //组件配置项
Ctor: VueComponentCtor,//组件构造方法
数据:{
挂钩:{
init: fn,//实例化组件调用方法
插入:fn,
预修补:fn,
销毁:fn
},
scopedSlots: { //作用域插槽配置项,用于生成作用域插槽虚拟节点
插槽名称:插槽【数学】函数
}
},
孩子:[ //组件插槽节点
标签:"模板",
propsData:未定义,//道具参数
侦听器:未定义,
数据:{
插槽:"你好"
},
孩子:[ VNode ],
父:未定义,
上下文:componentContext //父组件作用域
//.
]
}
}
],
//.
}
在某视频剪辑软件中,组件是页面结构的基本单元,从上述的虚拟节点中,我们也可以看出,VNode页面层级结构结束于试验组件,测试组件孩子们处理会在子组件初始化过程中处理。子组件构造方法组装与属性合并在vue-dev \ src \ core \ vdom \ create-component。js创建组件方法中,组件实例化调用入口是在vue-dev \ src \ core \ vdom \ patch。js创建组件方法中。
七、子组件状态初始化
实例化子组件时,会在initRender - resolveSlots方法中,将子组件插槽节点挂载到组件作用域伏特计中,挂载形式为虚拟机.$slots={slotName: [VNode]}形式。
八、子组件编译阶段
子组件在编译阶段,会将狭槽节点,编译成以下大西洋时间结构:
{
标签:“h1”,
父:未定义,
儿童:[
{
标签:"插槽",
插槽名称:“\”你好\ ,
//.
}
],
//.
}
九、子组件生成渲染方法
生成的渲染方法如下,其中_t为渲染槽方法的简写,从渲染槽方法,我们就可以直观的将插槽内容与插槽点联系在一起。
//渲染方法
用(这个){
return _c(h1 ,[ _t(hello) ],2)
}
//源码路径:vue-dev \ src \ core \ instance \ render-helpers \ render-slot。射流研究…
导出函数渲染槽(
名称:字符串,
回退:数组节点,
道具:对象,
bindObject:目标
):数组节点{
const scopedSlotFn=this .$scopedSlots[name]
让节点
if (scopedSlotFn) { //作用域槽
道具=道具 {}
if (bindObject) {
if (process.env.NODE_ENV!==生产!isObject(bindObject)) {
警告(
没有参数的插槽v型装订需要一个对象,
这
)
}
props=extend(extend({},bindObject),props)
}
//作用域插槽,获取插槽虚拟节点
nodes=scopedSlotFn(props) 回退
}否则{
//获取插槽普通插槽虚拟节点
节点=这个插槽[名称] 回退
}
const target=props props.slot
如果(目标){
归还这个. createElement(template ,{ slot: target },nodes)
}否则{
返回节点
}
}
作用域插槽与具名插槽区别
!-演示-
div id=应用程序
试验
模板slot=hello slot-scope=scope
{{scope.hello}}
/模板
/测试
/div
脚本
var vm=new Vue({
埃尔: #app ,
组件:{
测试:{
data () {
返回{
你好:"123"
}
},
模板:" h1 "
slot name= hello :hello= hello /slot
/h1
}
}
})
/脚本
作用域插槽与普通插槽相比,主要区别在于插槽内容可以获取到子组件作用域变量。由于需要注入子组件变量,相比于具名插槽,作用域插槽有以下几点不同:
组装呈现方法时,作用域插槽生成一个包含注入作用域的方法。与生成VNode的createElement相比,多了一层注入作用域方法包,决定了子组件生成VNode时生成VNode的作用域槽,而父组件创建VNode时生成命名槽。_u是resolveScopedSlots,用于将节点配置项转换为{scopedSlots: {slotName: fn}}形式。
用(这个){
return _c(div ,{
属性:{
id :应用程序
}
},[_c(test ,{
scopedSlots: _u([{
按键:“你好”,
fn:功能(范围){
return[_ v( \ n _ s(scope . hello) \ n )]
}
}])
})], 1)
}
当子组件被初始化时,命名的slot节点将被处理并挂载到组件$slots中,作用域slot将在renderSlot中被直接调用。
除此之外,其他流程大致相同。slot的机制不难理解,关键在于模板解析和渲染函数生成这两个步骤,过程很长,很难理解。
十、使用技巧
通过以上分析,我们可以大致了解槽加工流程。大部分工作使用模板来编写vue代码,但有时模板有一定的局限性,需要借助render方法放大vue的组件抽象能力。然后在render方法中,我们的槽的用法如下:
10.1、具名插槽
槽加工一般分为两部分:
父组件:父组件只需要写成模板编译的渲染方法,也就是指定槽名。
子组件:由于子组件直接取父组件初始化阶段生成的VNode,所以子组件只需要用父组件生成的VNode替换槽标签。当子组件被初始化时,它将在组件的$slots属性上挂载命名的slot。
div id=应用程序
!-测试-
!-模板槽=hello -
!- 123 -
!-/模板-
!-/测试-
/div
脚本
新Vue({
//El:“# app”,
渲染(createElement) {
返回createElement(test ,[
createElement(h3 ,{
插槽:“你好”,
domProps: {
内部文本:“123”
}
})
])
},
组件:{
测试:{
渲染(createElement) {
返回createElement(h1 ,[ this。$ slots . hello]);
}
//模板:“h1”
//插槽名称=hello/slot
///h1
}
}
}).$ mount(“# app”)
/脚本
10.2、作用域插槽
作用域插槽是灵活的,可以注入子组件状态。Scope slot render方法对于打包次要组件非常有用。以chestnut为例,在封装ElementUI表组件的基于JSON的数据时,作用域槽非常有用。
div id=应用程序
!-测试-
!-span slot= hello slot-scope= scope -
!- {{scope.hello}} -
!- /span -
!-/测试-
/div
脚本
新Vue({
//El:“# app”,
渲染(createElement) {
返回createElement(test ,{
scopedSlots:{
Hello: scope={//在父组件生成渲染方法中,最终转换的scope slot方法与此写法一致。
返回createElement(span ,{
domProps: {
innerText: scope.hello
}
})
}
}
})
},
组件:{
测试:{
data () {
返回{
你好:“123”
}
},
渲染(createElement) {
//函数由作用域槽的父组件传递,需要手动调用生成VNode。
设slotVnode=this。$ scopedslots . hello({ hello:this . hello })
返回createElement(h1 ,[slot node])
}
//模板:“h1”
// slot name= hello :hello= hello /slot
///h1
}
}
}).$ mount(“# app”)
/脚本
以上是Vue槽实现原理的详细内容。更多关于Vue slot的信息,请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。