JSFiddle - React, Tailwind, and code Playground

by sj82516

HTML

<h1>
使用Proxy 產生 One-way data binding
</h1>

<div id="app">
<h2>{{title}}</h2>
<p>
 {{message.title}}
</p>
<p>
 {{message.content}}
</p>
<ul>
	<li v-for="item in arr">{{item.arr}}</li>
</ul>
</div>

JavaScript

class Vue {
	constructor({el, data}){
		this.data = Object.assign({}, data);
		
		this.data = new Proxy(data, {
		 set: (target, property, value) => {
		   Reflect.set(target, property, value);
		   // update view
		 }
		})
		this._rootEl = document.querySelector('el');
        this._constructComponent();
	}
	
	//渲染頁面
    _constructComponent(){
    	if(!this.rootEl){
        	throw("根物件不存在");
        }
        let children = this.rootEl.children;
     	for(let i=0; i < children.length; i++){
        	let child = children[i];
            let mustacheExec = /^\{{2}(.*)\}{2}$/.exec(child.textContent);
            if(mustacheExec){
            	this._handleMustache(mustacheExec[1], child);
            }
            
            if(child.hasAttribute('v-model')){
            	this._handleVModel(child.getAttribute('v-model'), child)
            }
			
			if(child.hasAttribute('v-for')){
            	this._handleVFor(child.getAttribute('v-model'), child)
            }
        }
    }
    
    // string interpolation : {{ ... }}
    _handleMustache(propertyName, el){
    	if(!this.dataStored[propertyName]){
        	throw("資料不存在,你綁錯人囉")
        }
        el.textContent = this.dataStored[propertyName].value;
        console.log(el.textContent)
        this.dataStored[propertyName].elements.push(el);
    }
    
    // 處理v-model雙向綁定
    _handleVModel(propertyName, el){
    	let vm = this;
    	if(!this.dataStored[propertyName]){
        	throw("資料不存在,你綁錯人囉")
        }
        el.value = vm.dataWithSetter[propertyName];
        el.addEventListener("keyup", function(){
    		vm.dataWithSetter[propertyName] = el.value;
		});
    }
	
	_handleVFor(propertyName, el){
	
	}
}