diff --git a/src/runtime/instance/api.js b/src/runtime/instance/api.js deleted file mode 100644 index 20dea88c2..000000000 --- a/src/runtime/instance/api.js +++ /dev/null @@ -1,3 +0,0 @@ -export function apiMixin (Vue) { - -} diff --git a/src/runtime/instance/events.js b/src/runtime/instance/events.js index 24884112c..673e0fd5d 100644 --- a/src/runtime/instance/events.js +++ b/src/runtime/instance/events.js @@ -1,7 +1,86 @@ -export function initEvents (vm) { +import { toArray } from '../util/index' +export function initEvents (vm) { + vm._events = Object.create(null) } export function eventsMixin (Vue) { + Vue.prototype.$on = function (event, fn) { + (this._events[event] || (this._events[event] = [])) + .push(fn) + return this + } + /** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + */ + + Vue.prototype.$once = function (event, fn) { + var self = this + function on () { + self.$off(event, on) + fn.apply(this, arguments) + } + on.fn = fn + this.$on(event, on) + return this + } + + /** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + */ + + Vue.prototype.$off = function (event, fn) { + var cbs + // all + if (!arguments.length) { + this._events = Object.create(null) + return this + } + // specific event + cbs = this._events[event] + if (!cbs) { + return this + } + if (arguments.length === 1) { + this._events[event] = null + return this + } + // specific handler + var cb + var i = cbs.length + while (i--) { + cb = cbs[i] + if (cb === fn || cb.fn === fn) { + cbs.splice(i, 1) + break + } + } + return this + } + + /** + * Trigger an event on self. + * + * @param {String} event + */ + + Vue.prototype.$emit = function (event) { + var cbs = this._events[event] + if (cbs) { + cbs = cbs.length > 1 ? toArray(cbs) : cbs + var args = toArray(arguments, 1) + for (var i = 0, l = cbs.length; i < l; i++) { + cbs[i].apply(this, args) + } + } + } } diff --git a/src/runtime/instance/index.js b/src/runtime/instance/index.js index 6e5f7706c..133363fc2 100644 --- a/src/runtime/instance/index.js +++ b/src/runtime/instance/index.js @@ -1,7 +1,6 @@ import { initState, stateMixin } from './state' import { initRender, renderMixin } from './render' import { initEvents, eventsMixin } from './events' -import { apiMixin } from './api' export default function Vue (options) { this.$options = options @@ -14,4 +13,3 @@ export default function Vue (options) { stateMixin(Vue) eventsMixin(Vue) renderMixin(Vue) -apiMixin(Vue) diff --git a/src/runtime/instance/state.js b/src/runtime/instance/state.js index db246ce26..3aaca328e 100644 --- a/src/runtime/instance/state.js +++ b/src/runtime/instance/state.js @@ -83,35 +83,14 @@ function makeComputedGetter (getter, owner) { } function initMethods (vm) { - var methods = vm.$options.methods + const methods = vm.$options.methods if (methods) { - for (var key in methods) { + for (let key in methods) { vm[key] = bind(methods[key], vm) } } } -function proxy (vm, key) { - if (!isReserved(key)) { - Object.defineProperty(vm, key, { - configurable: true, - enumerable: true, - get: function proxyGetter () { - return vm._data[key] - }, - set: function proxySetter (val) { - vm._data[key] = val - } - }) - } -} - -function unproxy (vm, key) { - if (!isReserved(key)) { - delete vm[key] - } -} - export function stateMixin (Vue) { Object.defineProperty(Vue.prototype, '$data', { get () { @@ -123,6 +102,18 @@ export function stateMixin (Vue) { } } }) + + Vue.prototype.$watch = function (fn, cb, options) { + options = options || {} + options.user = true + const watcher = new Watcher(this, fn, cb, options) + if (options.immediate) { + cb.call(this, watcher.value) + } + return function unwatchFn () { + watcher.teardown() + } + } } function setData (vm, newData) { @@ -154,3 +145,24 @@ function setData (vm, newData) { observe(newData, vm) vm.$forceUpdate() } + +function proxy (vm, key) { + if (!isReserved(key)) { + Object.defineProperty(vm, key, { + configurable: true, + enumerable: true, + get: function proxyGetter () { + return vm._data[key] + }, + set: function proxySetter (val) { + vm._data[key] = val + } + }) + } +} + +function unproxy (vm, key) { + if (!isReserved(key)) { + delete vm[key] + } +} diff --git a/src/runtime/observer/watcher.js b/src/runtime/observer/watcher.js index 4357577b5..be04baa34 100644 --- a/src/runtime/observer/watcher.js +++ b/src/runtime/observer/watcher.js @@ -2,6 +2,7 @@ import config from '../config' import Dep from './dep' import { pushWatcher } from './batcher' import { + warn, extend, isArray, isObject, @@ -51,7 +52,10 @@ export default function Watcher (vm, expOrFn, cb, options) { if (isFn) { this.getter = expOrFn } else { - this.getter = new Function(`with(this){return ${expOrFn}}`) + this.getter = function () {} + process.env.NODE_ENV !== 'production' && warn( + 'Watcher only accpets function.' + ) } this.value = this.lazy ? undefined