vue2.0源码手写学习记录

vue源码学习记录

对vue的源码一直只看过原理的解析以及部分代码,没有真正的手写实现,感觉理解不够深入,因此手写了部分重要原理,参考尚硅谷vue2源码解析视频课程。

1、mustache模板解析

        let str = `<div>
            <ol> 
                {
    {#students}} 
                    <li>
                      学生{
    {name}}的爱好是
                      <ol>{
    {#hobbies}}
                          <li>{
    {.}}</li>
                          {
    {/hobbies}}
                      </ol>
                    <li>
                {
    {/students}}
             </ol>
            </div>`
        let data = {
   
            students:[
                {
   name:'zz1',hobbies:['zz1']},
                {
   name:'zz2',hobbies:['zz2','zzzz2']},
                {
   name:'zz3',hobbies:['zz3','zzzz3']},
            ]
        }

目的是将str字符串解析成对应的html,使之能正常展示。
首先将str解析成token数组,以变量为分隔,上述字符串将被解析成13个数组如下图所示
在这里插入图片描述

生成的内容是没被折叠的,可以知道,3-11的数据应该在students的内部,因此,对生成的tokens进行处理,处理成有包含关系的tokens,如下图所示
在这里插入图片描述
接下来就是将生成的tokens解析成我们熟悉的html,包括变量的读取以及循环等指令的处理,具体实现如下

//index.js
import parseTemplateToToken from './parseTemplateToToken'
import renderTemplate from './renderTemplate'
window.TemplateEngine = {
   
    render(templateStr,data){
   
        const tokens = parseTemplateToToken(templateStr)
        console.log(tokens)
        const template = renderTemplate(tokens,data)
        console.log(template)
        return template
    }
}
//parseTemplateToToken.js
import Scanner from './scanner'
import foldTokens from './foldTokens'
export default function parseTemplateToToken(templateStr) {
   
    const scanner = new Scanner(templateStr)
    let tokens = []
    var word
    while (!scanner.eos()) {
   
        word = scanner.scanUtil('{
   {')
        if (word) {
   
            tokens.push(['text',word])
        }
        scanner.scan('{
   {')

        word = scanner.scanUtil('}}')
        if (word) {
   
            if (word[0] === '#') {
   
                tokens.push(['#',word.substring(1)])
            } else if (word[0] === '/') {
   
                tokens.push(['/',word.substring(1)])
            } else {
   
                tokens.push(['name',word])
            }
        }
        scanner.scan('}}')
    }
    console.log(JSON.stringify(tokens))
    return foldTokens(tokens)
}
//Scanner类
class Scanner {
   
    constructor(templateStr){
   
        this.templateStr = templateStr
        this.tail = templateStr;
        this.pos = 0 
    }

    //跳过需要查找的字符
    scan(tag){
   
        if(this.tail.indexOf(tag)===0){
   
            this.pos += tag.length
            this.tail = this.templateStr.substring(this.pos)
        }
    }

    //找到需要查找的字符位置    
    scanUtil(tag){
    
        const pos_backUp = this.pos
        while(this.tail.indexOf(tag)!==0&&!this.eos()){
   
            this.pos++
            this.tail = this.templateStr.substring(this.pos)
        }
        return this.templateStr.substring(pos_backUp,this.pos)
    }

    eos(){
   
        return this.pos>this.templateStr.length-1
    }
}

export default Scanner
//foldTokens.js,将解析出的tokens折叠
export default function foldTokens(tokens) {
   
    let result = []
    let collector = result
    let sections = []
    for (let i = 0; i < tokens.length; i++) {
   
        let token = tokens[i]
        switch (token[0]) {
   
            case '#':
                collector.push(token)
                sections.push(token)
                collector = token[2] = []
                break;
            case '/':
                sections.pop()
                collector = sections.length ? sections[sections.length - 1][2] : result
                break;
            default:
                collector.push(token)
        }
    }
    return result
}
//renderTemplate.js,将折叠好的token生成html
import lookup from './lookup'
export default function renderTemplate(tokens,data) {
   
    let result = ''
    for(let i=0;i<tokens.length;i++){
   
        if(tokens[i][0] === 'text'){
   
            result +=tokens[i][1]
        }else if(tokens[i][0] === 'name'){
   
            result +=lookup(data,tokens[i][1])
        }else{
   
            result +=parseArray(data,tokens[i])
        }
    }
    return result
}

function parseArray(data,tokens){
   
    let value  = l
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值