Source location:
vue-next/packages/compile-core/src/transforms/vOn.ts
vue-next/packages/compile-core/src/transforms/vBind.ts
Here, the transform module has been basically implemented, but it needs to deal with v-on and v-bind. Take this as a simple example to see what instruction compilation will do
Explain
directiveTransforms is also a kind of transform plugin conversion plug-in, which includes some instruction processing functions such as transformOn and transformBind. This paper implements these two functions. The things done by instruction processing are relatively trivial, which can be summarized briefly
- Different processing is performed for different instructions
- v-on needs humping event monitoring, event processing, monitoring cache, application expansion plug-ins, etc
- v-bind needs to handle some pre modifiers and some fault tolerance
- Package instruction contents into JS_PROPERTY object return
Write about transformOn
Two tool functions
Here are two tool functions
capitalize
As mentioned above, to hump event monitoring, of course, there must be such a tool function
function camelize(str) { return str.replace( /-(\w)/g, (neverUse, c) => (c ? c.toUpperCase() : '') ); }
The series here may seem a little confused. The first parameter of replace can receive a regular expression, while the second parameter receives a callback function. The parameters of the callback function are very similar to the return results of RegExp.exec(). The first parameter is the matched substring, and the second parameter starts to capture the contents of the group. The following is an example
const str = 'yes-this-is-my-handler'; // In the above example // nerverUse is ['- t', '-i', '-m', '-h'] // c is ['t ',' I ','m', 'H'] camelize(str); // yesThisIsMyHandler
toHandlerKey
Here is a tool function to convert XXX XX into onxxxXx, which is very simple
const toHandlerKey = str => (str ? `on${capitalize(str)}` : '')
transformOn
The things to be done in transformOn are tedious, but the things to be done in our transformOn are very simple. We only need to hump event monitoring, and then package it into JS_PROPERTY type objects can be returned
const transformOn = dir => { const { arg } = dir; // Humping let eventName; if (arg.type === NodeTypes.SIMPLE_EXPRESSION) { if (arg.isStatic) { const rawName = arg.content; eventName = createSimpleExpression(toHandlerKey(camelize(rawName)), true); } // The source code here processes the dynamic event name into a composite expression } else { eventName = arg; } // Processing expression let exp = dir.exp; if (exp && !exp.content.trim()) { exp = undefined; } // The source code will handle the event cache here // The source code will handle the external plug-in extended compiler augmentor here // Package and return JS_PROPERTY node let ret = { props: [ createObjectProperty( eventName, exp || createSimpleExpression('() => {}', false) ), ], }; return ret; };
Write about transformBind
transformBind needs to do many simple things, such as fault-tolerant processing, adding prefixes, wrapping nodes, and looking at the code directly
const transformBind = dir => { const { exp, modifiers } = dir; const arg = dir.arg; // Fault tolerant processing. If it is empty, an empty string will be output if (arg.type !== NodeTypes.SIMPLE_EXPRESSION) { arg.children.unshift('('); arg.children.push(') || ""'); } else if (!arg.isStatic) { arg.content = `${arg.content} || ""`; } // Add "." prefix to prop // Add "^" prefix to attr if (modifiers.includes('prop')) { injectPrefix(arg, '.'); } if (modifiers.includes('attr')) { injectPrefix(arg, '^'); } // Package and return JS_PROPERTY node if ( !exp || (exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) ) { return { props: [createObjectProperty(arg, createSimpleExpression('', true))], }; } return { props: [createObjectProperty(arg, exp)], }; }; // Prefix handler const injectPrefix = (arg, prefix) => { if (arg.type === NodeTypes.SIMPLE_EXPRESSION) { if (arg.isStatic) { arg.content = prefix + arg.content; } else { arg.content = `\`${prefix}\${${arg.content}}\``; } } else { arg.children.unshift(`'${prefix}' + (`); arg.children.push(`)`); } };
summary
The above is the implementation of transformOn and transformBind, both of which belong to directiveTransforms. They are called in the previous transformElement. It should be noted here that these instruction processing plug-ins will only process instructions with args, because instructions without args have been processed in transformElement
From the perspective of these two instruction processing plug-ins, in fact, they are very similar to nodeTransforms. They do some processing and then package them according to the structure to facilitate generation. In fact, it is the same. Other instructions such as v-model and v-for will be packaged. Due to the author's limited level and energy, other instructions will not be implemented first