1. Analysis of key source code of v-bind1. Where are v-bind attributes stored uniformly: attrsMap and attrsList<p v-bind:title="vBindTitle"></p> Assuming that the After getting this HTML tag, Vue processes the title attribute and does the following steps:
As for how to handle common attribute values such as 2. Parse HTML, parse the attribute set attrs, and return it in the start callbackfunction handleStartTag (match) { ... const l = match.attrs.length const attrs = new Array(l) for (let i = 0; i < l; i++) { const args = match.attrs[i] ... attrs[i] = { name: args[1], value: decodeAttr(value, shouldDecodeNewlines) } } ... if (options.start) { // Upload to the start function here options.start(tagName, attrs, unary, match.start, match.end) } } 3. Create ASTElement in the start callback, createASTElement(... ,attrs, ...)// Parsing HMTL parseHTML(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 element export function createASTElement ( tag: string, attrs: Array<ASTAttr>, // attribute object array parent: ASTElement | void // parent element is also ASTElement ): ASTElement { // Returns ASTElement return { type: 1, tag, attrsList: attrs, attrsMap: makeAttrsMap(attrs), rawAttrsMap: {}, parent, children: [] } } 5. Data type definition of attrs//Declare an ASTAttr attribute abstract syntax tree object data type declare type ASTAttr = { name: string; // attribute namevalue: any; // attribute valuedynamic?: boolean; // is it a dynamic attributestart?: number; end?: number }; 6. Binding attribute acquisition functionBinding attribute acquisition function getBindingAttr and attribute operation function getAndRemoveAttr 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 JSON.stringify(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 = el.attrsMap[name]) != null) { const list = el.attrsList for (let i = 0, l = list.length; i < l; i++) { if (list[i].name === name) { list.splice(i, 1) // Remove an attribute from attrsList, will not remove break from attrsMap } } } if (removeFromMap) { delete el.attrsMap[name] } return val } 2. How to get the value of v-bind Take the following code as an example to analyze how I will analyze it by writing down a few scenes:
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="vBind.key" v-bind:title="vBind.title" v-bind:class="vBind.class" v-bind:style="vBind.style" v-bind:text-content.prop="vBind.textContent" /> </div> 1. v-bind:key source code analysisfunction processKey (el) { const exp = getBindingAttr(el, 'key') if(exp){ ... el.key = exp; } } The 2. v-bind:title source code analysis function processAttrs(el){ const list = el.attrsList; ... if (bindRE.test(name)) { // v-bind name = name.replace(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 ? (el.dynamicAttrs || (el.dynamicAttrs = [])) : (el.attrs || (el.attrs = [])) attrs.push(rangeSetItem({ name, value, dynamic }, range)) el.plain = false } By reading the source code, we can see that for native attributes, such as title, vue will first parse 3. v-bind:class source code analysis function transformNode (el: ASTElement, options: CompilerOptions) { const warn = options.warn || baseWarn const staticClass = getAndRemoveAttr(el, 'class') if (staticClass) { el.staticClass = JSON.stringify(staticClass) } const classBinding = getBindingAttr(el, 'class', false /* getStatic */) if (classBinding) { el.classBinding = classBinding } } In the 4. v-bind:style source code analysis Style is an function transformNode (el: ASTElement, options: CompilerOptions) { const warn = options.warn || baseWarn const staticStyle = getAndRemoveAttr(el, 'style') if (staticStyle) { el.staticStyle = JSON.stringify(parseStyleText(staticStyle)) } const styleBinding = getBindingAttr(el, 'style', false /* getStatic */) if (styleBinding) { el.styleBinding = styleBinding } } In the 5. v-bind:text-content.prop source code analysis Let's look at the source code. function processAttrs(el) { const list = el.attrsList ... if (bindRE.test(name)) { // v-bind if (modifiers) { if (modifiers.prop && !isDynamic) { name = camelize(name) if (name === 'innerHtml') name = 'innerHTML' } } if (modifiers && modifiers.prop) { addProp(el, name, value, list[i], isDynamic) } } } export function addProp (el: ASTElement, name: string, value: string, range?: Range, dynamic?: boolean) { (el.props || (el.props = [])).push(rangeSetItem({ name, value, dynamic }, range)) el.plain = false } props?: Array<ASTAttr>; From the source code above, we can see that There is a question worth pondering: Why do this? What are the similarities and differences with HTML attributes?
6. v-bind modifier.camel.sync source code analysis . In fact, I was confused when I first saw the .sync modifier, but after reading the component's .sync carefully and combining it with actual work, I found its power. <Parent v-bind:foo="parent.foo" v-on:updateFoo="parent.foo = $event" ></Parent> In Vue, Is there a more concise way to write it? ? ? That's what we have here, the .sync operator. It can be shortened to: <Parent v-bind:foo.sync="parent.foo"></Parent> Then trigger it in the child component through Let's look at the source code: if (modifiers.camel && !isDynamic) { name = camelize(name) } if (modifiers.sync) { syncGen = genAssignmentCode(value, `$event`) if (!isDynamic) { addHandler(el,`update:${camelize(name)}`,syncGen,null,false,warn,list[i]) // Hyphenate is a hyphenation function, where camelize is a camel case 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 that: For the attributes of To summarize This is the end of this article about understanding v-bind in vue. For more relevant content about v-bind in vue, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: Summary of some points to note when registering Tomcat as a service
>>: Comparison of the efficiency of different methods of deleting files in Linux
Because the Raspberry Pi is based on ARM architec...
First, let’s take an example: There is a type fie...
There is no data directory, my-default.ini and my...
This article example shares the specific code of ...
In the project, we often encounter the problem of...
Computed properties Sometimes we put too much log...
Table of contents background: Nginx smooth upgrad...
Table of contents 1. What is a JavaScript engine?...
The inline-block property value becomes very usef...
Good morning everyone, I haven’t updated my artic...
On a Linux computer, there are two times, one is ...
When using HTML tables, we sometimes need to chan...
Let’s start with a question Five years ago when I...
1. CSS Box Model The box includes: margin, border...
Table of contents 1. What is Set 2. Set Construct...