component_spec.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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. _.nextTick(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. _.nextTick(function () {
  297. expect(spy2).toHaveBeenCalled()
  298. _.nextTick(function () {
  299. expect(el.textContent).toBe('BBB')
  300. done()
  301. })
  302. })
  303. })
  304. })
  305. it('transition-mode: out-in', function (done) {
  306. var spy1 = jasmine.createSpy('enter')
  307. var spy2 = jasmine.createSpy('leave')
  308. var next
  309. var vm = new Vue({
  310. el: el,
  311. data: {
  312. view: 'a'
  313. },
  314. template: '<component is="{{view}}" v-transition="test" transition-mode="out-in"></component>',
  315. components: {
  316. a: { template: 'AAA' },
  317. b: { template: 'BBB' }
  318. },
  319. transitions: {
  320. test: {
  321. enter: function (el, done) {
  322. spy2()
  323. _.nextTick(done)
  324. },
  325. leave: function (el, done) {
  326. spy1()
  327. next = done
  328. }
  329. }
  330. }
  331. })
  332. expect(el.textContent).toBe('AAA')
  333. vm.view = 'b'
  334. _.nextTick(function () {
  335. expect(spy1).toHaveBeenCalled()
  336. expect(spy2).not.toHaveBeenCalled()
  337. expect(el.textContent).toBe('AAA')
  338. next()
  339. expect(spy2).toHaveBeenCalled()
  340. expect(el.textContent).toBe('BBB')
  341. done()
  342. })
  343. })
  344. it('teardown', function (done) {
  345. var vm = new Vue({
  346. el: el,
  347. template: '<component is="{{view}}" keep-alive></component>',
  348. data: {
  349. view: 'test'
  350. },
  351. components: {
  352. test: {},
  353. test2: {}
  354. }
  355. })
  356. vm.view = 'test2'
  357. _.nextTick(function () {
  358. expect(vm._children.length).toBe(2)
  359. var child = vm._children[0]
  360. var child2 = vm._children[1]
  361. vm._directives[0].unbind()
  362. expect(vm._directives[0].cache).toBeNull()
  363. expect(vm._children.length).toBe(0)
  364. expect(child._isDestroyed).toBe(true)
  365. expect(child2._isDestroyed).toBe(true)
  366. done()
  367. })
  368. })
  369. it('already mounted warn', function () {
  370. el.setAttribute('v-_component', 'test')
  371. var vm = new Vue({
  372. el: el
  373. })
  374. expect(hasWarned(_, 'already mounted instance')).toBe(true)
  375. })
  376. })
  377. }