From 35b1e44215c4ea95a2d68b5cc93bb95575c57725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8B=BE=E8=82=A1?= Date: Sun, 17 Apr 2016 16:06:12 +0800 Subject: [PATCH] + [jsfm] supported computed options --- .../lib/__test__/assets/computed.input | 54 ++++++++++++++++ .../lib/__test__/assets/computed.output | 15 +++++ src/js-framework/lib/__test__/test.js | 26 ++++++++ src/js-framework/lib/vm/__test__/vm.js | 46 +++++++++++++- src/js-framework/lib/vm/index.js | 1 + src/js-framework/lib/vm/instance/scope.js | 61 ++++++++++--------- 6 files changed, 170 insertions(+), 33 deletions(-) create mode 100644 src/js-framework/lib/__test__/assets/computed.input create mode 100644 src/js-framework/lib/__test__/assets/computed.output diff --git a/src/js-framework/lib/__test__/assets/computed.input b/src/js-framework/lib/__test__/assets/computed.input new file mode 100644 index 0000000000..0188eda029 --- /dev/null +++ b/src/js-framework/lib/__test__/assets/computed.input @@ -0,0 +1,54 @@ +define('@weex-component/computed', function (require, exports, module) { + +; + module.exports = { + data: function () { + return {x: 1, y: 2} + }, + computed: { + n: function () { + return this.x + this.y + }, + m: { + get: function () { + return this.x + this.y + }, + set: function (v) { + this.y = v + } + } + }, + methods: { + foo: function () { + this.m = 10 + } + } + } + + +;module.exports.template = { + "type": "container", + "events": { + "click": "foo" + }, + "children": [ + { + "type": "text", + "attr": { + "value": function () {return this.n} + } + }, + { + "type": "text", + "attr": { + "value": function () {return this.m} + } + } + ] +} + +;}) + +// require module + +bootstrap('@weex-component/computed') diff --git a/src/js-framework/lib/__test__/assets/computed.output b/src/js-framework/lib/__test__/assets/computed.output new file mode 100644 index 0000000000..8c5534d9ae --- /dev/null +++ b/src/js-framework/lib/__test__/assets/computed.output @@ -0,0 +1,15 @@ +{ + type: 'container', + event: ['click'], + children: [{ + type: 'text', + attr: { + value: 3 + }, + }, { + type: 'text', + attr: { + value: 3 + } + }] +} diff --git a/src/js-framework/lib/__test__/test.js b/src/js-framework/lib/__test__/test.js index 7c329e846a..fc2963171a 100644 --- a/src/js-framework/lib/__test__/test.js +++ b/src/js-framework/lib/__test__/test.js @@ -343,6 +343,32 @@ describe('test input and output', function () { delete allDocs[name] }) + it('computed case', function () { + var name = 'computed' + var inputCode = readInput(name) + var outputCode = readOutput(name) + var doc = new Document(name) + allDocs[name] = doc + + framework.createInstance(name, inputCode) + var expected = eval('(' + outputCode + ')') + var actual = doc.toJSON() + expect(actual).eql(expected) + + framework.refreshInstance(name, {x: 10}) + expected.children[0].attr.value = 12 + expected.children[1].attr.value = 12 + expect(actual).eql(expected) + + framework.refreshInstance(name, {m: 10}) + expected.children[0].attr.value = 20 + expected.children[1].attr.value = 20 + expect(actual).eql(expected) + + framework.destroyInstance(name) + delete allDocs[name] + }) + it('backward(register/render) case', function () { var name = 'backward1' var inputCode = readInput(name) diff --git a/src/js-framework/lib/vm/__test__/vm.js b/src/js-framework/lib/vm/__test__/vm.js index 7335d5c011..0f44eeb1db 100644 --- a/src/js-framework/lib/vm/__test__/vm.js +++ b/src/js-framework/lib/vm/__test__/vm.js @@ -139,11 +139,25 @@ describe('generate virtual dom for a single vm', () => { type: 'container', attr: {a: 1, b: 2}, style: {c: 3, d: 4}, children: [ {type: 'image', attr: {src: function () {return this.x}}}, - {type: 'text', attr: {value: function () {return this.y}}} + {type: 'text', attr: {value: function () {return this.n}}}, + {type: 'text', attr: {value: function () {return this.m}}} ] }, data: { x: '', y: '' + }, + computed: { + n: function () { + return this.y.toUpperCase() + }, + m: { + get: function () { + return this.y.toUpperCase() + }, + set: function (v) { + this.y = v + } + } } } @@ -153,32 +167,58 @@ describe('generate virtual dom for a single vm', () => { expect(vm._app).equal(app) expect(vm.x).eql('') expect(vm.y).eql('') + expect(vm.n).eql('') + expect(vm.m).eql('') var el = doc.body expect(el.type).eql('container') expect(el.attr).eql({a: 1, b: 2}) expect(el.style).eql({c: 3, d: 4}) expect(el.children).is.an.array - expect(el.children.length).eql(2) + expect(el.children.length).eql(3) var image = el.children[0] var text = el.children[1] + var text2 = el.children[2] expect(image.type).eql('image') expect(image.attr).eql({src: ''}) expect(text.type).eql('text') - expect(text.attr).eql({value: ''}) + expect(text.attr).eql({value: ''}) + expect(text2.type).eql('text') + expect(text2.attr).eql({value: ''}) vm.x = '' differ.flush() expect(el).equal(doc.body) expect(image).equal(el.children[0]) expect(text).equal(el.children[1]) + expect(text2).equal(el.children[2]) vm.x = 'other string value' differ.flush() expect(el).equal(doc.body) expect(image).equal(el.children[0]) expect(image.attr).eql({src: 'other string value'}) + + vm.y = 'other string value' + differ.flush() + expect(el).equal(doc.body) + expect(text).equal(el.children[1]) + expect(text.attr).eql({value: 'OTHER STRING VALUE'}) + expect(text2).equal(el.children[2]) + expect(text2.attr).eql({value: 'OTHER STRING VALUE'}) + + vm.m = 'third string value' + differ.flush() + expect(vm.x).eql('other string value') + expect(vm.y).eql('third string value') + expect(vm.n).eql('THIRD STRING VALUE') + expect(vm.m).eql('THIRD STRING VALUE') + expect(el).equal(doc.body) + expect(text).equal(el.children[1]) + expect(text.attr).eql({value: 'THIRD STRING VALUE'}) + expect(text2).equal(el.children[2]) + expect(text2.attr).eql({value: 'THIRD STRING VALUE'}) }) it('generate an element tree with shown', () => { diff --git a/src/js-framework/lib/vm/index.js b/src/js-framework/lib/vm/index.js index 480f643b30..620cca91e1 100644 --- a/src/js-framework/lib/vm/index.js +++ b/src/js-framework/lib/vm/index.js @@ -47,6 +47,7 @@ export default function Vm( this._options = component this._methods = component.methods || {} + this._computed = component.computed || {} this._css = component.style || {} this._ids = {} this._watchers = [] diff --git a/src/js-framework/lib/vm/instance/scope.js b/src/js-framework/lib/vm/instance/scope.js index 1b05a3bab6..2bbf7e09ab 100644 --- a/src/js-framework/lib/vm/instance/scope.js +++ b/src/js-framework/lib/vm/instance/scope.js @@ -12,7 +12,7 @@ var Dep = require('../observer/dep') exports._initScope = function () { this._initData() - // this._initComputed() + this._initComputed() this._initMethods() // this._initMeta() } @@ -137,36 +137,37 @@ exports._unproxy = function (key) { // } // } -// /** -// * Setup computed properties. They are essentially -// * special getter/setters -// */ +/** + * Setup computed properties. They are essentially + * special getter/setters + */ -// function noop () {} -// exports._initComputed = function () { -// var computed = this.$options.computed -// if (computed) { -// for (var key in computed) { -// var userDef = computed[key] -// var def = { -// enumerable: true, -// configurable: true -// } -// if (typeof userDef === 'function') { -// def.get = _.bind(userDef, this) -// def.set = noop -// } else { -// def.get = userDef.get -// ? _.bind(userDef.get, this) -// : noop -// def.set = userDef.set -// ? _.bind(userDef.set, this) -// : noop -// } -// Object.defineProperty(this, key, def) -// } -// } -// } +function noop () {} +exports._initComputed = function () { + // var computed = this.$options.computed + var computed = this._computed + if (computed) { + for (var key in computed) { + var userDef = computed[key] + var def = { + enumerable: true, + configurable: true + } + if (typeof userDef === 'function') { + def.get = _.bind(userDef, this) + def.set = noop + } else { + def.get = userDef.get + ? _.bind(userDef.get, this) + : noop + def.set = userDef.set + ? _.bind(userDef.set, this) + : noop + } + Object.defineProperty(this, key, def) + } + } +} /** * Setup instance methods. Methods must be bound to the