Last active
June 15, 2017 02:52
-
-
Save zmmbreeze/8e0c97fbd99e94426e346c6fb3d79be4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue'; | |
/** | |
* 代理字段到当前实例上 | |
* @eg: | |
* const src = {name: 'b'}; | |
* const target = {}; | |
* proxy(['name'], target, src); | |
* console.log(target.name); // => b | |
* target.name = 'a'; | |
* console.log(src.name); // => a | |
* | |
* @param {Object} target 代理对象 | |
* @param {Array.<string>} keyNames 字段名数组 | |
* @param {Object} src 被代理的目标对象 | |
* @param {Object} options 可选配置 | |
* @param {boolean} options.readonly 是否只读 | |
* @param {function(string):string} options.nameTransform 字段名和被代理对象上字段名不一样, | |
* 可以使用此函数做转化 | |
*/ | |
function proxy(target, keyNames, src, options) { | |
const readonly = options && options.readonly; | |
const nameTransform = options && options.nameTransform; | |
keyNames.forEach((keyName) => { | |
const targetName = nameTransform ? nameTransform(keyName) : keyName; | |
const descriptor = { | |
enumerable: true, | |
writable: !readonly, | |
get() { | |
return src[targetName]; | |
} | |
}; | |
if (!readonly) { | |
descriptor.set = function (nextValue) { | |
src[targetName] = nextValue; | |
}; | |
} | |
Object.defineProperty(target, keyName, descriptor); | |
}); | |
} | |
/** | |
* 使一个类变成部分数据为Observable,利用了Vue的能力 | |
* @param {Object} instance 类的实例 | |
* @param {Object} options 可选配置 | |
* @param {Object=} options.data https://vuejs.org/v2/api/#data | |
* @param {Object=} options.computed https://vuejs.org/v2/api/#computed | |
* @param {Object=} options.watch https://vuejs.org/v2/api/#watch | |
* @param {Array.<string>=} options.proxyNames 代理到instance上面的属性名数组 | |
* 默认是Object.keys(options.data); | |
* @param {Array.<string>=} options.readonlyProxyNames 代理到instance上面的只读属性名数组 | |
* 默认是Object.keys(options.computed); | |
* @param {string} vmName 默认为 _vm | |
*/ | |
export default function observeData(instance, options) { | |
const vmName = options.vmName || '_vm'; | |
instance[vmName] = new Vue({ | |
data: options.data, | |
watch: options.watch, | |
computed: options.computed | |
}); | |
instance.proxy = function () { | |
const args = Array.from(arguments); | |
args.unshift(this); | |
proxy.apply(this, args); | |
}; | |
proxy(instance, options.proxyNames || Object.keys(options.data), instance[vmName]); | |
proxy(instance, options.readonlyProxyNames || Object.keys(options.computed), instance[vmName], { | |
readonly: true | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 使一个类变成部分数据为Observable,利用了Vue的能力 | |
* @param {Object} instance 类的实例 | |
* @param {Object} options 可选配置 | |
* @param {Object=} options.data https://vuejs.org/v2/api/#data | |
* @param {Object=} options.computed https://vuejs.org/v2/api/#computed | |
* @param {Object=} options.watch https://vuejs.org/v2/api/#watch | |
*/ | |
export default function observeData(instance, options) { | |
Object.defineProperty(instance, '$watch', { | |
enumerable: true, | |
value: function () { | |
this._watchers = []; | |
return Vue.prototype.$watch.apply(this, arguments); | |
} | |
}); | |
if (options.data) { | |
Object.keys(options.data).forEach((key) => { | |
const value = options.data[key]; | |
Vue.util.defineReactive(instance, key, value); | |
}); | |
} | |
if (options.watch) { | |
Object.keys(options.watch).forEach((key) => { | |
const value = options.watch[key]; | |
Vue.prototype.$watch.call(instance, key, value); | |
}); | |
} | |
if (options.computed) { | |
Object.keys(options.computed).forEach((key) => { | |
const getter = options.computed[key]; | |
let dirty = false; | |
let cachedValue; | |
Object.defineProperty(instance, key, { | |
enumerable: true, | |
get: () => { | |
if (!dirty) { | |
return cachedValue; | |
} | |
cachedValue = getter(); | |
return cachedValue; | |
} | |
}); | |
instance.$watch( | |
function () { | |
cachedValue = getter.apply(this, arguments); | |
return cachedValue; | |
}, | |
function () { | |
dirty = true; | |
} | |
); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment