@@ -21,18 +21,19 @@ module.exports = compile
2121
2222function compile ( el , options , partial , transcluded ) {
2323 var isBlock = el . nodeType === 11
24- var params = ! partial && options . paramAttributes
25- // if el is a fragment, this is a block instance
26- // and paramAttributes will be stored on the first
27- // element in the template. (excluding the _blockStart
28- // comment node)
29- var paramsEl = isBlock ? el . childNodes [ 1 ] : el
30- var paramsLinkFn = params
31- ? compileParamAttributes ( paramsEl , params , options )
24+ // link function for param attributes.
25+ var params = options . paramAttributes
26+ var paramsLinkFn = params && ! partial && ! transcluded && ! isBlock
27+ ? compileParamAttributes ( el , params , options )
3228 : null
29+ // link function for the node itself.
30+ // if this is a block instance, we return a link function
31+ // for the attributes found on the container, if any.
32+ // options._containerAttrs are collected during transclusion.
3333 var nodeLinkFn = isBlock
34- ? null
34+ ? compileBlockContainer ( options . _containerAttrs , params , options )
3535 : compileNode ( el , options )
36+ // link function for the childNodes
3637 var childLinkFn =
3738 ! ( nodeLinkFn && nodeLinkFn . terminal ) &&
3839 el . tagName !== 'SCRIPT' &&
@@ -41,22 +42,21 @@ function compile (el, options, partial, transcluded) {
4142 : null
4243
4344 /**
44- * A linker function to be called on a already compiled
45- * piece of DOM, which instantiates all directive
45+ * A composite linker function to be called on a already
46+ * compiled piece of DOM, which instantiates all directive
4647 * instances.
4748 *
4849 * @param {Vue } vm
4950 * @param {Element|DocumentFragment } el
5051 * @return {Function|undefined }
5152 */
5253
53- function linkFn ( vm , el ) {
54+ function compositeLinkFn ( vm , el ) {
5455 var originalDirCount = vm . _directives . length
5556 var parentOriginalDirCount =
5657 vm . $parent && vm . $parent . _directives . length
5758 if ( paramsLinkFn ) {
58- var paramsEl = isBlock ? el . childNodes [ 1 ] : el
59- paramsLinkFn ( vm , paramsEl )
59+ paramsLinkFn ( vm , el )
6060 }
6161 // cache childNodes before linking parent, fix #657
6262 var childNodes = _ . toArray ( el . childNodes )
@@ -102,10 +102,44 @@ function compile (el, options, partial, transcluded) {
102102 // transcluded linkFns are terminal, because it takes
103103 // over the entire sub-tree.
104104 if ( transcluded ) {
105- linkFn . terminal = true
105+ compositeLinkFn . terminal = true
106106 }
107107
108- return linkFn
108+ return compositeLinkFn
109+ }
110+
111+ /**
112+ * Compile the attributes found on a "block container" -
113+ * i.e. the container node in the parent tempate of a block
114+ * instance. We are only concerned with v-with and
115+ * paramAttributes here.
116+ *
117+ * @param {Object } attrs - a map of attr name/value pairs
118+ * @param {Array } params - param attributes list
119+ * @param {Object } options
120+ * @return {Function }
121+ */
122+
123+ function compileBlockContainer ( attrs , params , options ) {
124+ if ( ! attrs ) return null
125+ var paramsLinkFn = params
126+ ? compileParamAttributes ( attrs , params , options )
127+ : null
128+ var withVal = attrs [ config . prefix + 'with' ]
129+ var withLinkFn = null
130+ if ( withVal ) {
131+ var descriptor = dirParser . parse ( withVal ) [ 0 ]
132+ var def = options . directives [ 'with' ]
133+ withLinkFn = function ( vm , el ) {
134+ vm . _bindDir ( 'with' , el , descriptor , def )
135+ }
136+ }
137+ return function blockContainerLinkFn ( vm ) {
138+ // explicitly passing null to the linkers
139+ // since v-with doesn't need a real element
140+ if ( paramsLinkFn ) paramsLinkFn ( vm , null )
141+ if ( withLinkFn ) withLinkFn ( vm , null )
142+ }
109143}
110144
111145/**
@@ -363,14 +397,15 @@ function makeChildLinkFn (linkFns) {
363397 * Compile param attributes on a root element and return
364398 * a paramAttributes link function.
365399 *
366- * @param {Element } el
400+ * @param {Element|Object } el
367401 * @param {Array } attrs
368402 * @param {Object } options
369403 * @return {Function } paramsLinkFn
370404 */
371405
372406function compileParamAttributes ( el , attrs , options ) {
373407 var params = [ ]
408+ var isEl = el . nodeType
374409 var i = attrs . length
375410 var name , value , param
376411 while ( i -- ) {
@@ -384,15 +419,15 @@ function compileParamAttributes (el, attrs, options) {
384419 'http://vuejs.org/api/options.html#paramAttributes'
385420 )
386421 }
387- value = el . getAttribute ( name )
422+ value = isEl ? el . getAttribute ( name ) : el [ name ]
388423 if ( value !== null ) {
389424 param = {
390425 name : name ,
391426 value : value
392427 }
393428 var tokens = textParser . parse ( value )
394429 if ( tokens ) {
395- el . removeAttribute ( name )
430+ if ( isEl ) el . removeAttribute ( name )
396431 if ( tokens . length > 1 ) {
397432 _ . warn (
398433 'Invalid param attribute binding: "' +
0 commit comments