Permalink
Browse files

support default scoped slot + function children as scoped slot

  • Loading branch information...
1 parent 745f8a9 commit 303378f85b26934396e2f6dc0973f6982da2beb1 @yyx990803 yyx990803 committed Nov 18, 2016
View
@@ -1,5 +1,6 @@
{
"presets": ["es2015", "flow-vue"],
+ "plugins": ["transform-vue-jsx"],
"ignore": [
"dist/*.js",
"packages/**/*.js"
View
@@ -53,6 +53,7 @@ declare interface VNodeData {
};
directives?: Array<VNodeDirective>;
keepAlive?: boolean;
+ scopedSlots?: { [key: string]: Function }
}
declare type VNodeDirective = {
View
@@ -60,8 +60,11 @@
"devDependencies": {
"babel-core": "^6.9.0",
"babel-eslint": "^7.1.0",
+ "babel-helper-vue-jsx-merge-props": "^2.0.2",
"babel-loader": "^6.2.4",
"babel-plugin-coverage": "^1.0.0",
+ "babel-plugin-syntax-jsx": "^6.18.0",
+ "babel-plugin-transform-vue-jsx": "^3.2.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-flow-vue": "^1.0.0",
"buble": "^0.14.0",
@@ -355,7 +355,7 @@ function processSlot (el) {
} else {
const slotTarget = getBindingAttr(el, 'slot')
if (slotTarget) {
- el.slotTarget = slotTarget
+ el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget
el.slotScope = getAndRemoveAttr(el, 'scope')
}
}
@@ -191,9 +191,6 @@ export function renderMixin (Vue: Class<Component>) {
fallback: ?Array<VNode>,
props: ?Object
): ?Array<VNode> {
- if (process.env.NODE_ENV !== 'production' && name === 'default' && props) {
- warn(`Scoped slots must be named`, this)
- }
const scopedSlotFn = this.$scopedSlots && this.$scopedSlots[name]
if (scopedSlotFn) { // scoped slot
return scopedSlotFn(props || {}) || fallback
@@ -39,6 +39,13 @@ export function _createElement (
// in case of component :is set to falsy value
return emptyVNode()
}
+ // support single function children as default scoped slot
+ if (Array.isArray(children) &&
+ typeof children[0] === 'function') {
+ data = data || {}
+ data.scopedSlots = { default: children[0] }
+ children.length = 0
+ }
if (typeof tag === 'string') {
let Ctor
const ns = config.getTagNamespace(tag)
@@ -1,6 +1,25 @@
import Vue from 'vue'
describe('Component scoped slot', () => {
+ it('default slot', () => {
+ const vm = new Vue({
+ template: `<test><span slot scope="props">{{ props.msg }}</span></test>`,
+ components: {
+ test: {
+ data () {
+ return { msg: 'hello' }
+ },
+ template: `
+ <div>
+ <slot :msg="msg"></slot>
+ </div>
+ `
+ }
+ }
+ }).$mount()
+ expect(vm.$el.innerHTML).toBe('<span>hello</span>')
+ })
+
it('normal element slot', done => {
const vm = new Vue({
template: `
@@ -204,25 +223,6 @@ describe('Component scoped slot', () => {
expect(vm.$el.innerHTML).toBe('<span>meh</span>')
})
- it('warn un-named scoped slot', () => {
- new Vue({
- template: `<test><span scope="lol"></span></test>`,
- components: {
- test: {
- data () {
- return { msg: 'hello' }
- },
- template: `
- <div>
- <slot :msg="msg"></slot>
- </div>
- `
- }
- }
- }).$mount()
- expect('Scoped slots must be named').toHaveBeenWarned()
- })
-
it('warn key on slot', () => {
new Vue({
template: `
@@ -250,7 +250,7 @@ describe('Component scoped slot', () => {
expect(`\`key\` does not work on <slot>`).toHaveBeenWarned()
})
- it('render function usage', done => {
+ it('render function usage (named, via data)', done => {
const vm = new Vue({
render (h) {
return h('test', {
@@ -282,4 +282,50 @@ describe('Component scoped slot', () => {
expect(vm.$el.innerHTML).toBe('<span>world</span>')
}).then(done)
})
+
+ it('render function usage (default, as children)', () => {
+ const vm = new Vue({
+ render (h) {
+ return h('test', [
+ props => h('span', [props.msg])
+ ])
+ },
+ components: {
+ test: {
+ data () {
+ return { msg: 'hello' }
+ },
+ render (h) {
+ return h('div', [
+ this.$scopedSlots.default({ msg: this.msg })
+ ])
+ }
+ }
+ }
+ }).$mount()
+ expect(vm.$el.innerHTML).toBe('<span>hello</span>')
+ })
+
+ it('render function usage (JSX)', () => {
+ const vm = new Vue({
+ render (h) {
+ return <test>{
+ props => <span>{props.msg}</span>
+ }</test>
+ },
+ components: {
+ test: {
+ data () {
+ return { msg: 'hello' }
+ },
+ render (h) {
+ return <div>
+ {this.$scopedSlots.default({ msg: this.msg })}
+ </div>
+ }
+ }
+ }
+ }).$mount()
+ expect(vm.$el.innerHTML).toBe('<span>hello</span>')
+ })
})

0 comments on commit 303378f

Please sign in to comment.