<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="app">
<input type="text" name="" v-model='num'>
<button v-click='addNum'>点击</button>
<h1 v-bind='num'></h1>
</div>
</body>
</html>
<script type="text/javascript">
function MyVue(options) {
this._init(options);
}
MyVue.prototype._init = function(options) {
this.$options = options;
this.$data = options.data;
this.$el = document.querySelector(options.el);
this.$methods = options.methods;
this._binding = {};
/**
* _binding保存着model与view的映射关系,也就是我们前面定义的Watcher的实例。
* 当model改变时,我们会触发其中的指令类更新,保证view也能实时更新
*/
this._obverse(this.$data);
this._compile(this.$el);
};
MyVue.prototype._obverse = function (obj) {
var value;
for(var i in obj){
if(obj.hasOwnProperty(i)){
value = obj[i];
this._binding[i] = {
_directives:[]
}
var binding = this._binding[i];
if(typeof value === 'object'){
this._obverse(value);
}
Object.defineProperty(this.$data,i,{
enumerable:true,
configurable:true,
get:function () {
console.log("获取值"+value);
return value;
},
set:function (newVal) {
console.log("设置值"+value);
if(value !== newVal){
value = newVal;
binding._directives.forEach(function (item) {
item.update();
})
}
}
})
}
}
}
MyVue.prototype._compile = function (root) {
var _this = this;
var nodes = root.children;
for(var n = 0;n<nodes.length;n++){
(function (node) {
if(node.children.length !== 0){
_this._compile(node);
}
if(node.hasAttribute('v-click')){
var attrVal = node.getAttribute('v-click');
node.addEventListener('click',(function () {
return _this.$methods[attrVal].bind(_this.$data);
})())
}
if(node.hasAttribute('v-bind')){
var attrVal = node.getAttribute('v-bind');
_this._binding[attrVal]._directives.push(new Watcher('text',node,_this,attrVal,'innerHTML'));
}
if(node.hasAttribute('v-model') && (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA')){
var attrVal = node.getAttribute('v-model');
node.addEventListener('input',(function (key) {
_this._binding[attrVal]._directives.push(new Watcher('input',node,_this,attrVal,'value'));
return function () {
_this.$data[attrVal] = node.value;
}
})(n));
}
})(nodes[n])
}
}
function Watcher(name,el,vm,exp,attr) {
this.name = name; //指令的名称
this.el = el; //指令对应的节点
this.vm = vm; //指令所属的vm实例
this.exp = exp; // 指令对应的值
this.attr = attr; //指令所需要的改变的属性
this.update();
}
Watcher.prototype.update = function () {
this.el[this.attr] = this.vm.$data[this.exp];
}
var app = new MyVue({
el:'#app',
data:{
num:0
},
methods:{
addNum:function () {
console.log('num');
this.num++;
}
}
});
</script>