inheritance.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. var Observer = require('../src/observer/observer')
  2. var _ = require('../src/util')
  3. function Vue (options) {
  4. // scope prototypal inehritance
  5. var scope = this._scope = options.parent
  6. ? Object.create(options.parent._scope)
  7. : {}
  8. // copy instantiation data into scope
  9. for (var key in options.data) {
  10. if (key in scope) {
  11. // key exists on the scope prototype chain
  12. // cannot use direct set here, because in the parent
  13. // scope everything is already getter/setter and we
  14. // need to overwrite them with Object.defineProperty.
  15. _.define(scope, key, options.data[key], true)
  16. } else {
  17. scope[key] = options.data[key]
  18. }
  19. }
  20. // create observer
  21. // pass in noProto:true to avoid mutating the __proto__
  22. var ob = this._observer = Observer.create(this._scope, true)
  23. // relay change events from parent scope.
  24. // this ensures the current Vue instance is aware of
  25. // stuff going on up in the scope chain.
  26. if (options.parent) {
  27. var po = options.parent._observer
  28. ;['set', 'mutate', 'added', 'deleted'].forEach(function (event) {
  29. po.on(event, function (key, a, b) {
  30. if (!scope.hasOwnProperty(key)) {
  31. ob.emit(event, key, a, b)
  32. }
  33. })
  34. })
  35. }
  36. // proxy everything on self
  37. for (var key in this._scope) {
  38. _.proxy(this, this._scope, key)
  39. }
  40. // also proxy newly added keys.
  41. var self = this
  42. ob.on('added', function (key) {
  43. if (!self.hasOwnProperty(key)) {
  44. _.proxy(self, scope, key)
  45. }
  46. })
  47. }
  48. Vue.prototype.$add = function (key, val) {
  49. this._scope.$add.call(this._scope, key, val)
  50. }
  51. Vue.prototype.$delete = function (key) {
  52. this._scope.$delete.call(this._scope, key)
  53. }
  54. window.vm = new Vue({
  55. data: {
  56. a: 'go!',
  57. b: 2,
  58. c: {
  59. d: 3
  60. },
  61. arr: [{a:1}, {a:2}, {a:3}],
  62. get hello () {
  63. return 'hello!' + this.a
  64. },
  65. go: function () {
  66. console.log(this.a)
  67. }
  68. }
  69. })
  70. window.child = new Vue({
  71. parent: vm,
  72. data: {
  73. a: 1,
  74. change: function () {
  75. this.c.d = 4
  76. this.b = 456 // Unlike Angular, setting primitive values in Vue WILL affect outer scope,
  77. // unless you overwrite it in the instantiation data!
  78. }
  79. }
  80. })
  81. vm._observer.on('set', function (key, val) {
  82. console.log('vm set:' + key.replace(/[\b]/g, '.'), val)
  83. })
  84. child._observer.on('set', function (key, val) {
  85. console.log('child set:' + key.replace(/[\b]/g, '.'), val)
  86. })
  87. vm._observer.on('mutate', function (key, val) {
  88. console.log('vm mutate:' + key.replace(/[\b]/g, '.'), val)
  89. })
  90. child._observer.on('mutate', function (key, val) {
  91. console.log('child mutate:' + key.replace(/[\b]/g, '.'), val)
  92. })