Skip to content

Commit 77c359f

Browse files
committed
some small improvements
1 parent ea2bfaa commit 77c359f

File tree

2 files changed

+130
-103
lines changed

2 files changed

+130
-103
lines changed

src/directives/element/slot.js

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import {
99
export default {
1010

1111
priority: SLOT,
12-
params: ['name','plugin'],
12+
params: ['name','plugin',''],
1313

1414
bind () {
1515
// this was resolved during component transclusion
1616
var name = this.params.name || 'default'
1717
var content = this.vm._slotContents && this.vm._slotContents[name]
1818
if (!content || !content.hasChildNodes()) {
19-
this.fallback()
19+
this.compile(extractContent(this.el, true), this.vm)
2020
} else {
2121
this.compile(content.cloneNode(true), this.vm._context, this.vm)
2222
}
@@ -44,45 +44,43 @@ export default {
4444
: this._scope
4545

4646
if (this.params.plugin) {
47-
console.log(this)
47+
if (!host) {
48+
// TODO warn to use plugin only within components
49+
}
4850
// copy all remaining attributes from slot to all direct children
4951
let attrs = this.el.attributes
5052
for(let i = attrs.length - 1; i >= 0; i--) {
5153
let name = attrs[i].name,
5254
value = attrs[i].value,
5355
children = content.children
54-
// prefix value
55-
// TODO properly handle v-bind
56-
if (name[0]===':') {
57-
value = '__'+value
58-
}
59-
// TODO properly handle v-on
6056
for(let j = 0, len = children.length; j < len; j++) {
6157
// TODO warn if child can't have attributes?
62-
children[j].setAttribute(name,value)
58+
if (!(children[j].hasAttribute(name) ||
59+
(name[0]===':' && children[j].hasAttribute('v-bind'+name)) ||
60+
(name[0]==='@' && children[j].hasAttribute('v-on:'+name.slice(1)))
61+
)) {
62+
children[j].setAttribute(name,value)
63+
}
6364
}
6465
}
65-
if (!scope) {
66-
scope = {}
67-
}
66+
// use v-for scope when available
67+
scope = this._frag ? this._frag.scope : scope || {}
68+
6869
// add all data from context to scope
6970
for(let data in context._data) {
70-
defineReactive(scope,data,context._data[data])
71+
if (scope[data] == null) {
72+
defineReactive(scope,data,context._data[data])
73+
}
7174
}
7275
// add all data from host to scope with prefixed names
7376
for(let data in host._data) {
74-
defineReactive(scope,'__'+data,host._data[data])
75-
}
76-
// add all data from v-for
77-
if (this._frag) {
78-
// TODO how to get the data out of the v-for scope?
79-
defineReactive(scope,'__item',this._frag.scope.item)
77+
defineReactive(scope,'_'+data,host._data[data])
8078
}
79+
// child relations test: how to get the slot content to be comp11 child?
80+
this.unlink = context.$compile(content, host, scope, this._frag)
81+
} else {
82+
this.unlink = context.$compile(content, host, scope, this._frag)
8183
}
82-
83-
this.unlink = context.$compile(
84-
content, host, scope, this._frag
85-
)
8684
}
8785
if (content) {
8886
replace(this.el, content)
@@ -91,10 +89,6 @@ export default {
9189
}
9290
},
9391

94-
fallback () {
95-
this.compile(extractContent(this.el, true), this.vm)
96-
},
97-
9892
unbind () {
9993
if (this.unlink) {
10094
this.unlink()

test/unit/specs/directives/element/slot_spec.js

Lines changed: 108 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -458,61 +458,6 @@ describe('Slot Distribution', function () {
458458
expect('"slot" attribute must be static').toHaveBeenWarned()
459459
})
460460

461-
it('plugin directive - scoped data', function () {
462-
var vm = new Vue({
463-
el: el,
464-
template: '<comp1><comp2>{{text}}</comp2></comp1>',
465-
data: {
466-
text:'main'
467-
},
468-
components: {
469-
comp1: {
470-
template: '<div><slot plugin :text="text"></slot></div>',
471-
data: function(){
472-
return {
473-
text:'comp1'
474-
}
475-
}
476-
},
477-
comp2: {
478-
props: {
479-
text: {
480-
type: String
481-
}
482-
},
483-
template: '<div>{{text}}<slot></slot></div>'
484-
}
485-
}
486-
})
487-
expect(vm.$el.textContent).toBe('comp1main')
488-
})
489-
490-
it('plugin directive - child relations', function () {
491-
var vm = new Vue({
492-
el: el,
493-
template: '<comp1><comp2></comp2></comp1>',
494-
data: {
495-
text:'main'
496-
},
497-
components: {
498-
comp1: {
499-
template: '<div><comp11><slot></slot><comp11></div>',
500-
components: {
501-
comp11: {
502-
template: '<div><slot plugin></slot></div>'
503-
}
504-
}
505-
},
506-
comp2: {
507-
template: '<div><slot></slot></div>'
508-
}
509-
}
510-
})
511-
expect(vm.$children[0].$children.length).toBe(1)
512-
expect(vm.$children[0].$children[0].$options.name).toBe("comp11")
513-
expect(vm.$children[0].$children[0].$children[0].$options.name).toBe("comp2")
514-
})
515-
516461
it('child relations', function () {
517462
var vm = new Vue({
518463
el: el,
@@ -539,31 +484,119 @@ describe('Slot Distribution', function () {
539484
expect(vm.$children[0].$children[1].$children.length).toBe(0)
540485
})
541486

542-
it('plugin directive - v-for', function () {
543-
var vm = new Vue({
544-
el: el,
545-
template: '<comp1><comp2></comp2></comp1>',
546-
data: {
547-
text:'main'
548-
},
549-
components: {
550-
comp1: {
551-
template: '<div><slot plugin :item="item" v-for="item in data"></slot></div>',
552-
data: function() {
553-
return {data:[{name:"foo"},{name:"bar"}]}
487+
488+
describe('plugin directive', function() {
489+
490+
it('scoped data', function () {
491+
var vm = new Vue({
492+
el: el,
493+
template: '<comp1><comp2>{{text}}</comp2></comp1>',
494+
data: {
495+
text:'main'
496+
},
497+
components: {
498+
comp1: {
499+
template: '<div><slot plugin :text="_text"></slot></div>',
500+
data: function(){
501+
return {
502+
text:'comp1'
503+
}
554504
}
505+
},
506+
comp2: {
507+
props: {
508+
text: {
509+
type: String
510+
}
511+
},
512+
template: '<div>{{text}}<slot></slot></div>'
513+
}
514+
}
515+
})
516+
expect(vm.$el.textContent).toBe('comp1main')
517+
})
518+
519+
it('scoped data hierarchy', function () {
520+
var vm = new Vue({
521+
el: el,
522+
template: '<comp1><comp2 :text="text">{{text}}</comp2></comp1>',
523+
data: {
524+
text:'main'
555525
},
556-
comp2: {
557-
props: {
558-
item: {
559-
type: Object
526+
components: {
527+
comp1: {
528+
template: '<div><slot plugin :text="_text"></slot></div>',
529+
data: function(){
530+
return {
531+
text:'comp1'
532+
}
560533
}
561534
},
562-
template: '<div>{{item.name}}</div>'
535+
comp2: {
536+
props: {
537+
text: {
538+
type: String
539+
}
540+
},
541+
template: '<div>{{text}}<slot></slot></div>'
542+
}
563543
}
564-
}
544+
})
545+
expect(vm.$el.textContent).toBe('mainmain')
546+
})
547+
548+
it('child relations', function () {
549+
var vm = new Vue({
550+
el: el,
551+
template: '<comp1><comp2></comp2></comp1>',
552+
data: {
553+
text:'main'
554+
},
555+
components: {
556+
comp1: {
557+
template: '<div><comp11><slot></slot></comp11></div>',
558+
components: {
559+
comp11: {
560+
template: '<div><slot plugin></slot></div>'
561+
}
562+
}
563+
},
564+
comp2: {
565+
template: '<div><slot></slot></div>'
566+
}
567+
}
568+
})
569+
expect(vm.$children[0].$children.length).toBe(1)
570+
expect(vm.$children[0].$children[0].$options.name).toBe("comp11")
571+
expect(vm.$children[0].$children[0].$children[0].$options.name).toBe("comp2")
572+
})
573+
574+
it('v-for', function () {
575+
var vm = new Vue({
576+
el: el,
577+
template: '<comp1><comp2></comp2></comp1>',
578+
data: {
579+
text:'main'
580+
},
581+
components: {
582+
comp1: {
583+
template: '<div><slot plugin :item="item" v-for="item in data"></slot></div>',
584+
data: function() {
585+
return {data:[{name:"foo"},{name:"bar"}]}
586+
}
587+
},
588+
comp2: {
589+
props: {
590+
item: {
591+
type: Object
592+
}
593+
},
594+
template: '<div>{{item.name}}</div>'
595+
}
596+
}
597+
})
598+
expect(vm.$el.textContent).toBe('foobar')
565599
})
566-
console.log(vm.$el)
567-
expect(vm.$el.textContent).toBe('foobar')
568600
})
601+
569602
})

0 commit comments

Comments
 (0)