main.js 4.3 KB

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