最近在复习Vue的源码,今天带大家手写实现一下Vue内置组件component,比较简单,最近面试有被问到。
前言
Vue
大家都很熟悉,除了原生的组件,其自己也封装了一下内置组件,比如component
,transition
,keep-alive
等等。
component
算是用的比较多的了,当我们遇到需要根据不同条件显示不同组件的时候,一般都是用component
来实现。当然你也可以v-if,v-else-if,v-else
,就显的比较笨了。
大家如果没用过,可以先自己尝试一下这个component
组件。最主要的就是它有一个is
属性,你给is赋予什么组件名,它就渲染什么组件。
内置组件component的使用
我写一个小demo
演示一下。
先随意的写三个组件,A
,B
,C
。
组件内容就是aaaa
,bbbb
,cccc
,方便我们辨认当然渲染的是哪个组件。
然后集体引入,挂载。
视图内容大概这样写,需求就是,准备三个按钮,点击哪个按钮就显示哪个组件。
<div> <button @click="changeComp('A')">显示A</button> <button @click="changeComp('B')">显示B</button> <button @click="changeComp('C')">显示C</button> </div> <component :is="compList"></component>
compList
提前声明好,默认是A
组件。
data() { return { compList: 'A' }; },
changeComp
函数内容如下:
methods: { changeComp(comp) { this.compList = comp; }, }
OK,这就完事了,大家可以自己试一下,是可以完成既定的需求的。
component组件的原理分析
我们今天的任务是,了解内置组件component
的原理,并手写实现一个。
那么component
的实现原理是怎么样的呢,这个就需要牵扯一块比较大的知识链了,也是Vue
的核心内容。关于Vue
的虚拟DOM
以及模板编译的部分内容。
简单来说,Vue
内部实现了一个虚拟DOM
来妥善解决原生DOM
的性能问题。
虚拟DOM与原生DOM
比如我们当前需要插入1000
个DOM
节点,如果是原生DOM
来做的话,就是扎扎实实的,一个个操作,改变DOM
,DOM
需要被改变1000
次,这对于性能是极大的损耗,造成很多的问题。
虚拟DOM
的原理就是,先在框架内部用对象模拟一下原生DOM
的形态,记录你这1000
次的DOM
操作,最后将DOM
被操作1000
次后的形态赋给原生DOM
。这样就能极大的优化大量DOM
操作带来的负面影响。
然后再来思考一下,我们平时写的.vue
文件,其实跟原生写法是有区别的,无论是HTML
、JS
还是CSS
,在编写阶段有做了些许的改动,这样做有助于提高我们的编写效率。但是浏览器是只认原生的HTML
、CSS
和JS
的,所以我们编写的组件内容,其实只是一个template
模板,需要进行编译转换为原生的DOM
才能渲染到浏览器上。
而componet
组件其实就是内部做了这个事情,将你传入的组件, 先转换为虚拟DOM
,然后渲染为真实DOM
,展示到视图上。
render函数的使用
这里面就涉及到一个知识点了,关于render
函数的使用,具体的内容大家可以去Vue
文档详细了解一下render
函数。可能大家日常开发用的比较少,涉及一些偏底层的东西时才会遇到。
我这里只介绍render
函数做的事情。
它的形态大概是这个样式。
render(h) { // return h('A'); return h('div', '6666'); },
render
函数接收一个参数,比如叫它h
,h
也是一个函数,它的作用就是将传入的内容构建为虚拟DOM
,这个传入的内容支持原生的写法,也支持Vue
组件。
比如我代码里给出的,h('div', '6666')
,h
函数就会生成一个div
组件,文本内容是666
。被注释掉的,就是传入Vue
中自己的写的组件名字为A
,同样支持。
但是h
函数仅仅只是将传入的内容,生成虚拟DOM
,不是真实的原生DOM
,然后将它return
出去,render
函数才会将这个虚拟DOM
渲染成为真实DOM
。
上述关于render
函数的内容不知道大家是否理解,可以去Vue
官方文档里,详细看一下,然后自己写写demo
体验一下,render
函数算是Vue
进阶中比较重要的内容了。
所以,话说回来,知道了render
函数这个东西,我们就能够比较好的实现component
这个内置组件了。component
组件会接收一个属性is
,is
的值就是我们要渲染的组件。component
组件的内容其实就是进行了 Vue组件 => 虚拟DOM => 真实DOM
,渲染视图,其实就通过render
函数实现就可以。
尝试手写实现component
话不多说,我们试一下。
因为组件内容比较少,所以我们直接使用Vue.component
来编写组件内容。
Vue.component("myComponent", { props: ["is"], render(h) { return h(this.is); }, });
其实核心代码就上面这几行,组件名字是myComponent
,props
的作用就是指定组件要接收的参数is
。然后编写一下render
函数,因为是渲染Vue
组件,所以直接return h(this.is)
就可以。
将这段代码写在JS
里,然后就可以使用了。记得要import Vue from 'vue'
来引入Vue
,因为我们是通过Vue.component
来编写组件的。
下面我们试一试,这个myComponent
是否有用。
<div> <button @click="changeComp('A')">显示A</button> <button @click="changeComp('B')">显示B</button> <button @click="changeComp('C')">显示C</button> </div> <component :is="compList"></component> <my-component :is="compList"></my-component>
实际操作后可以发现,我们自己写的myComponent
和Vue
内置的component
效果是一模一样的,大家自己也可以试一下。
完整代码:
<template> <div> <div> <button @click="changeComp('A')">显示A</button> <button @click="changeComp('B')">显示B</button> <button @click="changeComp('C')">显示C</button> </div> <component :is="compList"></component> <my-component :is="compList"></my-component> </div> </template> <script> import Vue from "vue"; import A from "../components/A.vue"; import B from "../components/B.vue"; import C from "../components/C.vue"; Vue.component("myComponent", { props: ["is"], render(h) { return h(this.is); }, }); export default { components: { A, B, C, }, data() { return { compList: 'A' }; }, methods: { changeComp(comp) { this.compList = comp; }, }, }; </script> <style scoped> </style>
总结
今天的内容是带着大家手写实现Vue
的内置组件component
,在尝试实现某一个东西的时候,就需要先思考它的作用以及内部原理。手写component
的过程比较简单,但是涉及到了很多Vue
的原理性知识点,比如虚拟DOM、render函数、模板编译等。
到此这篇关于手写Vue内置组件component的实现示例的文章就介绍到这了,更多相关Vue内置组件component内容请搜索阿兔在线工具以前的文章或继续浏览下面的相关文章希望大家以后多多支持阿兔在线工具!