2
0
Evan You 10 жил өмнө
parent
commit
d6c5abbf35

+ 14 - 1
src/compiler/codegen/index.js

@@ -15,6 +15,8 @@ function genElement (el) {
     return genChildren(el)
   } else if (el.tag === 'render') {
     return genRender(el)
+  } else if (el.tag === 'slot') {
+    return genSlot(el)
   } else {
     return `__h__('${el.tag}', ${genData(el)}, ${genChildren(el)})`
   }
@@ -44,6 +46,10 @@ function genData (el) {
   if (el.key) {
     data += `key:${el.key},`
   }
+  // slot names
+  if (el.attrsMap.slot) {
+    data += `slot:"${el.attrsMap.slot}",`
+  }
   // svg
   if (el.svg) {
     data += 'svg:true,'
@@ -102,7 +108,14 @@ function genText (text) {
 }
 
 function genRender (el) {
-  return `${el.method}(${el.args || ''})`
+  return `${el.method}(${el.args || 'null'},${genChildren(el)})`
+}
+
+function genSlot (el) {
+  const name = el.name
+    ? `"${el.name}"`
+    : (el.dynamicName || '"default"')
+  return `$slots[${name}]`
 }
 
 function genProps (props) {

+ 7 - 2
src/compiler/parser/index.js

@@ -161,8 +161,13 @@ function processRender (el) {
   }
 }
 
-function processSlot () {
-  // todo
+function processSlot (el) {
+  if (el.tag === 'slot') {
+    el.name = el.attrsMap.name
+    el.dynamicName =
+      el.attrsMap[':name'] ||
+      el.attrsMap['v-bind:name']
+  }
 }
 
 function processClassBinding (el) {

+ 33 - 10
src/runtime/instance/render.js

@@ -10,13 +10,32 @@ export const renderState = {
 export function initRender (vm) {
   vm._vnode = null
   vm._mounted = false
-  // TODO: handle _renderData and _renderChildren
+  vm._renderData = vm.$options._renderData
+  vm.$slots = resolveSlots(vm.$options._renderChildren)
   const el = vm.$options.el
   if (el) {
     vm.$mount(el)
   }
 }
 
+function resolveSlots (children) {
+  const slots = {
+    default: children
+  }
+  if (children) {
+    let i = children.length
+    let name, child
+    while (i--) {
+      child = children[i]
+      if ((name = child.data && child.data.slot)) {
+        (slots[name] || (slots[name] = [])).push(child)
+        children.splice(i, 1)
+      }
+    }
+  }
+  return slots
+}
+
 export function renderMixin (Vue) {
   // shorthands used in render functions
   Vue.prototype.__h__ = createElement
@@ -36,8 +55,9 @@ export function renderMixin (Vue) {
   }
 
   Vue.prototype._tryUpdate = function (data, children) {
+    this._renderData = data
+    this.$slots = resolveSlots(children)
     if (children) {
-      // TODO: handle content slots
       this.$forceUpdate()
       return
     }
@@ -53,20 +73,23 @@ export function renderMixin (Vue) {
     }
   }
 
+  Vue.prototype._render = function () {
+    const prev = renderState.activeInstance
+    renderState.activeInstance = this
+    const vnode = this.$options.render.call(this)
+    // merge parent data
+    // TODO
+    renderState.activeInstance = prev
+    return vnode
+  }
+
   Vue.prototype.$mount = function (el) {
     callHook(this, 'beforeMount')
     this.$el = el && query(el)
     if (this.$el) {
       this.$el.innerHTML = ''
     }
-    const render = this.$options.render
-    this._watcher = new Watcher(this, () => {
-      const prev = renderState.activeInstance
-      renderState.activeInstance = this
-      const vnode = render.call(this)
-      renderState.activeInstance = prev
-      return vnode
-    }, this._update)
+    this._watcher = new Watcher(this, this._render, this._update)
     this._update(this._watcher.value)
     callHook(this, 'mounted')
     this._mounted = true