SoFunction
Updated on 2025-04-05

Let you understand v-bind in vue

1. V-bind key source code analysis

1. Where are the v-bind attributes stored uniformly: attrsMap and attrsList

<p v-bind:title="vBindTitle"></p>

Assume p tagv-bindIt's meltedtitleAttributes, let's analyzetitleThe attribute isvueHow is it processed?

After vue gets this html tag, it will do the following steps:

  • AnalysisHTML, parse out the attribute collectionattrs,existstartReturn in the callback
  • Create in start callbackASTElement,createASTElement(... ,attrs, ...)
  • After creationASTElementWill generateattrsListandattrsMap

As for how to deal with it after creationv-bind:titleFor such ordinary attribute values, you can find out in the v-bind:src source code analysis below.

2. Parses HTML, parse out attribute collection attrs, and return in the start callback

 
  function handleStartTag (match) {
    ...
    const l = 
    const attrs = new Array(l)
    for (let i = 0; i &lt; l; i++) {
      const args = [i]
      ...
      attrs[i] = {
        name: args[1],
        value: decodeAttr(value, shouldDecodeNewlines)
      }
    }
   ...
    if () {
      // Upload to the start function here      (tagName, attrs, unary, , )
    }
  }

3. Create ASTElement in the start callback, createASTElement(... ,attrs, ...)

// parse HTMLparseHTML(template, {
    ...
    start(tag, attrs, unary, start, end) {
        let element: ASTElement = createASTElement(tag, attrs, currentParent) // Note the attrs here    }
})

4. After creation, ASTElement will generate attrsList and attrsMap.

// Create AST elementexport function createASTElement (
  tag: string,
  attrs: Array&lt;ASTAttr&gt;, // Array of attribute objects  parent: ASTElement | void // The parent element is also ASTElement): ASTElement { // The return is also ASTElement  return {
    type: 1,
    tag,
    attrsList: attrs,
    attrsMap: makeAttrsMap(attrs),
    rawAttrsMap: {},
    parent,
    children: []
  }
}

5. Attrs data type definition

// Declare an ASTAttr attribute abstract syntax tree object data typedeclare type ASTAttr = {
  name: string; // Attribute name  value: any; // Attribute value  dynamic?: boolean; // Is it a dynamic attribute?  start?: number;
  end?: number
};

6. Binding attribute acquisition function

Binding attribute get function getBindingAttr and attribute operation function getAndRemoveAttr

getBindingAttrIts subfunctionsgetAndRemoveAttrIn dealing with specific scenariosv-bindVery useful, that is,"v-bindHow to deal with different binding properties" chapter is very useful. Here is a list of them for the following articlev-bind:keySource code analysis;v-bind:srcSource code analysis;v-bind:classSource code analysis;v-bind:styleSource code analysis;v-bind:Source code analysis Source code analysis reference.

export function getBindingAttr (
  el: ASTElement,
  name: string,
  getStatic?: boolean
): ?string {
  const dynamicValue =
    getAndRemoveAttr(el, ':' + name) ||
    getAndRemoveAttr(el, 'v-bind:' + name)
  if (dynamicValue != null) {
    return parseFilters(dynamicValue)
  } else if (getStatic !== false) {
    const staticValue = getAndRemoveAttr(el, name)
    if (staticValue != null) {
      return (staticValue)
    }
  }
}

// note: this only removes the attr from the Array (attrsList) so that it
// doesn't get processed by processAttrs.
// By default it does NOT remove it from the map (attrsMap) because the map is
// needed during codegen.
export function getAndRemoveAttr (
  el: ASTElement,
  name: string,
  removeFromMap?: boolean
): ?string {
  let val
  if ((val = [name]) != null) {
    const list = 
    for (let i = 0, l = ; i &lt; l; i++) {
      if (list[i].name === name) {
        (i, 1) // Delete an attribute from attrsList, not deleted from attrsMap        break
      }
    }
  }
  if (removeFromMap) {
    delete [name]
  }
  return val
}

2. How to get the value of v-bind

The following code is an example from the source code analysisvueHow to get itv-bindvalue.

I will analyze it by recording several scenarios:

  • Commonkeyproperty
  • Bind a normalhtml attribute:title
  • Bindclassandstyle
  • Bind onehtml DOM property:textContent
vBind:{
    key: +new Date(),
    title: "This is a HTML attribute v-bind",
    class: "{ borderRadius: isBorderRadius }"
    style: "{ minHeight: 100 + 'px' , maxHeight}"
    text-content: "hello vue v-bind"
}

<div
   v-bind:key=""
   v-bind:title=""
   v-bind:class=""
   v-bind:style=""
   v-bind:=""
 />
</div>

1. v-bind:key source code analysis

function processKey (el) {
  const exp = getBindingAttr(el, 'key')
   if(exp){
      ...
       = exp;
   }
}


processKeyUsed in functionsgetBindingAttrFunction, since we usev-bind, useless:, soconst dynamicValue = getAndRemoveAttr(el, 'v-bind:'+'key');,getAndRemoveAttr(el, 'v-bind:key')Function toattrsMapDetermine whether it exists'v-bind:key', take the value of this property as val and assign it fromattrsListDelete, but will notattrsMapDelete, finally'v-bind:key'The value of val isdynamicValue, then return the parsed filtered result, and finally the result issetforprocessKeyThe element of thekey property. Then store it insegmentsIn, as forsegmentsWhat is it, you can see in the source code above.

2. v-bind:title source code analysis

titleIt's a kind of "non-vueSpecial "that is ordinaryHTML attribute

function processAttrs(el){
     const list = ;
     ...
     if ((name)) { // v-bind
        name = (bindRE, '')
        value = parseFilters(value)
        ...
        addAttr(el, name, value, list[i], ...)
      }
}
export const bindRE = /^:|^\.|^v-bind:/
export function addAttr (el: ASTElement, name: string, value: any, range?: Range, dynamic?: boolean) {
  const attrs = dynamic
    ? ( || ( = []))
    : ( || ( = []))
  (rangeSetItem({ name, value, dynamic }, range))
   = false
}

By reading the source code, we can see that for native attributes, such as title, vue will first parse out the original attributes, such as title.nameandvalue, and then do a series of whether there ismodifiersThe judgment ofmodifierThe part of the article will be explained in detail below), and finally updatedASTElementofattrs,therebyattrsListandattrsMapAlso synchronously updated.

3. v-bind:class source code analysis

cssofclassIt is a very important level in the presentation level of front-end development. thereforevueIn ForclassThe attributes have also been treated with a lot of special treatments.

function transformNode (el: ASTElement, options: CompilerOptions) {
  const warn =  || baseWarn
  const staticClass = getAndRemoveAttr(el, 'class')
  if (staticClass) {
     = (staticClass)
  }
  const classBinding = getBindingAttr(el, 'class', false /* getStatic */)
  if (classBinding) {
     = classBinding
  }
}

existtransfromNodeIn the function, it will passgetAndRemoveAttrGet staticclass, that is, class="foo";getBindingAttrGet the bound class, that isv-bind:class=""Right nowv-bind:class="{ borderRadius: isBorderRadius }", assign the classBinding of ASTElement to the attribute we bind for subsequent use.

4. v-bind:style source code analysis

Style is the priority of direct operation styles after important, a more intuitive operation style than classHTML attribute. vue also handles this property in special terms.

function transformNode (el: ASTElement, options: CompilerOptions) {
  const warn =  || baseWarn
  const staticStyle = getAndRemoveAttr(el, 'style')
  if (staticStyle) {
     = (parseStyleText(staticStyle))
  }
  const styleBinding = getBindingAttr(el, 'style', false /* getStatic */)
  if (styleBinding) {
     = styleBinding
  }
}

existtransfromNodeIn the function, it will passgetAndRemoveAttrGet a static style, that isstyle="{fontSize: '12px'}";existgetBindingAttrGet the bound style, that isv-bind:style=""i.e. v-bind:class={ minHeight: 100 + 'px' , maxHeight}", where maxHeight is a variable,ASTElementofstyleBindingAssign the attributes we bind for subsequent use.

5. v-bind: Source code analysis

textContentIt is a native property of the DOM object, so it can be identified through prop. If we want to set a DOM prop directly through vue, we can make modifications on the DOM node.

Let's look at the source code below.

function processAttrs (el) {
  const list = 
  ...
  if ((name)) { // v-bind
      if (modifiers) {
          if ( && !isDynamic) {
            name = camelize(name)
            if (name === 'innerHtml') name = 'innerHTML'
          }
       }
       if (modifiers && ) {
          addProp(el, name, value, list[i], isDynamic)
        }
   }
}
export function addProp (el: ASTElement, name: string, value: string, range?: Range, dynamic?: boolean) {
  ( || ( = [])).push(rangeSetItem({ name, value, dynamic }, range))
   = false
}
props?: Array<ASTAttr>;

Through the above source code, we can see thatv-bind:In-housetext-contentFirst, it was humped intotextContent(This is becauseDOM propertyAll are camel formats), vue is correctinnerHtmlThe error writing method is compatible and it is also intentional. Then, the textContent attribute is added to theASTElement's props, and here props are essentially an ASTATtr.

There is a question worth thinking about:Why do it? What are the similarities and differences with HTML attribute?

  • NoHTML attributeYou can directly modify the text content of the DOM, so you need to identify it separately
  • It is faster than manually updating the DOM text node through js, eliminating the steps of querying the dom and replacing the text content.
  • You can see which attribute we v-bind on the tag, which is very intuitive
  • In fact, v-bind:title can be understood asv-bind:,v-bind:onlyvueHTML is a default not to add modifiersattributeForget it

6. V-bind modifier.camel.sync source code analysis

.camelIt's just camel, it's very simple. But .sync is not that simple, it will be expanded into a v-on listener that updates the parent component's binding value.

Actually, when I first saw this .sync modifier, I was confused, but if I read the .sync of the component carefully and combined with actual work, I will find that it is powerful.

<Parent
  v-bind:foo=""
  v-on:updateFoo=" = $event"
></Parent>

In vue, the parent component passes the child componentpropsIt cannot be passed directly by subcomponents = newFooGo to modify. Unless we are in the componentthis.$emit("updateFoo", newFoo),Then use v-on to listen on the parent componentupdateFooevent. If you want better readability, you can$emitChange the name to update:foo, and thenv-on:update:foo

Is there a simpler way to write it? ? ? That is our .sync operator. It can be abbreviated as:

<Parent v-bind:=""></Parent>

Then in the subcomponent passesthis.$emit("update:foo", newFoo); to trigger, note that the event name here must be in the format of update:xxx, because in the source code of vue, using the .sync modifier attribute will be used to generate a customv-on:update:xxxmonitor.

Let's look at the source code below:

if ( &amp;&amp; !isDynamic) {
  name = camelize(name)
}
if () {
  syncGen = genAssignmentCode(value, `$event`)
  if (!isDynamic) {
    addHandler(el,`update:${camelize(name)}`,syncGen,null,false,warn,list[i]) 
   // Hyphenate is a hyphenate function, where camelize is a camelize function    if (hyphenate(name) !== camelize(name)) {
      addHandler(el,`update:${hyphenate(name)}`,syncGen,null,false,warn,list[i])
    }
  } else {
    // handler w/ dynamic event name
    addHandler(el,`"update:"+(${name})`,syncGen,null,false,warn,list[i],true)
  }
}

By reading the source code, we can see:v-bind:vue will determine whether the attribute is a dynamic attribute. If it is not a dynamic property, first add a camel listening, and then add a hyphen to it, for examplev-bind:,firstv-on:update:fooBar,Thenv-on:update:foo-bar. v-on listening is throughaddHandler plus. If it is a dynamic attribute, it will not be camel or hyphenated, throughaddHandler(el,update:${name}, ...),Listen honestly to the event of that dynamic attribute.

A summary in one sentence.sync: .syncis a syntactic sugar, simplifying v-bind and v-on toandthis.$emit('update:xxx'). It provides us with a way for child components to quickly update parent component data.

This is all about this article about how to understand v-bind in vue. This is the end of this article. For more related v-bind content in vue, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!