vuejs render(vue render原理)

我们在写 Vue 项目的时候,会在 main.js 里面看到一句:
new Vue({  router,  render: h => h(App)}).$mount(\\\'#app\\\')
注意这句:render: h => h(App)。
h 是什么意思?

将 h 作为 createElement 的别名是 Vue 生态系统中的一个通用惯例,实际上也是 JSX 所要求的。从 Vue 的 Babel 插件的 3.4.0 版本开始,我们会在以 ES2015 语法声明的含有 JSX 的任何方法和 getter 中 (不是函数或箭头函数中) 自动注入 const h = this.$createElement,这样你就可以去掉 (h) 参数了。对于更早版本的插件,如果 h 在当前作用域中不可用,应用会抛错。

https://cn.vuejs.org/v2/guide/render-function.html#JSX

在 Vue 中也是可以使用 JSX 语法的,JSX 语法写在 render 函数里,如果页面 render 函数存在,那么就不会从页面的 template 模板里提取 HTML。

也就是说 render 和 template 是互斥的。
现在我们知道了 render: h=> h(App)  其实 h 是 createElement 方法。
createElement 方法定义在「src/core/vdom/create-element.js」里面调用了 _createElement 方法。
方法内部判断传入的标签是不是 string 类型,如果不是那就是对象,会去创建组件:
if (typeof tag === \\\'string\\\')//判断
我们传入的是 App ,所以会去执行 else 语句:
createComponent(Ctor, data, context, children, tag);//执行
createComponent 方法定义在「src/core/vdom/create-component.js」。

方法里把 Vue 赋值给 baseCtor 然后去执行一个 baseCtor.extend 扩展,扩展里面会执行一个 validateComponentName 函数,来判断你组件的名字是不是保留标签。函数内部:

if (isBuiltInTag(name) || config.isReservedTag(name)) {  warn(    \\\'Do not use built-in or reserved HTML elements as component \\\' +    \\\'id: \\\' + name  );}
会去判断你的组件名称不能是 Html 和 SVG 里面的标签,这些都属于保留标签。
var isHTMLTag = makeMap(  \\\'html,body,base,head,link,meta,style,title,\\\' +  \\\'address,article,aside,footer,header...);var isSVG = makeMap(  \\\'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,\\\' +  \\\'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,\\\' +  \\\'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view\\\',  true);
我常犯的错误就是组件名称写成「header」,现在知道为什么不能用 header 了。
createComponent 这个方法是递归执行的。创建子组件,并执行子组件的 init 和其他方法,会以执行子组件的 path 来结束子组件的执行。
子组件执行 _render 的时候会生成 VDemo ,并生成到父组件的「组件树」下。这样循环遍历,最后插入到 body 上。

递归处理组件的创建,所以插入组件的时候是先插入子组件,最后插入父组件。


图片授权基于 www.pixabay.com 相关协议

推荐阅读

Vue 在哪步执行数据监听?
挂载前数据经历了什么?

如何用 vue-cli 调试源码

原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34628.html

(0)
小道研究的头像小道研究
上一篇 2024年4月20日
下一篇 2024年4月20日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注