Evan You пре 11 година
родитељ
комит
b5bfc59a70
9 измењених фајлова са 256 додато и 7 уклоњено
  1. 5 2
      CONTRIBUTING.md
  2. 2 2
      component.json
  3. 0 1
      src/batcher.js
  4. 137 0
      src/emitter.js
  5. 0 0
      src/observer/array.js
  6. 0 0
      src/observer/object.js
  7. 75 0
      src/observer/observer.js
  8. 29 1
      src/util.js
  9. 8 1
      src/vue.js

+ 5 - 2
CONTRIBUTING.md

@@ -26,10 +26,13 @@ Hi! I’m really excited that you are interested in contributing to Vue.js. Befo
 ## Code Style
 
 - [No semicolons unless necessary](http://inimino.org/~inimino/blog/javascript_semicolons).
+- Follow JSDoc.
 - 2 spaces indentation.
 - multiple var declarations.
-- align equal signs where possible.
-- Return early in one line if possible.
+- align equal signs where appropriate.
+- Return early.
+- 1 space after `function`
+- 1 space between arguments, but not between parens.
 - When in doubt, read the source code.
 - Break long ternary conditionals like this:
 

+ 2 - 2
component.json

@@ -26,9 +26,9 @@
     "src/instance/dom.js",
     "src/instance/events.js",
     "src/instance/lifecycle.js",
+    "src/observer/array.js",
+    "src/observer/object.js",
     "src/observer/observer.js",
-    "src/observer/watch-array.js",
-    "src/observer/watch-object.js",
     "src/parsers/directive.js",
     "src/parsers/expression.js",
     "src/parsers/path.js",

+ 0 - 1
src/batcher.js

@@ -1 +0,0 @@
-module.exports = 123

+ 137 - 0
src/emitter.js

@@ -0,0 +1,137 @@
+/**
+ * Simple event emitter based on component/emitter.
+ *
+ * @constructor
+ * @param {Object} ctx - the context to call listners with.
+ */
+
+function Emitter (ctx) {
+  this._ctx = ctx || this
+}
+
+var p = Emitter.prototype
+
+/**
+ * Listen on the given `event` with `fn`.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ */
+
+p.on = function (event, fn) {
+  this._cbs = this._cbs || {}
+  ;(this._cbs[event] = this._cbs[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
+ * @return {Emitter}
+ */
+
+p.once = function (event, fn) {
+  var self = this
+  this._cbs = this._cbs || {}
+
+  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
+ * @return {Emitter}
+ */
+ 
+p.off = function (event, fn) {
+  this._cbs = this._cbs || {}
+
+  // all
+  if (!arguments.length) {
+    this._cbs = {}
+    return this
+  }
+
+  // specific event
+  var callbacks = this._cbs[event]
+  if (!callbacks) return this
+
+  // remove all handlers
+  if (arguments.length === 1) {
+    delete this._cbs[event]
+    return this
+  }
+
+  // remove specific handler
+  var cb
+  for (var i = 0; i < callbacks.length; i++) {
+    cb = callbacks[i]
+    if (cb === fn || cb.fn === fn) {
+      callbacks.splice(i, 1)
+      break
+    }
+  }
+  return this
+}
+
+/**
+ * The internal, faster emit with fixed amount of arguments
+ * using Function.call.
+ *
+ * @param {Object} event
+ * @return {Emitter}
+ */
+
+p.emit = function (event, a, b, c) {
+  this._cbs = this._cbs || {}
+  var callbacks = this._cbs[event]
+
+  if (callbacks) {
+    callbacks = callbacks.slice(0)
+    for (var i = 0, len = callbacks.length; i < len; i++) {
+      callbacks[i].call(this._ctx, a, b, c)
+    }
+  }
+
+  return this
+}
+
+/**
+ * The external emit using Function.apply, used
+ * by Vue instance event methods.
+ *
+ * @param {Object} event
+ * @return {Emitter}
+ */
+
+p.applyEmit = function (event) {
+  this._cbs = this._cbs || {}
+  var callbacks = this._cbs[event], args
+
+  if (callbacks) {
+    callbacks = callbacks.slice(0)
+    args = callbacks.slice.call(arguments, 1)
+    for (var i = 0, len = callbacks.length; i < len; i++) {
+      callbacks[i].apply(this._ctx, args)
+    }
+  }
+
+  return this
+}
+
+module.exports = Emitter

+ 0 - 0
src/observer/watch-array.js → src/observer/array.js


+ 0 - 0
src/observer/watch-object.js → src/observer/object.js


+ 75 - 0
src/observer/observer.js

@@ -0,0 +1,75 @@
+var _ = require('../util')
+var Emitter = require('../emitter')
+
+/**
+ * Observer class that are attached to each observed
+ * object. They are essentially event emitters, but can
+ * connect to each other and relay the events up the nested
+ * object chain.
+ *
+ * @constructor
+ * @extends Emitter
+ * @private
+ */
+
+function Observer () {
+  Emitter.call(this)
+  this.connections = Object.create(null)
+}
+
+var p = Observer.prototype = Object.create(Emitter.prototype)
+
+/**
+ * Observe an object of unkown type.
+ *
+ * @param {*} obj
+ * @return {Boolean} - returns true if successfully observed.
+ */
+
+p.observe = function (obj) {
+  if (obj && obj.$observer) {
+    // already observed
+    return
+  }
+  if (_.isArray(obj)) {
+    this.observeArray(obj)
+    return true
+  }
+  if (_.isObject(obj)) {
+    this.observeObject(obj)
+    return true
+  }
+}
+
+/**
+ * Connect to another Observer instance,
+ * capture its get/set/mutate events and relay the events
+ * while prepending a key segment to the path.
+ *
+ * @param {Observer} target
+ * @param {String} key
+ */
+
+p.connect = function (target, key) {
+
+}
+
+/**
+ * Disconnect from a connected target Observer.
+ *
+ * @param {Observer} target
+ * @param {String} key
+ */
+
+p.disconnect = function (target, key) {
+  
+}
+
+/**
+ * Mixin Array and Object observe methods
+ */
+
+_.mixin(p, require('./array'))
+_.mixin(p, require('./object'))
+
+module.exports = Observer

+ 29 - 1
src/util.js

@@ -1,4 +1,9 @@
-// common utils
+/**
+ * Mix properties into target object.
+ *
+ * @param {Object} target
+ * @param {Object} mixin
+ */
 
 exports.mixin = function (target, mixin) {
   for (var key in mixin) {
@@ -6,4 +11,27 @@ exports.mixin = function (target, mixin) {
       target[key] = mixin[key]
     }
   }
+}
+
+/**
+ * Object type check. Only returns true
+ * for plain JavaScript objects.
+ *
+ * @param {*} obj
+ * @return {Boolean}
+ */
+
+exports.isObject = function (obj) {
+  return Object.prototype.toString.call(obj) === '[object Object]'
+}
+
+/**
+ * Array type check.
+ *
+ * @param {*} obj
+ * @return {Boolean}
+ */
+
+exports.isArray = function (obj) {
+  return Array.isArray(obj)
 }

+ 8 - 1
src/vue.js

@@ -2,13 +2,18 @@ var _        = require('./util')
 var Compiler = require('./compiler/compiler')
 
 /**
- *  The exposed Vue constructor.
+ * The exposed Vue constructor.
+ *
+ * @constructor
+ * @public
  */
+
 function Vue (options) {
   this._compiler = new Compiler(this, options)
 }
 
 // mixin instance methods
+
 var p = Vue.prototype
 _.mixin(p, require('./instance/lifecycle'))
 _.mixin(p, require('./instance/data'))
@@ -16,9 +21,11 @@ _.mixin(p, require('./instance/dom'))
 _.mixin(p, require('./instance/events'))
 
 // mixin asset registers
+
 _.mixin(Vue, require('./api/asset-register'))
 
 // static methods
+
 Vue.config   = require('./api/config')
 Vue.use      = require('./api/use')
 Vue.require  = require('./api/require')