vue原理

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>仿vue</title>
</head>
<body>

	<div id="app">
		<input type="text" v-model = 'name'>-<input type="text" v-model = 'testData'>
		<span>输入数据为:{{name}} -- {{testData}}</span>
		<h3>合并字符串{{name+testData}}</h3>
		<h3>v-bind:</h3>
		<h3 v-bind='name'>v-bind=name</h3>
		<button v-on:click='change'>change</button>
	</div>
	
</body>
<script>
	window.onload = function(){
		var app = new myVue({
			el:"#app",
			data : {
				name:"仿vue",
				testData : "另一个数据变量"
			},
			method : {
				change:function(){
					this.name = 'change';
				}
			}
		})
	}

	function myVue(options = {}){
		this.$options = options;
		this.$el = document.querySelector(options.el);
		this._data = options.data;
		this._watcherTpl = {};
		this._methods = options.method;
		this._observer(this._data);
		this._compile(this.$el);
	}

	myVue.prototype._observer = function(obj){
		var _this = this;
		Object.keys(obj).forEach(key => {
			_this._watcherTpl[key] = {
				_directive : []
			}

			var value = obj[key];

			var watcherTpl = _this._watcherTpl[key];

			Object.defineProperty(_this._data,key,{
				configurable : true,
				enumerable : true,
				get(){
					return value;
				},
				set(newValue){
					var oldvalue = value;
					if(value !== newValue){
						value = newValue;
						watcherTpl._directive.forEach(item => {
							item.update(oldvalue);
						})
					}
				}
			});
		});
		
	}

	myVue.prototype._compile = function(el){
		var _this = this;
		var nodes = el.children;
		for (var i = 0; i < nodes.length; i++) {
			var node = nodes[i];
			if(node.children.length){
				_this._compile(node);
			}

			if(node.hasAttribute('v-model')&&(node.tagName == 'INPUT'||node.tagName == 'TEXTAREA')){
				node.addEventListener('input',(function(key){
					var attrVal = node.getAttribute('v-model');
					_this._watcherTpl[attrVal]._directive.push(new Watcher(node,_this,attrVal,'value'));
					return function(){
						_this._data[attrVal] = nodes[key].value;
					}
				})(i));
			}

			if(node.hasAttribute('v-bind')){
				var attrVal = node.getAttribute('v-bind');
				_this._watcherTpl[attrVal]._directive.push(new Watcher(node,_this,attrVal,'innerHTML'));
			}

			var reg = /\{\{\s*([^}]+\S)\s*\}\}/g;
			var txt = node.textContent;
			if(reg.test(txt)){
				 let replaceList = node.innerHTML.match(reg) || (node.hasAttribute('vueID') && node.getAttribute('vueID').match(reg))
		            if(replaceList) {
		                if(!node.hasAttribute('vueID')) {
		                    node.setAttribute('vueID', node.innerHTML)
		                }
		                node.innerHTML = node.getAttribute('vueID')
		                replaceList.forEach(v => {
		                    let key = v.slice(2, v.length - 2)
							var algorithm_reg = /[\+\-\*]/g; 
							if(algorithm_reg.test(key)){
							 var keys = key.split(algorithm_reg);
							}else{
								node.innerHTML = node.innerHTML.replace(v, this._data[key]);
								var getName = _this._watcherTpl[key];
								if(!getName._directive){
									getName._directive = [];
								}
								getName._directive.push(new Watcher(node,_this,key,'innerHTML'));
							}
		                   
		                })

		            }
				/*node.textContent = txt.replace(reg,(mathced,placeholder)=>{
  						 // matched匹配的文本节点包括{{}}, placeholder 是{{}}中间的属性名
  					var getName = _this._watcherTpl[placeholder];
  					if(!getName._directive){
  						getName._directive = [];
  					}
  					getName._directive.push(new Watcher(node,_this,placeholder,'innerHTML'));

  					
					return placeholder.split('.').reduce((val,key) => {
							return _this._data[key];
					},_this.$el);
				})*/
			}

			if(node.hasAttribute('v-on:click')){
				var methodName = node.getAttribute('v-on:click');
				node.addEventListener('click',() => this._methods[methodName].bind(this._data)());
			}

		}
	}

	function Watcher(el,vm,value,attr){
		this.el = el;
		this.vm = vm;
		this.val = value;
		this.attr = attr;
		this.update();
	}

	Watcher.prototype.update =function(oldvalue){
		if(!this.el.hasAttribute('vueID')){
			this.el[this.attr] = this.vm._data[this.val];
		}else{
			this.el[this.attr] = this.el[this.attr].replace(oldvalue, this.vm._data[this.val]);
		}
		
	}
</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值