main.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. var config = require('./config'),
  2. ViewModel = require('./viewmodel'),
  3. utils = require('./utils'),
  4. makeHash = utils.hash,
  5. assetTypes = ['directive', 'filter', 'partial', 'effect', 'component']
  6. // require these so Browserify can catch them
  7. // so they can be used in Vue.require
  8. require('./observer')
  9. require('./transition')
  10. ViewModel.options = config.globalAssets = {
  11. directives : require('./directives'),
  12. filters : require('./filters'),
  13. partials : makeHash(),
  14. effects : makeHash(),
  15. components : makeHash()
  16. }
  17. /**
  18. * Expose asset registration methods
  19. */
  20. assetTypes.forEach(function (type) {
  21. ViewModel[type] = function (id, value) {
  22. var hash = this.options[type + 's']
  23. if (!hash) {
  24. hash = this.options[type + 's'] = makeHash()
  25. }
  26. if (!value) return hash[id]
  27. if (type === 'partial') {
  28. value = utils.toFragment(value)
  29. } else if (type === 'component') {
  30. value = utils.toConstructor(value)
  31. } else if (type === 'filter') {
  32. utils.checkFilter(value)
  33. }
  34. hash[id] = value
  35. return this
  36. }
  37. })
  38. /**
  39. * Set config options
  40. */
  41. ViewModel.config = function (opts, val) {
  42. if (typeof opts === 'string') {
  43. if (val === undefined) {
  44. return config[opts]
  45. } else {
  46. config[opts] = val
  47. }
  48. } else {
  49. utils.extend(config, opts)
  50. }
  51. return this
  52. }
  53. /**
  54. * Expose an interface for plugins
  55. */
  56. ViewModel.use = function (plugin) {
  57. if (typeof plugin === 'string') {
  58. try {
  59. plugin = require(plugin)
  60. } catch (e) {
  61. utils.warn('Cannot find plugin: ' + plugin)
  62. return
  63. }
  64. }
  65. // additional parameters
  66. var args = [].slice.call(arguments, 1)
  67. args.unshift(this)
  68. if (typeof plugin.install === 'function') {
  69. plugin.install.apply(plugin, args)
  70. } else {
  71. plugin.apply(null, args)
  72. }
  73. return this
  74. }
  75. /**
  76. * Expose internal modules for plugins
  77. */
  78. ViewModel.require = function (path) {
  79. return require('./' + path)
  80. }
  81. ViewModel.extend = extend
  82. ViewModel.nextTick = utils.nextTick
  83. /**
  84. * Expose the main ViewModel class
  85. * and add extend method
  86. */
  87. function extend (options) {
  88. var ParentVM = this
  89. // extend data options need to be copied
  90. // on instantiation
  91. if (options.data) {
  92. options.defaultData = options.data
  93. delete options.data
  94. }
  95. // inherit options
  96. // but only when the super class is not the native Vue.
  97. if (ParentVM !== ViewModel) {
  98. options = inheritOptions(options, ParentVM.options, true)
  99. }
  100. utils.processOptions(options)
  101. var ExtendedVM = function (opts, asParent) {
  102. if (!asParent) {
  103. opts = inheritOptions(opts, options, true)
  104. }
  105. ParentVM.call(this, opts, true)
  106. }
  107. // inherit prototype props
  108. var proto = ExtendedVM.prototype = Object.create(ParentVM.prototype)
  109. utils.defProtected(proto, 'constructor', ExtendedVM)
  110. // allow extended VM to be further extended
  111. ExtendedVM.extend = extend
  112. ExtendedVM.super = ParentVM
  113. ExtendedVM.options = options
  114. // allow extended VM to add its own assets
  115. assetTypes.forEach(function (type) {
  116. ExtendedVM[type] = ViewModel[type]
  117. })
  118. // allow extended VM to use plugins
  119. ExtendedVM.use = ViewModel.use
  120. ExtendedVM.require = ViewModel.require
  121. return ExtendedVM
  122. }
  123. /**
  124. * Inherit options
  125. *
  126. * For options such as `data`, `vms`, `directives`, 'partials',
  127. * they should be further extended. However extending should only
  128. * be done at top level.
  129. *
  130. * `proto` is an exception because it's handled directly on the
  131. * prototype.
  132. *
  133. * `el` is an exception because it's not allowed as an
  134. * extension option, but only as an instance option.
  135. */
  136. function inheritOptions (child, parent, topLevel) {
  137. child = child || {}
  138. if (!parent) return child
  139. for (var key in parent) {
  140. if (key === 'el') continue
  141. var val = child[key],
  142. parentVal = parent[key]
  143. if (topLevel && typeof val === 'function' && parentVal) {
  144. // merge hook functions into an array
  145. child[key] = [val]
  146. if (Array.isArray(parentVal)) {
  147. child[key] = child[key].concat(parentVal)
  148. } else {
  149. child[key].push(parentVal)
  150. }
  151. } else if (
  152. topLevel &&
  153. (utils.isTrueObject(val) || utils.isTrueObject(parentVal))
  154. && !(parentVal instanceof ViewModel)
  155. ) {
  156. // merge toplevel object options
  157. child[key] = inheritOptions(val, parentVal)
  158. } else if (val === undefined) {
  159. // inherit if child doesn't override
  160. child[key] = parentVal
  161. }
  162. }
  163. return child
  164. }
  165. module.exports = ViewModel