Vue 响应式原理

24 篇文章 0 订阅
1 篇文章 0 订阅

Vue 响应式原理


<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	body
	<div id="app">
		<div>{{ age }}
			<p>
			</p>
		</div>
		<span>{{ name }}</span><br>
		<input type="" name="" v-mode="name">
		<p>{{ hello }}</p>
	</div>
	<script type="text/javascript">
		const app = document.getElementById('app');
		// console.log(app.getAttributes());
		app.getA
		class Vue {
			constructor(obj={}) {
				this.$option = obj;
				this.el = obj.el;
				this._data = obj.data;
				observe(this._data);
				for (let key in this._data) {
					Object.defineProperty(this, key, {
						enumerable: true,
						get() {
							return this._data[key];
						},
						set(newVal) {
							this._data[key] = newVal;
						}
					})
				}
				new Compile(this.el, this);
				initComputed.call(this);
			}
		}
		

		function initComputed() {
			let vm = this;
			let computed = vm.$option.computed;
			vm.computed = computed;
			Object.keys(computed).forEach(key => {
				Object.defineProperty(vm, key, {
					get: typeof computed[key] === 'function' ? computed[key] : computed[key].get, 
					set(){}
				})
			})
		}
		const vm = new Vue({
			el: '#app',
			data: {
				name: 'huzhixin',
				age: 20,
				like: {
					name: 'huqiao'
				}
			},
			computed: {
				hello() {
					return `${this.name}今年${this.age}`;
				}
			}
		})

		//发布订阅
		
		function Dep () {
			this.subs = [];
			this.addSub = function(fn) {
				this.subs.push(fn);
			}
		}

		Dep.prototype.notify = function () {
			this.subs.forEach(item => item.update());
		}
		function Watcher (vm, reg, fn) {
			this.fn = fn;
			this.vm = vm;
			this.reg = reg;
			Dep.target = this;
			let arr = reg.split('.');
			let val = vm;
			arr.forEach(k => {
				val = val[k];
			})
			Dep.target = null;
		}

		Watcher.prototype.update = function () {
			let val = this.vm;
			let arr = this.reg.split('.');
			arr.forEach(k => {
				val = val[k];
			})
			this.fn(val);
		}


		function Compile(el, vm) {
			vm.$el = document.querySelector(el);
			let fragment = document.createDocumentFragment();
			while(child = vm.$el.firstChild) {
				fragment.appendChild(child);
			}

			replace(fragment, vm);
			vm.$el.appendChild(fragment);

		}
		function observe(data) {
			return new Observe(data);
		}
		function replace(allNodes, vm) {
			Array.from(allNodes.childNodes).forEach(node => {
				let text = node.textContent;
				let reg = /\{\{(.*)\}\}/;

				if (node.nodeType === 1 && reg.test(text)) {
					let propArr = RegExp.$1.trim().split('.');
					let val = vm;
					propArr.forEach(k => {
						val = val[k];
					})
					new Watcher(vm, RegExp.$1.trim(), newVal => {
						node.textContent = text.replace(reg, newVal);
					})
					node.textContent = text.replace(reg, val);
					
				}
				if (node.nodeType === 1) {

					let nodeAttrs = node.attributes;
					Array.from(nodeAttrs).forEach(attr => {
						let name = attr.name;
						let val = attr.value;
						if (name.indexOf('v-model')) {
							node.value = vm[val];
						}
						new Watcher(vm, val, (newVal) => {
							node.value = newVal;
						})
						node.addEventListener('input',function (e) {
							let newVal = e.target.value;
							vm[val] = newVal;
						})
					})
				}
				if (node.childNodes) {
					replace(node);
				}
			})
		}
		function Observe(data) {
			let dep = new Dep();	//创建一个Dep实例对象
			
			for (let key in data) {
				let val = data[key];
				if (val.toString() === '[object Object]') {
					observe(val);
				} else {
					Object.defineProperty(data, key, {
						enumerable: true,
						get() {
							Dep.target && dep.addSub(Dep.target);	//添加Dep到addSub中
							return val;
						},
						set(newVal) {
							if (newVal === val) return;
							val = newVal;
							dep.notify(); 	//让所有update方法执行
						}
					})
				}
				
			}
		}
		

		

		

		// function H() {
		// 	const dep = new Dep();
		// 	console.log( dep.addSub)
		// }
	</script>
</body>
</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值