Browse Source

添加computed计算属性

peian 8 years ago
parent
commit
b279eafe45
4 changed files with 54 additions and 17 deletions
  1. 2 2
      js/compile.js
  2. 21 3
      js/mvvm.js
  3. 22 10
      js/watcher.js
  4. 9 2
      mvvm.html

+ 2 - 2
js/compile.js

@@ -141,7 +141,7 @@ var compileUtil = {
     },
 
     _getVMVal: function(vm, exp) {
-        var val = vm._data;
+        var val = vm;
         exp = exp.split('.');
         exp.forEach(function(k) {
             val = val[k];
@@ -150,7 +150,7 @@ var compileUtil = {
     },
 
     _setVMVal: function(vm, exp, value) {
-        var val = vm._data;
+        var val = vm;
         exp = exp.split('.');
         exp.forEach(function(k, i) {
             // 非最后一个key,更新val的值

+ 21 - 3
js/mvvm.js

@@ -1,14 +1,16 @@
 function MVVM(options) {
-    this.$options = options;
+    this.$options = options || {};
     var data = this._data = this.$options.data;
     var me = this;
 
     // 数据代理
     // 实现 vm.xxx -> vm._data.xxx
     Object.keys(data).forEach(function(key) {
-        me._proxy(key);
+        me._proxyData(key);
     });
 
+    this._initComputed();
+
     observe(data, this);
 
     this.$compile = new Compile(options.el || document.body, this)
@@ -19,8 +21,9 @@ MVVM.prototype = {
         new Watcher(this, key, cb);
     },
 
-    _proxy: function(key) {
+    _proxyData: function(key, setter, getter) {
         var me = this;
+        setter = setter || 
         Object.defineProperty(me, key, {
             configurable: false,
             enumerable: true,
@@ -31,5 +34,20 @@ MVVM.prototype = {
                 me._data[key] = newVal;
             }
         });
+    },
+
+    _initComputed: function() {
+        var me = this;
+        var computed = this.$options.computed;
+        if (typeof computed === 'object') {
+            Object.keys(computed).forEach(function(key) {
+                Object.defineProperty(me, key, {
+                    get: typeof computed[key] === 'function' 
+                            ? computed[key] 
+                            : computed[key].get,
+                    set: function() {}
+                });
+            });
+        }
     }
 };

+ 22 - 10
js/watcher.js

@@ -1,8 +1,15 @@
-function Watcher(vm, exp, cb) {
+function Watcher(vm, expOrFn, cb) {
     this.cb = cb;
     this.vm = vm;
-    this.exp = exp;
+    this.expOrFn = expOrFn;
     this.depIds = {};
+
+    if (typeof expOrFn === 'function') {
+        this.getter = expOrFn;
+    } else {
+        this.getter = this.parseGetter(expOrFn);
+    }
+
     this.value = this.get();
 }
 
@@ -40,17 +47,22 @@ Watcher.prototype = {
     },
     get: function() {
         Dep.target = this;
-        var value = this.getVMVal();
+        var value = this.getter.call(this.vm, this.vm);
         Dep.target = null;
         return value;
     },
 
-    getVMVal: function() {
-        var exp = this.exp.split('.');
-        var val = this.vm._data;
-        exp.forEach(function(k) {
-            val = val[k];
-        });
-        return val;
+    parseGetter: function(exp) {
+        if (/[^\w.$]/.test(exp)) return; 
+
+        var exps = exp.split('.');
+
+        return function(obj) {
+            for (var i = 0, len = exps.length; i < len; i++) {
+                if (!obj) return;
+                obj = obj[exps[i]];
+            }
+            return obj;
+        }
     }
 };

+ 9 - 2
mvvm.html

@@ -9,10 +9,11 @@
 <div id="mvvm-app">
     <input type="text" v-model="someStr">
     <input type="text" v-model="child.someStr">
-    <p v-class="className" class="abc">
+    <!-- <p v-class="className" class="abc">
         {{someStr}}
         <span v-text="child.someStr"></span>
-    </p>
+    </p> -->
+    <p>{{getHelloWord}}</p>
     <p v-html="child.htmlStr"></p>
     <button v-on:click="clickBtn">change model</button>
 </div>
@@ -34,6 +35,12 @@
             }
         },
 
+        computed: {
+            getHelloWord: function() {
+                return this.someStr + this.child.someStr;
+            }
+        },
+
         methods: {
             clickBtn: function(e) {
                 var randomStrArr = ['childOne', 'childTwo', 'childThree'];