手写vue的插值语法的两种方式


一、准备步骤

(1)、新建vue.js文件
(2)、新建index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {{ str }}
        <h1>{{ str }}</h1>
        <input type="text" v-model="str">
        <button @click="change()">hahh</button>
    </div>
</body>

<script src="./vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            str:'hahh'
        },
    })
</script>
</html>

(3)、在文件中引入vue.js文件

注意:这时候的vue.js里面的是什么东西都没有,因此我们是在vue.js中手写vue插值语法

二、开始操作

1、原生vue是使用new的形式

注意:这里new的形式表示vue.js里面是采用类的方式

1.1、编写Vue类

class Vue{
	
}

2、在使用官方vue.js时在html文件中是采用向Vue类中传入一个大对象。

例如:

new Vue({
	el:'#app',
	data:{},
	methods:{},
	……
})

2.1、在Vue类中传入大对象

class Vue{
/*这里的options是前面传过来的大对象,放在constructer构造方法里面*/
	constructor(options){
		
	}
}

2.2、实现在官方vue中打印的this. d a t a 和 t h i s . data和this. datathis.el

class Vue{
/*这里的options是前面传过来的大对象,放在constructer构造方法里面*/
	constructor(options){
		this.$data = options.data
		this.$el = document.querySelector(options.el) //选择根节点
	}
}

2.3、实现插值解析

这里我们先写一个实现模版解析的方法,并在构造方法中使用它

class Vue{
/*这里的options是前面传过来的大对象,放在constructer构造方法里面*/
	constructor(options){
		this.$data = options.data
		this.$el = document.querySelector(options.el) //选择根节点
		this.analysis( this.$el ) //向方法中传入根节点
	}
	analysis(el){
		//首先得到根节点下的所有子节点 得到的是一个 Nodelist 数组
		const childNodes = el.childNodes
		//遍历所有子节点
		childNodes.forEach(childEl => {
			//判断节点类型
			/*
				* 3 为文本节点
				* 1 为元素节点
				* 我们在 实现模版解析的时候 实际是解析的 {{}} 中的东西,因此我们只需要找到文本节点即可,若不是文本节点继续找就行了
			*/
			if(childEl.nodeType == 1){
				if(childEl.childNodes.length > 0){
				//实现一种递归的形式
					analysis(childEl)
				}
			}
			if(childEl.nodeType == 3){
				// 正则判断 {{}}
                let reg = /\{\{(.*?)\}\}/g
                childEl.textContent = text.replace(reg,(macth,vmKey) => {
                    vmKey = vmKey.trim()    
                    return this.$data[vmKey];
                })
			}
		})
	}
}

3、写法2

注意:这一个比较通俗易懂

注意!!!:这种方式有一个小bug不知有没有人能够看出来呀 哈哈哈哈

class Vue{
    constructor( options ){
        this.$el = document.querySelector( options.el )
        this.$data = options.data
        this.analysis( this.$el )
    }
    // 模版解析

    analysis( rootNode ){
       
        const childNodes = rootNode.childNodes
       
        // 遍历子节点
        childNodes.forEach(child => {
           //判断节点类型
			/*
				* 3 为文本节点
				* 1 为元素节点
				* 我们在 实现模版解析的时候 实际是解析的 {{}} 中的东西,因此我们只需要找到文本节点即可,若不是文本节点继续找就行了
			*/

            if(child.nodeType == 3){
         		//得到原节点为解析的内容 {{ xxx }}
                const nodeTextContent = child.textContent.trim()
                //得到 '{{' 和 '}}' 符号的下标
                let begin = nodeTextContent.indexOf('{{') 
                let end = nodeTextContent.indexOf('}}')
                //得到 {{ }} 符号中间的属性
                let key = nodeTextContent.slice(begin+2,end).trim()
                //判断模版字符是否完整
                if( begin > -1 && end > -1 ){
                	//完整就解析
                    child.textContent = this.$data()[key]
                }
            }
            //递归
            if(child.nodeType == 1){
                this.analysis( child )
            }
        });
    }
}

总结

提示:需要对dom树有一定的了解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值