component_spec.js 9.9 KB

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