Vue.slot의 원리에 대해 이야기하고 슬롯이 어떻게 구현되는지 살펴보겠습니다!
이 글은 Vue에 대한 유용한 정보를 공유하고, 여러분이 알지 못하는 Vue.slot의 원리에 대해 이야기해 보는 것이 모든 사람에게 도움이 되기를 바랍니다.
일상적인 비즈니스 개발이든 기본 구성 요소의 캡슐화이든
슬롯
은 프로그래밍 구현에 많은 편의를 제공하기 때문에 우리 시야에 자주 등장한다고 믿습니다. 이름이 지정된 슬롯이든 스코프 슬롯의 다양한 용도 등슬롯
의 사용법은 모두가 잘 알고 있을 것입니다.slot
및slot-scope
의 하위 레이어가 어떻게 구현되는지 알고 계시나요?插槽slot
都是经常出现在我们的视野的,因为它为我们编程实现提供了很多便捷。可能大家对于slot
的用法已经烂透于心了,不管是 具名插槽 ,还是 作用域插槽 各种用法等等...那大?们又知不知道slot
、slot-scope
底层是怎么实现的呢?
通俗易懂、10分钟就能带走的 Vue.slot
的干货源码实现分析!!!跟着笔者一起探究下 Vue(v2.6.14)
中的插槽 slot
是怎么实现的!!本文主要会分两块进行讲解:
普通插槽(具名插槽、默认插槽)
作用域插槽
这篇文章没有晦涩的源码解析,直接用大白话讲解,所以不管大家对Vue源码的熟悉程度,都是能看明白的。通过现场调试,让你看清 Vue
的 slot
是如何实现的。let's go go go!(学习视频分享:vue视频教程)
一、回顾 slot
用法
先跟大家一起回顾下插槽的大概用法。这里的 slot
用法使用 2.6.0 的新标准(本文也会带一下 v2.5
的写法的跟 v2.6
在源码实现上有什么区别!)。
如果想详细了解用法可以去官网详细看看Vue 的 slot 文档
https://cn.vuejs.org/v2/guide/components-slots.html
1. 默认插槽
<!-- 子组件 --> <template> <div class="wrapper"> <!-- 默认插槽 --> <div class="main"> <slot></slot> </div> </template> <!-- 父组件 --> <my-slot> <template> <h1 id="默认插槽">默认插槽</h1> </template> </my-slot>
页面展示效果如图:
2. 具名插槽
接着上述的案例,添加具名插槽 header
,代码如下:
<!-- 子组件 --> <template> <div class="wrapper"> <!-- header 具名插槽 --> <header class="header"> <slot name="header"></slot> </header> <!-- 默认插槽 --> <div class="main"> <slot></slot> </div> </template> <!-- 父组件 --> <my-slot> <template v-slot:header> <h1 id="header-nbsp-具名插槽">header 具名插槽</h1> </template> <template> <h1 id="默认插槽">默认插槽</h1> </template> </my-slot>
如上代码块可以发现:
子组件中的
slot标签
带上了一个名为name
的属性,值为header
父组件中的
template标签
带上了v-slot
的属性,值为header
页面展示效果如图:
3. 作用域插槽(slot-scope)
再接着上述案例,添加作用域插槽 footer
,代码如下
<!-- 子组件 --> <template> <div class="wrapper"> <!-- header 具名插槽 --> <header class="header"> <slot name="header"></slot> </header> <!-- 默认插槽 --> <div class="main"> <slot></slot> </div> <!-- footer 具名 + 作用域插槽 --> <footer class="footer"> <slot name="footer" :footerInfo="footerInfo"></slot> </footer> </div> </template> <script> export default { name: "mySlot", data () { return { footerInfo: { text: '这是 子组件 footer插槽 的作用域数据' } } } } </script> <!-- 父组件 --> <my-slot> <template v-slot:header> <h1 id="header-nbsp-具名插槽">header 具名插槽</h1> </template> <template> <h1 id="默认插槽">默认插槽</h1> </template> <template v-slot:footer="slotProps"> <h1 id="footer-nbsp-具名-nbsp-nbsp-作用域插槽">footer 具名 + 作用域插槽</h1> <p>{{ slotProps.footerInfo.text }}</p> </template> </my-slot>
如上代码块可以发现:
子组件中的
slot标签
除了有name=footer
的属性,还有一个:footerInfo="footerInfo"
的属性(作用就是传递子组件数据)父组件中的
template标签
不仅有v-slot:footer
,并且还有一个赋值操作="slotProps"
,在模版的双括号语法中,直接通过slotProps
访问到 子组件的footerInfo
页面展示效果如图:
好了,简单回顾完用法后,笔者在这里先提三个问题:
- 普通插槽、 作用域插槽 的 vNode 是在哪个环节生成的,render 父组件时还是子组件时?
- 作用域插槽 为什么能在父组件访问到子组件的数据?
- 普通插槽 跟 作用域插槽 在实现上有区别吗?
我们带着疑问接着往下看!
二、不同slot
的编译区别
我们根据上述最终的案例代码,执行一下打包命令,看看 Vue 在编译模板的时候,是怎么处理我们的 slot
的!事不宜迟,赶紧 build
一哈~(偷偷告诉大?,Vue
处理 作用域插槽 跟 普通插槽 的差异就是从编译开始的,也就是 render函数 会有所不同)
这里笔者顺便使用 v2.5
的具名插槽写法给大?参照一下(对具名插槽header做改写,使用 slot="header"
的写法),大家可以看下 v2.6
、v2.5
Vue(v2.6.14)
의 슬롯 slot
이 어떻게 구현되는지 살펴보세요! ! 이 글에서는 주로 두 부분으로 나누어 설명합니다: 🎜- 🎜일반 슬롯(명명된 슬롯, 기본 슬롯)🎜
- 🎜 스코프 슬롯 🎜
Vue
의 슬롯
이 어떻게 구현되었는지 명확하게 확인할 수 있습니다. 가자 가자 가자! (학습 영상 공유: vue video tutorial🎜)🎜1. 슬롯
사용법 검토
🎜먼저, 슬롯의 일반적인 사용법을 살펴보겠습니다. 여기서 slot
의 사용은 2.6.0의 새로운 표준을 사용합니다(이 기사에서는 v2.5
및 v2.5
의 작성 방법에 대해서도 설명합니다. code>v2.6 소스코드 구현의 차이점은 무엇인가요! 🎜🎜🎜사용법에 대해 더 자세히 알고 싶다면 공식 웹사이트로 이동하여 Vue의 슬롯 문서를 자세히 읽어보세요🎜🎜https://cn.vuejs.org/v2/guide/comComponents-slots.html🎜 blockquote>1. 기본 슬롯
{ scopedSlots: t._u([ { key: "footer", // 函数接收了一个参数n fn: function (n) { return [ // h1 标签的 render 函数 e("h1", [t._v("footer 具名 + 作用域插槽")]), // p 标签的 render 函数,这里可以看到编译后是:n.footerInfo.text e("p", [t._v(t._s(n.footerInfo.text))]) ] } } ]) }
2. 명명된 슬롯< /h3>🎜위의 경우에 따라 Slot header
라는 이름을 추가하면 코드는 다음과 같습니다. 🎜rrreee🎜위 코드 블록에서 찾을 수 있습니다: 🎜- 🎜
슬롯 태그
에 이름이 있습니다. name
속성에 header
🎜 - 🎜
템플릿 값이 있습니다. 상위 구성 요소의 태그
에는 v -slot
속성이 있고 값은 header
🎜
🎜페이지 표시 효과는 다음과 같습니다. 그림에서: 🎜🎜🎜3. 스코프 삽입 슬롯(slot-scope)
🎜위의 경우에 따라 스코프 슬롯 footer
를 추가합니다. 다음과 같습니다🎜rrreee🎜위의 코드 블록을 찾을 수 있습니다:🎜- 🎜sub
name=footer
속성 외에도 구성 요소에는 :footerInfo="footerInfo"
속성도 있습니다(해당 기능은 하위 구성 요소 데이터를 전달하는 것입니다)🎜 - 🎜
템플릿 태그
상위 구성 요소에는 v-slot:footer
가 있을 뿐만 아니라 할당 작업 = "slotProps"
도 있습니다. 템플릿의 이중 대괄호 구문에서는 footerInfo
🎜
🎜 slotProps
를 통한 하위 구성 요소 페이지 표시 효과는 그림과 같습니다: 🎜🎜
🎜🎜자, 사용법을 간략히 살펴본 후 작성자는 여기서 세 가지 질문을 할 것입니다: 🎜- 일반 슬롯과 범위 슬롯의 vNode는 어떤 링크에서 생성됩니까? 상위 구성 요소를 렌더링할 때 아니면 하위 구성 요소일 때?
- 범위 슬롯 상위 구성 요소에서 하위 구성 요소의 데이터에 액세스할 수 있는 이유는 무엇입니까?
- 일반 슬롯과 범위 지정 슬롯의 구현에 차이가 있나요?
🎜질문과 함께 읽어봅시다! 🎜2. 다양한 슬롯
의 컴파일 차이점🎜위의 마지막 사례 코드를 기반으로 패키징 명령을 실행하여 Vue가 어떻게 컴파일되는지 확인합니다. 템플릿을 생성할 때 슬롯
을 어떻게 처리하나요? 더 이상 고민할 필요 없이 서둘러 빌드
하세요~ (모두에게 비밀리에 알리시겠습니까? Vue
는 스코프 슬롯 및 일반 슬롯을 처리합니다. 차이점은 컴파일부터 시작됩니다. 즉, 렌더링 기능이 달라집니다) 🎜🎜그런데 작성자는 참고용으로 v2.5
의 명명된 슬롯 쓰기 방법을 사용합니다( 명명된 슬롯 slot="header"
를 사용하여 슬롯 헤더를 다시 작성합니다. v2.6
, v2.5
명명된 슬롯을 살펴볼 수 있습니다. 작성과 구현의 차이~ 어차피 어렵지 않아서 그냥 꺼내서 살펴봤습니다🎜
上图左边是 v2.6
、右边是 v2.5
的,这里,我们集中关注:
scopedSlots
属性。使用作用域插槽的 footer
的 render函数 是放在 scopedSlots
里的,并且 函数中 还有接收一个参数
my-slot
的 children
。可以发现,默认插槽的 render函数
一直都是作为当前组件的childre节点
,放在 当前 组件render函数 的第三个参数中
关注 header
两种具名插槽写法的区别。
- v2.6 中,我们使用了具名插槽,但是又未使用 作用域插槽的 header 也被放在了
scopedSlots
,但是函数的参数为空,这点跟作用域插槽有区别。 - v2.5 中, 具名插槽header 仅仅作为
my-slot组件
的children节点,并且其render函数的第二个参数中有一个 slot
的属性。
其实根据上述编译后的结果,我们不妨这样猜测:
默认插槽直接在父组件的 render
阶段生成 vNode
。
- 子组件
render
时,可能通过某种手段取得已经生成好的 插槽vNode
用作自己的 slot
节点。 - 因为观察上述默认插槽的render函数:
e("h1", [t._v("默认插槽")])
,直接就是 my-slot
组件的childre节点(位于 my-slot
组件的第三个参数)。
作用域插槽是在子组件 render
阶段生成 vNode
。
- 因为我们观察作用域插槽
footer
的编译后结果,其不作为 my-slot
组件的 children,而是被放在了 my-slot
组件的 第二个参数 data
中的一个 scopedSlots属性
里。 - 并且,作用域插槽的 render 函数 外层的 funciton 接收了一个参数。如果在执行子组件 render 的时候调用,那完全可以拿到子组件的数据。
这里放出具体的 作用域插槽 打包后代码,大家一看就很清晰了:
{
scopedSlots: t._u([
{
key: "footer",
// 函数接收了一个参数n
fn: function (n) {
return [
// h1 标签的 render 函数
e("h1", [t._v("footer 具名 + 作用域插槽")]),
// p 标签的 render 函数,这里可以看到编译后是:n.footerInfo.text
e("p", [t._v(t._s(n.footerInfo.text))])
]
}
}
])
}
로그인 후 복사로그인 후 복사三、slot
实现原理
1. 断点调试
为了方便大家看调试结果,当前项目的组件结构主要是这样,有三大层:
Vue
-> <app></app>
-> <my-slot></my-slot>
这里笔者在运行时代码 initRender()
、renderSlot()
中,打上 debugger ,直接带大火看看执行流程。这里简单介绍下两个方法:
initRender:获取 vm.$slot
。组件初始化时执行(比如执行到 my-slot组件
时,可从vm.$slot 获取父组件中的slot vNode
,也就是我们的 默认插槽)
renderSlot:把组件的 slot
替换成真正的 插槽vNode
接下来直接看实验截图:
1、先是进入initRender()
(这里跳过初始化 大Vue
、App
的过程)。直接到初始化 my-slot组件
过程。【 简单解释:由于 App组件
执行 render
得到 App组件vNode ,在 patch
过程中 遇到 vue-component-my-slot
的 vNode ,又执行 my-slot组件
的 初始化流程。不是很熟悉组件化流程的朋友可以去看看笔者的Vue响应式原理~】
- 我们不难发现,图中此时正值
my-slot组件
的 init
阶段。

- 再往下执行,我们可以得到 App组件中的
<h1 id="默认插槽">默认插槽</h1>
的vNode,赋值给 vm.$slot
(这里我们记住,默认插槽的 vNode 已经得到)

2. 그런 다음 renderSlot()
을 입력하세요. 그런 다음 위의 단일 단계 실행을 계속하면 renderSlot
에 도달하게 됩니다. 현재 my-slot 컴포넌트
의 render
단계에 진입했습니다. 첫 번째 단계를 되돌아보면 현재 기본 슬롯의 vNode가 있고 vm.$slot.default
renderSlot()
。接着上面继续单步执行,会走到 renderSlot
中。这时候,已经进入到 my-slot组件
的 render
阶段了。回顾第一步中,此时我们手握 默认插槽的vNode,并存在 vm.$slot.default
中
header插槽
- 按顺序走,先是 render 排第一的 header 的 vNode。如图所示,会走到断点处,我们接着单步

- 直接进入执行我们 header插槽 的render函数执行处。根据调试步骤,我们可以肯定,放置在
scopedSlots属性
中的 render函数,是在子组件 render 的时候执行

- 得到 header插槽 的 vNode

默认插槽
- 继续单步走,这次轮到 默认插槽 了!如图所示,这里的
key
正是 'default'
。可以发现,这里并没有像上面 header插槽 一样,去执行 render,而是直接将我们之前得到的 插槽vNode返回了。

- 得到 default插槽 的 vNode

作用域插槽
- 前面都跟 header插槽 一致,都是会在 my-slot 组件中 执行插槽的 render。我们直接单步到 render 处看看有什么区别。这里可以得出,function处传入的参数正是我们子组件
my-slot
的 data
数据,这就是为什么我们在 App组件
能通过 作用域插槽
访问到子组件数据的原因了

最后也是返回 footer插槽 的vNode。好了,验证过程结束~
2. 总结插槽实现原理
其实上面的流程只是论证过程,大家不可以不必深陷其中。笔者在这里直接根据实践过程,给大伙总结出结论!也就是要回到我们一开始的三个问题!
1、普通插槽、 作用域插槽 的 vNode 是在哪个环节生成的,render 父组件时还是子组件时?
默认插槽,不管 v2.5
、 v2.6
的写法,都是在 父组件中生成 vNode
。vNode
存在 vm.$slot
中。待子组件 render
到插槽时,会直接拿到 父组件的 vNode
-
具名插槽两个版本情况不一。根据编译结果可知:
v2.5
的写法,跟默认插槽是一样的,在父组件生成vNode,子组件直接拿来用
v2.6
中,直接时在 子组件 中才去执行 插槽render
,生成 插槽vNode
。
作用域插槽。不管版本,都是在子组件中进行render的。
大家不妨这么理解,模版编译后,只要是被放在 scopeSlots属性 中的插槽,都会在子组件执行 render 的时候才会去生成vNode。
2、作用域插槽 为什么能在父组件访问到子组件的数据?
- 作用域插槽只有子组件render的时候,才会执行render生成vNode。并且,作用域插槽的 render 函数能接参数,从而获得子组件的数据。就是这样形成了作用域插槽!所以我们能在父组件中,访问到子组件的data数据。
3、普通插槽 跟 作用域插槽 在实现上有区别吗?
- 有区别。
-
普通插槽。如果是 v2.5
헤더 슬롯 Strong>🎜- 순서대로 먼저 헤더의 vNode를 먼저 렌더링합니다. 그림과 같이 중단점에 도달하게 되며 한걸음씩 계속 진행하게 됩니다
🎜
🎜- 헤더의 렌더링 기능 실행을 직접 입력하세요 슬롯. 디버깅 단계에 따르면 하위 구성요소가 렌더링될 때
scopedSlots 속성
에 배치된 렌더링 함수가 실행되는지 확인할 수 있습니다
🎜
🎜- 헤더 슬롯의 vNode 가져오기
🎜
🎜🎜기본 슬롯🎜- 계속 한 단계씩 진행하세요. 이번에는 지금 기본 슬롯을 켜세요! 그림에 표시된 대로 여기서
키
는 정확히 '기본값'
입니다. 여기에서는 위의 헤더 슬롯처럼 렌더링을 실행하지 않고, 앞서 얻은 슬롯 vNode를 직접 반환하는 것을 확인할 수 있습니다.
🎜
🎜- 기본 슬롯의 vNode 가져오기
🎜
🎜🎜스코프 슬롯 🎜 - 앞의 것들은 헤더 슬롯과 일치하며, 슬롯의 렌더링은 my-slot 컴포넌트에서 실행됩니다. 차이점이 무엇인지 알아보기 위해 직접 렌더링을 진행해 보겠습니다. 여기서는 함수에 전달된 매개변수가 정확히 하위 구성요소인
my-slot
의 data
데이터라는 결론을 내릴 수 있습니다. 이것이 우리가 App 컴포넌트 scope 슬롯
을 통해 하위 컴포넌트 데이터에 접근할 수 있는 이유
🎜
🎜🎜마지막으로 바닥글 슬롯의 vNode도 반환합니다. 자, 검증 과정은 끝났습니다~🎜
2. 슬롯 구현 원리를 요약하자면
🎜사실 위 과정은 단지 시연 과정에 얽매일 필요가 없습니다. 여기에 저자는 실무 과정을 바탕으로 모두를 위한 결론을 직접 요약한다! 즉, 처음에 물었던 세 가지 질문으로 돌아가야 한다는 뜻입니다! 🎜🎜1. 상위 구성요소 또는 하위 구성요소를 렌더링할 때 일반 슬롯과 범위 슬롯의 vNode가 생성되는 단계는 무엇입니까? 🎜
- 🎜기본 슬롯,
v2.5
또는 v2.6
이 어떻게 작성되든 항상 상위 구성 요소 vNode
를 생성합니다. vNode
가 vm.$slot
에 존재합니다. 하위 구성요소 렌더링
이 슬롯에 도달하면 상위 구성요소의 vNode
🎜
- 🎜를 직접 가져옵니다. 명명된 슬롯두 버전 간에 상황이 다릅니다. 컴파일 결과에 따르면 🎜
- 🎜
v2.5
는 기본 슬롯과 동일한 방식으로 작성되어 상위 구성 요소 vNode, 하위 구성 요소는 🎜
- 🎜
v2.6
에서 직접 사용되며 슬롯 렌더링
은 하위 구성 요소에서 직접 실행되어 Slot vNode
를 생성합니다. 🎜
- 🎜범위 슬롯. 버전에 관계없이 하위 구성요소에서 렌더링됩니다. 🎜
- 🎜이 방법으로 이해하고 싶을 수도 있습니다. 템플릿이 컴파일된 후 슬롯이 scopeSlots 속성에 배치되어 있으면 하위 노드가 생성될 때 vNode가 생성됩니다. -컴포넌트는 렌더링을 실행합니다. 🎜
🎜2. 범위 슬롯 왜 상위 구성 요소에서 하위 구성 요소의 데이터에 액세스할 수 있나요? 🎜- 스코프 슬롯은 하위 구성 요소가 렌더링될 때 vNode를 생성하기 위해 렌더링만 실행합니다. 또한, 스코프 슬롯의 렌더링 기능은하위 구성요소의 데이터를 얻기 위해 매개변수를 수신할 수 있습니다. 이것이 범위가 지정된 슬롯이 형성되는 방식입니다! 따라서 상위 구성 요소에서 하위 구성 요소의 데이터에 액세스할 수 있습니다.
🎜3. 일반 슬롯과 스코프 슬롯의 구현에 차이가 있나요? 🎜- 차이가 있습니다.
- 🎜일반 슬롯.
v2.5
인 경우 명명된 슬롯과 기본 슬롯 모두 상위 구성 요소가 렌더링될 때만 vNode를 생성합니다. 하위 구성 요소가 슬롯을 렌더링하려는 경우 $slot에서 직접 가져옵니다. 상위 구성 요소 인스턴스입니다. vNode의 데이터입니다. 🎜
일반 슬롯. v2.6
인 경우, 명명된 슬롯이 하위 컴포넌트에서 렌더링을 실행하더라도 매개변수를 받지 않습니다. v2.6
,具名插槽 虽然是在子组件中执行的 render,但是其不接收参数。
作用域插槽。不管 v2.5
还是 v2.6
,都只在 子组件执行 render,并且能接收参数。
好了,最后来个精炼的总结。作用域插槽一定是延迟执行,且接收参数!普通插槽 可能延迟执行,可能直接执行,但不接收参数!
写在最后,很多时候我们搬砖,遵照文档把功能实现确实省力省心~但当你做多了,你就发现当前的东西缺乏挑战,索然无味。那这个时候,就会有一种冲动,想深入其实现原理,看看 slot
스코프 슬롯. v2.5
또는 v2.6
에 관계없이 렌더링은 하위 구성 요소에서만 실행되며 매개변수를 받을 수 있습니다.
자, 마지막에 간략하게 요약해보겠습니다. 🎜스코프 슬롯은 지연되어 매개변수를 받아야 합니다! 일반 슬롯은 지연되거나 직접 실행될 수 있지만 매개변수를 받지 않습니다! 🎜🎜
🎜마지막에 작성하면 여러 번 벽돌 작업을 하고 문서에 따라 기능을 구현하는데 정말 노동력이 절약되고 걱정이 없습니다~ 하지만 너무 많이 하면 현재의 일은 도전이 부족하고 지루합니다. 이때 구현 원리를 자세히 살펴보고 슬롯
이 어떻게 구현되는지 살펴보고 싶은 충동이 생길 것입니다. 특히 🎜범위가 지정된 슬롯🎜. 사용하다 보면 상위 컴포넌트가 스코프 슬롯을 통해 하위 컴포넌트의 데이터를 얻어야 한다는 것을 당연하게 여기겠지만, 소스 코드를 파고들어 다른 사람들이 어떻게 하는지 이해하고 나면 문득 깨달음을 얻게 될 것입니다. ~🎜🎜( 학습 영상 공유: 🎜웹 프론트엔드 개발🎜, 🎜프로그래밍 기초 영상🎜)🎜위 내용은 Vue.slot의 원리에 대해 이야기하고 슬롯이 어떻게 구현되는지 살펴보겠습니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!
슬롯 태그
에 이름이 있습니다. name
속성에 header
🎜템플릿 값이 있습니다. 상위 구성 요소의 태그
에는 v -slot
속성이 있고 값은 header
🎜3. 스코프 삽입 슬롯(slot-scope)
🎜위의 경우에 따라 스코프 슬롯footer
를 추가합니다. 다음과 같습니다🎜rrreee🎜위의 코드 블록을 찾을 수 있습니다:🎜- 🎜sub
name=footer
속성 외에도 구성 요소에는:footerInfo="footerInfo"
속성도 있습니다(해당 기능은 하위 구성 요소 데이터를 전달하는 것입니다)🎜 - 🎜
템플릿 태그
상위 구성 요소에는v-slot:footer
가 있을 뿐만 아니라 할당 작업= "slotProps"
도 있습니다. 템플릿의 이중 대괄호 구문에서는footerInfo
🎜
slotProps
를 통한 하위 구성 요소 페이지 표시 효과는 그림과 같습니다: 🎜🎜- 일반 슬롯과 범위 슬롯의 vNode는 어떤 링크에서 생성됩니까? 상위 구성 요소를 렌더링할 때 아니면 하위 구성 요소일 때?
- 범위 슬롯 상위 구성 요소에서 하위 구성 요소의 데이터에 액세스할 수 있는 이유는 무엇입니까?
- 일반 슬롯과 범위 지정 슬롯의 구현에 차이가 있나요?
2. 다양한 슬롯
의 컴파일 차이점🎜위의 마지막 사례 코드를 기반으로 패키징 명령을 실행하여 Vue가 어떻게 컴파일되는지 확인합니다. 템플릿을 생성할 때 슬롯
을 어떻게 처리하나요? 더 이상 고민할 필요 없이 서둘러 빌드
하세요~ (모두에게 비밀리에 알리시겠습니까? Vue
는 스코프 슬롯 및 일반 슬롯을 처리합니다. 차이점은 컴파일부터 시작됩니다. 즉, 렌더링 기능이 달라집니다) 🎜🎜그런데 작성자는 참고용으로 v2.5
의 명명된 슬롯 쓰기 방법을 사용합니다( 명명된 슬롯 slot="header"
를 사용하여 슬롯 헤더를 다시 작성합니다. v2.6
, v2.5
명명된 슬롯을 살펴볼 수 있습니다. 작성과 구현의 차이~ 어차피 어렵지 않아서 그냥 꺼내서 살펴봤습니다🎜上图左边是 v2.6
、右边是 v2.5
的,这里,我们集中关注:
scopedSlots
属性。使用作用域插槽的footer
的 render函数 是放在scopedSlots
里的,并且 函数中 还有接收一个参数my-slot
的children
。可以发现,默认插槽的render函数
一直都是作为当前组件的childre节点
,放在 当前 组件render函数 的第三个参数中关注
header
两种具名插槽写法的区别。- v2.6 中,我们使用了具名插槽,但是又未使用 作用域插槽的 header 也被放在了
scopedSlots
,但是函数的参数为空,这点跟作用域插槽有区别。 - v2.5 中, 具名插槽header 仅仅作为
my-slot组件
的children节点,并且其render函数的第二个参数中有一个slot
的属性。
- v2.6 中,我们使用了具名插槽,但是又未使用 作用域插槽的 header 也被放在了
其实根据上述编译后的结果,我们不妨这样猜测:
默认插槽直接在父组件的
render
阶段生成vNode
。- 子组件
render
时,可能通过某种手段取得已经生成好的插槽vNode
用作自己的slot
节点。 - 因为观察上述默认插槽的render函数:
e("h1", [t._v("默认插槽")])
,直接就是my-slot
组件的childre节点(位于my-slot
组件的第三个参数)。
- 子组件
作用域插槽是在子组件
render
阶段生成vNode
。- 因为我们观察作用域插槽
footer
的编译后结果,其不作为my-slot
组件的 children,而是被放在了my-slot
组件的 第二个参数data
中的一个scopedSlots属性
里。 - 并且,作用域插槽的 render 函数 外层的 funciton 接收了一个参数。如果在执行子组件 render 的时候调用,那完全可以拿到子组件的数据。
- 因为我们观察作用域插槽
这里放出具体的 作用域插槽 打包后代码,大家一看就很清晰了:
{ scopedSlots: t._u([ { key: "footer", // 函数接收了一个参数n fn: function (n) { return [ // h1 标签的 render 函数 e("h1", [t._v("footer 具名 + 作用域插槽")]), // p 标签的 render 函数,这里可以看到编译后是:n.footerInfo.text e("p", [t._v(t._s(n.footerInfo.text))]) ] } } ]) }
三、slot
实现原理
1. 断点调试
为了方便大家看调试结果,当前项目的组件结构主要是这样,有三大层:
Vue
-><app></app>
-><my-slot></my-slot>
这里笔者在运行时代码 initRender()
、renderSlot()
中,打上 debugger ,直接带大火看看执行流程。这里简单介绍下两个方法:
initRender:获取
vm.$slot
。组件初始化时执行(比如执行到my-slot组件
时,可从vm.$slot 获取父组件中的slot vNode
,也就是我们的 默认插槽)renderSlot:把组件的
slot
替换成真正的插槽vNode
接下来直接看实验截图:
1、先是进入initRender()
(这里跳过初始化 大Vue
、App
的过程)。直接到初始化 my-slot组件
过程。【 简单解释:由于 App组件
执行 render
得到 App组件vNode ,在 patch
过程中 遇到 vue-component-my-slot
的 vNode ,又执行 my-slot组件
的 初始化流程。不是很熟悉组件化流程的朋友可以去看看笔者的Vue响应式原理~】
- 我们不难发现,图中此时正值
my-slot组件
的init
阶段。
- 再往下执行,我们可以得到 App组件中的
<h1 id="默认插槽">默认插槽</h1>
的vNode,赋值给vm.$slot
(这里我们记住,默认插槽的 vNode 已经得到)
2. 그런 다음 renderSlot()
을 입력하세요. 그런 다음 위의 단일 단계 실행을 계속하면 renderSlot
에 도달하게 됩니다. 현재 my-slot 컴포넌트
의 render
단계에 진입했습니다. 첫 번째 단계를 되돌아보면 현재 기본 슬롯의 vNode가 있고 vm.$slot.default
renderSlot()
。接着上面继续单步执行,会走到 renderSlot
中。这时候,已经进入到 my-slot组件
的 render
阶段了。回顾第一步中,此时我们手握 默认插槽的vNode,并存在 vm.$slot.default
中
header插槽
- 按顺序走,先是 render 排第一的 header 的 vNode。如图所示,会走到断点处,我们接着单步
- 直接进入执行我们 header插槽 的render函数执行处。根据调试步骤,我们可以肯定,放置在
scopedSlots属性
中的 render函数,是在子组件 render 的时候执行
- 得到 header插槽 的 vNode
默认插槽
- 继续单步走,这次轮到 默认插槽 了!如图所示,这里的
key
正是'default'
。可以发现,这里并没有像上面 header插槽 一样,去执行 render,而是直接将我们之前得到的 插槽vNode返回了。
- 得到 default插槽 的 vNode
作用域插槽
- 前面都跟 header插槽 一致,都是会在 my-slot 组件中 执行插槽的 render。我们直接单步到 render 处看看有什么区别。这里可以得出,function处传入的参数正是我们子组件
my-slot
的data
数据,这就是为什么我们在App组件
能通过作用域插槽
访问到子组件数据的原因了
最后也是返回 footer插槽 的vNode。好了,验证过程结束~
2. 总结插槽实现原理
其实上面的流程只是论证过程,大家不可以不必深陷其中。笔者在这里直接根据实践过程,给大伙总结出结论!也就是要回到我们一开始的三个问题!
1、普通插槽、 作用域插槽 的 vNode 是在哪个环节生成的,render 父组件时还是子组件时?
默认插槽,不管
v2.5
、v2.6
的写法,都是在 父组件中生成vNode
。vNode
存在vm.$slot
中。待子组件render
到插槽时,会直接拿到 父组件的vNode
-
具名插槽两个版本情况不一。根据编译结果可知:
v2.5
的写法,跟默认插槽是一样的,在父组件生成vNode,子组件直接拿来用v2.6
中,直接时在 子组件 中才去执行插槽render
,生成插槽vNode
。
作用域插槽。不管版本,都是在子组件中进行render的。
大家不妨这么理解,模版编译后,只要是被放在 scopeSlots属性 中的插槽,都会在子组件执行 render 的时候才会去生成vNode。
2、作用域插槽 为什么能在父组件访问到子组件的数据?
- 作用域插槽只有子组件render的时候,才会执行render生成vNode。并且,作用域插槽的 render 函数能接参数,从而获得子组件的数据。就是这样形成了作用域插槽!所以我们能在父组件中,访问到子组件的data数据。
3、普通插槽 跟 作用域插槽 在实现上有区别吗?
- 有区别。
-
普通插槽。如果是
헤더 슬롯 Strong>🎜v2.5
- 순서대로 먼저 헤더의 vNode를 먼저 렌더링합니다. 그림과 같이 중단점에 도달하게 되며 한걸음씩 계속 진행하게 됩니다
🎜
- 헤더의 렌더링 기능 실행을 직접 입력하세요 슬롯. 디버깅 단계에 따르면 하위 구성요소가 렌더링될 때
scopedSlots 속성
에 배치된 렌더링 함수가 실행되는지 확인할 수 있습니다
🎜
- 헤더 슬롯의 vNode 가져오기
🎜🎜기본 슬롯🎜
- 계속 한 단계씩 진행하세요. 이번에는 지금 기본 슬롯을 켜세요! 그림에 표시된 대로 여기서
키
는 정확히'기본값'
입니다. 여기에서는 위의 헤더 슬롯처럼 렌더링을 실행하지 않고, 앞서 얻은 슬롯 vNode를 직접 반환하는 것을 확인할 수 있습니다.
🎜
- 기본 슬롯의 vNode 가져오기
🎜🎜스코프 슬롯 🎜
- 앞의 것들은 헤더 슬롯과 일치하며, 슬롯의 렌더링은 my-slot 컴포넌트에서 실행됩니다. 차이점이 무엇인지 알아보기 위해 직접 렌더링을 진행해 보겠습니다. 여기서는 함수에 전달된 매개변수가 정확히 하위 구성요소인
my-slot
의data
데이터라는 결론을 내릴 수 있습니다. 이것이 우리가 App 컴포넌트scope 슬롯
을 통해 하위 컴포넌트 데이터에 접근할 수 있는 이유
🎜
- 🎜마지막으로 바닥글 슬롯의 vNode도 반환합니다. 자, 검증 과정은 끝났습니다~🎜
2. 슬롯 구현 원리를 요약하자면
🎜사실 위 과정은 단지 시연 과정에 얽매일 필요가 없습니다. 여기에 저자는 실무 과정을 바탕으로 모두를 위한 결론을 직접 요약한다! 즉, 처음에 물었던 세 가지 질문으로 돌아가야 한다는 뜻입니다! 🎜🎜1. 상위 구성요소 또는 하위 구성요소를 렌더링할 때 일반 슬롯과 범위 슬롯의 vNode가 생성되는 단계는 무엇입니까? 🎜- 🎜기본 슬롯,
v2.5
또는v2.6
이 어떻게 작성되든 항상 상위 구성 요소vNode
를 생성합니다.vNode
가vm.$slot
에 존재합니다. 하위 구성요소렌더링
이 슬롯에 도달하면 상위 구성요소의vNode
🎜 - 🎜를 직접 가져옵니다. 명명된 슬롯두 버전 간에 상황이 다릅니다. 컴파일 결과에 따르면 🎜
- 🎜
v2.5
는 기본 슬롯과 동일한 방식으로 작성되어 상위 구성 요소 vNode, 하위 구성 요소는 🎜 - 🎜
v2.6
에서 직접 사용되며슬롯 렌더링
은 하위 구성 요소에서 직접 실행되어Slot vNode
를 생성합니다. 🎜
- 🎜
- 🎜범위 슬롯. 버전에 관계없이 하위 구성요소에서 렌더링됩니다. 🎜
- 🎜이 방법으로 이해하고 싶을 수도 있습니다. 템플릿이 컴파일된 후 슬롯이 scopeSlots 속성에 배치되어 있으면 하위 노드가 생성될 때 vNode가 생성됩니다. -컴포넌트는 렌더링을 실행합니다. 🎜
- 스코프 슬롯은 하위 구성 요소가 렌더링될 때 vNode를 생성하기 위해 렌더링만 실행합니다. 또한, 스코프 슬롯의 렌더링 기능은하위 구성요소의 데이터를 얻기 위해 매개변수를 수신할 수 있습니다. 이것이 범위가 지정된 슬롯이 형성되는 방식입니다! 따라서 상위 구성 요소에서 하위 구성 요소의 데이터에 액세스할 수 있습니다.
- 차이가 있습니다.
- 🎜일반 슬롯.
v2.5
인 경우 명명된 슬롯과 기본 슬롯 모두 상위 구성 요소가 렌더링될 때만 vNode를 생성합니다. 하위 구성 요소가 슬롯을 렌더링하려는 경우 $slot에서 직접 가져옵니다. 상위 구성 요소 인스턴스입니다. vNode의 데이터입니다. 🎜 일반 슬롯.
v2.6
인 경우, 명명된 슬롯이 하위 컴포넌트에서 렌더링을 실행하더라도 매개변수를 받지 않습니다.v2.6
,具名插槽 虽然是在子组件中执行的 render,但是其不接收参数。作用域插槽。不管
v2.5
还是v2.6
,都只在 子组件执行 render,并且能接收参数。
- 🎜일반 슬롯.
好了,最后来个精炼的总结。作用域插槽一定是延迟执行,且接收参数!普通插槽 可能延迟执行,可能直接执行,但不接收参数!
写在最后,很多时候我们搬砖,遵照文档把功能实现确实省力省心~但当你做多了,你就发现当前的东西缺乏挑战,索然无味。那这个时候,就会有一种冲动,想深入其实现原理,看看
스코프 슬롯.slot
v2.5
또는v2.6
에 관계없이 렌더링은 하위 구성 요소에서만 실행되며 매개변수를 받을 수 있습니다. -
🎜마지막에 작성하면 여러 번 벽돌 작업을 하고 문서에 따라 기능을 구현하는데 정말 노동력이 절약되고 걱정이 없습니다~ 하지만 너무 많이 하면 현재의 일은 도전이 부족하고 지루합니다. 이때 구현 원리를 자세히 살펴보고
슬롯
이 어떻게 구현되는지 살펴보고 싶은 충동이 생길 것입니다. 특히 🎜범위가 지정된 슬롯🎜. 사용하다 보면 상위 컴포넌트가 스코프 슬롯을 통해 하위 컴포넌트의 데이터를 얻어야 한다는 것을 당연하게 여기겠지만, 소스 코드를 파고들어 다른 사람들이 어떻게 하는지 이해하고 나면 문득 깨달음을 얻게 될 것입니다. ~🎜🎜( 학습 영상 공유: 🎜웹 프론트엔드 개발🎜, 🎜프로그래밍 기초 영상🎜)🎜위 내용은 Vue.slot의 원리에 대해 이야기하고 슬롯이 어떻게 구현되는지 살펴보겠습니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











vue.js에서 JS 파일을 참조하는 세 가지 방법이 있습니다. & lt; script & gt; 꼬리표;; mounted () 라이프 사이클 후크를 사용한 동적 가져 오기; Vuex State Management Library를 통해 수입.

vue.js의 시계 옵션을 사용하면 개발자가 특정 데이터의 변경 사항을들을 수 있습니다. 데이터가 변경되면 콜백 기능을 트리거하여 업데이트보기 또는 기타 작업을 수행합니다. 구성 옵션에는 즉시 콜백을 실행할지 여부와 DEEP를 지정하는 즉시 포함되며, 이는 객체 또는 어레이에 대한 변경 사항을 재귀 적으로 듣는 지 여부를 지정합니다.

vue.js에서 게으른 로딩을 사용하면 필요에 따라 부품 또는 리소스를 동적으로로드 할 수 있으므로 초기 페이지로드 시간을 줄이고 성능을 향상시킵니다. 특정 구현 방법에는 & lt; keep-alive & gt를 사용하는 것이 포함됩니다. & lt; 구성 요소는 & gt; 구성 요소. 게으른 하중은 FOUC (Splash Screen) 문제를 일으킬 수 있으며 불필요한 성능 오버 헤드를 피하기 위해 게으른 하중이 필요한 구성 요소에만 사용해야합니다.

vue.js에서 bootstrap 사용은 5 단계로 나뉩니다 : Bootstrap 설치. main.js.의 부트 스트랩 가져 오기 부트 스트랩 구성 요소를 템플릿에서 직접 사용하십시오. 선택 사항 : 사용자 정의 스타일. 선택 사항 : 플러그인을 사용하십시오.

Vue DevTools를 사용하여 브라우저 콘솔에서 vue 탭을 보면 VUE 버전을 쿼리 할 수 있습니다. npm을 사용하여 "npm list -g vue"명령을 실행하십시오. package.json 파일의 "종속성"객체에서 vue 항목을 찾으십시오. Vue Cli 프로젝트의 경우 "vue -version"명령을 실행하십시오. & lt; script & gt에서 버전 정보를 확인하십시오. vue 파일을 나타내는 html 파일의 태그.

vue.js는 이전 페이지로 돌아갈 수있는 네 가지 방법이 있습니다. $ router.go (-1) $ router.back () 사용 & lt; router-link to = & quot;/quot; Component Window.history.back () 및 메소드 선택은 장면에 따라 다릅니다.

CSS 애니메이션 또는 타사 라이브러리를 사용하여 VUE에서 Marquee/Text Scrolling Effects를 구현하십시오. 이 기사는 CSS 애니메이션 사용 방법을 소개합니다. & lt; div & gt; CSS 애니메이션을 정의하고 오버플로를 설정하십시오 : 숨겨진, 너비 및 애니메이션. 키 프레임을 정의하고 변환을 설정하십시오 : Translatex () 애니메이션의 시작과 끝에서. 지속 시간, 스크롤 속도 및 방향과 같은 애니메이션 속성을 조정하십시오.

vue.js가 트래버스 어레이 및 객체에 대한 세 가지 일반적인 방법이 있습니다. V- 결합 지시문은 V-FOR와 함께 사용하여 각 요소의 속성 값을 동적으로 설정할 수 있습니다. .MAP 메소드는 배열 요소를 새 배열로 변환 할 수 있습니다.
