学习vue源码(9)手写代码生成器

attrsList: [],

attrsMap: {},

children: [{

type: 2,

text: “{{name}}”,

static: false,

expression: “_s(name)”

}]

}

]

}

使用例子中的模板生成后的 AST 来生成 render 后是这样的:

{

render: with(this){return _c('div',[_c('p',[_v(_s(name))])])}

}

格式化后是这样的:

with(this){

return _c(

‘div’,

[

_c(

‘p’,

[

_v(_s(name))

]

)

]

)

}

生成后的代码字符串中看到了有几个函数调用 _c,_v,_s。

_c 对应的是 createElement,它的作用是创建一个元素。

  • 第一个参数是一个HTML标签名

  • 第二个参数是元素上使用的属性所对应的数据对象,可选项

  • 第三个参数是 children

例如:

一个简单的模板:

生成后的代码字符串是:

with(this){return _c('p',{attrs:{"title":"Berwin"},on:{"click":c}},[_v("1")])}

格式化后:

with(this){

return _c(

‘p’,

{

attrs:{“title”:“Berwin”},

on:{“click”:c}

},

[_v(“1”)]

)

}

_v 的意思是创建一个文本节点。

_s 是返回参数中的字符串。

可能有同学觉得这个格式化后的代码很陌生,其实把with去掉后,就很熟悉了(其实with是用来改变作用域的,去掉也不会影响我们的理解)

return _c(

‘p’,

{

attrs:{“title”:“Berwin”},

on:{“click”:c}

},

[_v(“1”)]

)

有没有发现 这样很熟悉?没错我们去看vue官网的 render渲染函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sJtun0qJ-1591176301693)(https://imgkr.cn-bj.ufileos.com/681bf1eb-bc26-429d-8ede-52ddfd99f2e8.png)]

有没发现,其实生成的代码字符串 就是 vue官网中介绍的render函数里的 createElement函数。

而参数也是对应的

  • 第一个参数:标签名

  • 第二个参数:节点数据

  • 第三个参数:子节点数组

代码生成器的总体逻辑其实就是使用 element ASTs 去递归,然后拼出这样的 _c('div',[_c('p',[_v(_s(name))])]) 字符串。

那如何拼这个字符串呢??

请看下面的代码:

function genElement (el: ASTElement, state: CodegenState) {

const data = el.plain ? undefined : genData(el, state)

const children = genChildren(el, state, true)

let code = `_c(' e l . t a g ′ {el.tag}' el.tag{

data ? ,${data} : ‘’ // data

}${

children ? ,${children} : ‘’ // children

})`

return code

}

因为 _c 的参数需要 tagName、data 和 children。

所以上面这段代码的主要逻辑就是用 genData 和 genChildren 获取 data 和 children,然后拼到 _c 中去,拼完后把拼好的 "_c(tagName, data, children)" 返回。

el.plain 为true该节点没有属性。因此就不需要 执行genData。

所以我们现在比较关心的两个问题:

data 如何生成的(genData 的实现逻辑)?

children 如何生成的(genChildren 的实现逻辑)?

我们先看 genData 是怎样的实现逻辑:

function genData (el: ASTElement, state: CodegenState): string {

let data = ‘{’

// key

if (el.key) {

data += key:${el.key},

}

// ref

if (el.ref) {

data += ref:${el.ref},

}

if (el.refInFor) {

data += refInFor:true,

}

// pre

if (el.pre) {

data += pre:true,

}

// … 类似的还有很多种情况

data = data.replace(/,$/, ‘’) + ‘}’

return data

}

可以看到,就是根据 AST 上当前节点上都有什么属性,然后针对不同的属性做一些不同的处理,最后拼出一个字符串~

然后我们在看看 genChildren 是怎样的实现的:

function genChildren (
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

结尾

正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。

以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。

戳这里获取前端学习资料

节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

结尾

正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。

以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。

戳这里获取前端学习资料

前端学习书籍导图-1

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值