component_spec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. var _ = require('../../../../src/util')
  2. var Vue = require('../../../../src/vue')
  3. if (_.inBrowser) {
  4. describe('v-component', function () {
  5. var el
  6. beforeEach(function () {
  7. el = document.createElement('div')
  8. document.body.appendChild(el)
  9. spyOn(_, 'warn')
  10. })
  11. afterEach(function () {
  12. document.body.removeChild(el)
  13. })
  14. it('static', function () {
  15. var vm = new Vue({
  16. el: el,
  17. template: '<div v-component="test"></div>',
  18. components: {
  19. test: {
  20. data: function () {
  21. return { a: 123 }
  22. },
  23. template: '{{a}}'
  24. }
  25. }
  26. })
  27. expect(el.innerHTML).toBe('<div>123</div><!--v-component-->')
  28. })
  29. it('replace', function () {
  30. var vm = new Vue({
  31. el: el,
  32. template: '<div v-component="test"></div>',
  33. components: {
  34. test: {
  35. replace: true,
  36. data: function () {
  37. return { a: 123 }
  38. },
  39. template: '<p>{{a}}</p>'
  40. }
  41. }
  42. })
  43. expect(el.innerHTML).toBe('<p>123</p><!--v-component-->')
  44. })
  45. it('inline-template', function () {
  46. var vm = new Vue({
  47. el: el,
  48. template: '<div v-component="test" inline-template>{{a}}</div>',
  49. data: {
  50. a: 'parent'
  51. },
  52. components: {
  53. test: {
  54. data: function () {
  55. return { a: 'child' }
  56. },
  57. template: 'child option template'
  58. }
  59. }
  60. })
  61. expect(el.innerHTML).toBe('<div>child</div><!--v-component-->')
  62. })
  63. it('block replace', function () {
  64. var vm = new Vue({
  65. el: el,
  66. template: '<div v-component="test"></div>',
  67. components: {
  68. test: {
  69. replace: true,
  70. data: function () {
  71. return { a: 123, b: 234 }
  72. },
  73. template: '<p>{{a}}</p><p>{{b}}</p>'
  74. }
  75. }
  76. })
  77. expect(el.innerHTML).toBe('<!--v-start--><p>123</p><p>234</p><!--v-end--><!--v-component-->')
  78. })
  79. it('dynamic', function (done) {
  80. var vm = new Vue({
  81. el: el,
  82. template: '<div v-component="{{view}}" v-attr="view:view"></div>',
  83. data: {
  84. view: 'a'
  85. },
  86. components: {
  87. a: {
  88. template: 'AAA',
  89. data: function () {
  90. return { view: 'a' }
  91. }
  92. },
  93. b: {
  94. template: 'BBB',
  95. data: function () {
  96. return { view: 'b' }
  97. }
  98. }
  99. }
  100. })
  101. expect(el.innerHTML).toBe('<div view="a">AAA</div><!--v-component-->')
  102. vm.view = 'b'
  103. _.nextTick(function () {
  104. expect(el.innerHTML).toBe('<div view="b">BBB</div><!--v-component-->')
  105. vm.view = ''
  106. _.nextTick(function () {
  107. expect(el.innerHTML).toBe('<!--v-component-->')
  108. done()
  109. })
  110. })
  111. })
  112. it('keep-alive', function (done) {
  113. var spyA = jasmine.createSpy()
  114. var spyB = jasmine.createSpy()
  115. var vm = new Vue({
  116. el: el,
  117. template: '<div v-component="{{view}}" keep-alive></div>',
  118. data: {
  119. view: 'a'
  120. },
  121. components: {
  122. a: {
  123. created: spyA,
  124. template: 'AAA'
  125. },
  126. b: {
  127. created: spyB,
  128. template: 'BBB'
  129. }
  130. }
  131. })
  132. expect(el.innerHTML).toBe('<div>AAA</div><!--v-component-->')
  133. expect(spyA.calls.count()).toBe(1)
  134. expect(spyB.calls.count()).toBe(0)
  135. vm.view = 'b'
  136. _.nextTick(function () {
  137. expect(el.innerHTML).toBe('<div>BBB</div><!--v-component-->')
  138. expect(spyA.calls.count()).toBe(1)
  139. expect(spyB.calls.count()).toBe(1)
  140. vm.view = 'a'
  141. _.nextTick(function () {
  142. expect(el.innerHTML).toBe('<div>AAA</div><!--v-component-->')
  143. expect(spyA.calls.count()).toBe(1)
  144. expect(spyB.calls.count()).toBe(1)
  145. vm.view = 'b'
  146. _.nextTick(function () {
  147. expect(el.innerHTML).toBe('<div>BBB</div><!--v-component-->')
  148. expect(spyA.calls.count()).toBe(1)
  149. expect(spyB.calls.count()).toBe(1)
  150. done()
  151. })
  152. })
  153. })
  154. })
  155. it('should compile parent template directives & content in parent scope', function (done) {
  156. var vm = new Vue({
  157. el: el,
  158. data: {
  159. ok: false,
  160. message: 'hello'
  161. },
  162. template: '<div v-component="test" v-show="ok">{{message}}</div>',
  163. components: {
  164. test: {
  165. template: '<div><content></content> {{message}}</div>',
  166. replace: true,
  167. data: function () {
  168. return {
  169. message: 'world'
  170. }
  171. }
  172. }
  173. }
  174. })
  175. expect(el.firstChild.style.display).toBe('none')
  176. expect(el.firstChild.textContent).toBe('hello world')
  177. vm.ok = true
  178. vm.message = 'bye'
  179. _.nextTick(function () {
  180. expect(el.firstChild.style.display).toBe('')
  181. expect(el.firstChild.textContent).toBe('bye world')
  182. done()
  183. })
  184. })
  185. it('parent content + v-if', function (done) {
  186. var vm = new Vue({
  187. el: el,
  188. data: {
  189. ok: false,
  190. message: 'hello'
  191. },
  192. template: '<div v-component="test" v-if="ok">{{message}}</div>',
  193. components: {
  194. test: {
  195. template: '<content></content> {{message}}',
  196. data: function () {
  197. return {
  198. message: 'world'
  199. }
  200. }
  201. }
  202. }
  203. })
  204. expect(el.textContent).toBe('')
  205. expect(vm._children.length).toBe(0)
  206. expect(vm._directives.length).toBe(1) // v-if
  207. vm.ok = true
  208. _.nextTick(function () {
  209. expect(vm._children.length).toBe(1)
  210. expect(vm._directives.length).toBe(3) // v-if, v-component, v-text
  211. expect(el.textContent).toBe('hello world')
  212. done()
  213. })
  214. })
  215. it('props', function () {
  216. var vm = new Vue({
  217. el: el,
  218. data: {
  219. list: [{a:1}, {a:2}]
  220. },
  221. template: '<ul v-component="test" collection="{{list}}"></ul>',
  222. components: {
  223. test: {
  224. template: '<li v-repeat="collection">{{a}}</li>',
  225. props: ['collection']
  226. }
  227. }
  228. })
  229. expect(el.innerHTML).toBe('<ul><li>1</li><li>2</li><!--v-repeat--></ul><!--v-component-->')
  230. })
  231. it('wait-for', function (done) {
  232. var vm = new Vue({
  233. el: el,
  234. data: {
  235. view: 'a'
  236. },
  237. template: '<div v-component="{{view}}" wait-for="ok"></div>',
  238. components: {
  239. a: {
  240. template: 'AAA'
  241. },
  242. b: {
  243. template: 'BBB'
  244. }
  245. }
  246. })
  247. vm._children[0].$emit('ok')
  248. vm.view = 'b'
  249. _.nextTick(function () {
  250. expect(el.textContent).toBe('AAA')
  251. // old vm is already removed, this is the new vm
  252. vm._children[0].$emit('ok')
  253. expect(el.textContent).toBe('BBB')
  254. done()
  255. })
  256. })
  257. it('transition-mode: in-out', function (done) {
  258. var spy1 = jasmine.createSpy('enter')
  259. var spy2 = jasmine.createSpy('leave')
  260. var next
  261. var vm = new Vue({
  262. el: el,
  263. data: {
  264. view: 'a'
  265. },
  266. template: '<div v-component="{{view}}" v-transition="test" transition-mode="in-out"></div>',
  267. components: {
  268. a: { template: 'AAA' },
  269. b: { template: 'BBB' }
  270. },
  271. transitions: {
  272. test: {
  273. enter: function (el, done) {
  274. spy1()
  275. next = done
  276. },
  277. leave: function (el, done) {
  278. spy2()
  279. done()
  280. }
  281. }
  282. }
  283. })
  284. expect(el.textContent).toBe('AAA')
  285. vm.view = 'b'
  286. _.nextTick(function () {
  287. expect(spy1).toHaveBeenCalled()
  288. expect(spy2).not.toHaveBeenCalled()
  289. expect(el.textContent).toBe('AAABBB')
  290. next()
  291. expect(spy2).toHaveBeenCalled()
  292. expect(el.textContent).toBe('BBB')
  293. done()
  294. })
  295. })
  296. it('transition-mode: out-in', function (done) {
  297. var spy1 = jasmine.createSpy('enter')
  298. var spy2 = jasmine.createSpy('leave')
  299. var next
  300. var vm = new Vue({
  301. el: el,
  302. data: {
  303. view: 'a'
  304. },
  305. template: '<div v-component="{{view}}" v-transition="test" transition-mode="out-in"></div>',
  306. components: {
  307. a: { template: 'AAA' },
  308. b: { template: 'BBB' }
  309. },
  310. transitions: {
  311. test: {
  312. enter: function (el, done) {
  313. spy2()
  314. done()
  315. },
  316. leave: function (el, done) {
  317. spy1()
  318. next = done
  319. }
  320. }
  321. }
  322. })
  323. expect(el.textContent).toBe('AAA')
  324. vm.view = 'b'
  325. _.nextTick(function () {
  326. expect(spy1).toHaveBeenCalled()
  327. expect(spy2).not.toHaveBeenCalled()
  328. expect(el.textContent).toBe('AAA')
  329. next()
  330. expect(spy2).toHaveBeenCalled()
  331. expect(el.textContent).toBe('BBB')
  332. done()
  333. })
  334. })
  335. it('teardown', function (done) {
  336. var vm = new Vue({
  337. el: el,
  338. template: '<div v-component="{{view}}" keep-alive></div>',
  339. data: {
  340. view: 'test'
  341. },
  342. components: {
  343. test: {},
  344. test2: {}
  345. }
  346. })
  347. vm.view = 'test2'
  348. _.nextTick(function () {
  349. expect(vm._children.length).toBe(2)
  350. var child = vm._children[0]
  351. var child2 = vm._children[1]
  352. vm._directives[0].unbind()
  353. expect(vm._directives[0].cache).toBeNull()
  354. expect(vm._children.length).toBe(0)
  355. expect(child._isDestroyed).toBe(true)
  356. expect(child2._isDestroyed).toBe(true)
  357. done()
  358. })
  359. })
  360. it('already mounted warn', function () {
  361. el.setAttribute('v-component', 'test')
  362. var vm = new Vue({
  363. el: el
  364. })
  365. expect(hasWarned(_, 'already mounted instance')).toBe(true)
  366. })
  367. })
  368. }