vue原理的简易实现

Vue原理思路图
vue源码实现思路图

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app"></div>
	<script type="text/javascript">
		// 存储配置,监听属性,更新视图
		class Observer{
			constructor(){
				this.observables = []
			}
			subscribe(){
				this.observables.push(Observer.target)
			}
			publish(){
				this.observables.forEach( item => item.update());
			}
		}
		Observer.target = null
		class Observable{
			constructor(el, data, propName){
				this.$$data = data;
				this.$$el = el;
				this.$$propName = propName
			}
			update(){
				this.$$el.nodeValue = this.$$data[this.$$propName]
			}
		}

		let observer = new Observer();
		class Vue{
			constructor(opts){
				//  存储配置
				this.$data = opts.data();
				console.log(this.$data)
				this.$el = document.querySelector(opts.el)
				this.$template = opts.template;

				// 监听属性
				this.defineReactive();

				// 编译模板
				let div = this.compile()
				this.$el.append(div)
			}
			defineReactive(){
				Object.keys(this.$data).forEach(key => {
					let value = this.$data[key]
					Object.defineProperty(this.$data, key, {
						get(){
							console.log('get触发了')
							// 订阅数据
							if(Observer.target){
								observer.subscribe()
							}
							Observer.target = null;
							return value
						},
						set(newV){
							console.log('set 触发了')
							// 更新视图
							value = newV;
							observer.publish()
						}
					})
				});
			}
			compileTextNode(dom, propName){
				// 编译text节点
				Observer.target = new Observable(dom, this.$data, propName)
				dom.nodeValue = this.$data[propName]
				console.dir('text节点视图更新')
				
			}
			compileInputNode(dom, directive, propName){
				console.log(arguments)
				dom.value = this.$data[propName]
				dom.addEventListener('input', e => {
					this.$data[propName] = e.target.value
				}, false)

			}
			compile(){
				let div = document.createElement('div')
				let textRegex = /\{\{(.*)\}\}/
				let directiveRegex = /^v-(.*)$/;
				div.innerHTML = this.$template
				let elems = div.children[0].childNodes
				Array.from(elems).forEach( el => {
					 
					if(el.nodeType == 3){
						//text
						let re = textRegex.exec(el.nodeValue)
						if(!re) return;
						this.compileTextNode(el, re[1])
					}else if(el.nodeType == 1){
						// input
						Array.from(el.attributes).forEach( attr => {
							console.dir(attr)
							let re = directiveRegex.exec(attr.nodeName)
							if(!re) return;
							this.compileInputNode(el, re[1], attr.nodeValue)
						});	
					}
				});
				return div
			}
		}
	</script>
	<script type="text/javascript">
		let mv = new Vue({
			el: '#app',
			data(){
				return {
					msg: 'dsa'
				}
			},
			template: `
				<div>
					<input v-model="msg">
					{{msg}}
				</div>
			`
		})
	</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值