V – model principle
V-model in VUE is a grammatical sugar. The so-called grammatical sugar is a function produced by the secondary encapsulation of other basic functions. In a nutshell, the V-Model itself is the parent’s encapsulation of the child’s state and state change events. Its implementation principle is divided into two parts:
- Uses props to set the state of a child component
- Changes the state of the parent component by listening for events emitted by the child component, thus affecting the props value of the child component
Through the above two parts, the effect of binding the state of the parent component and the state of the child component is realized.
demo
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8" />
<title>V - model example</title>
<script type="text/javascript" src="vue.js"></script>
</head>
<body>
<div id="app">
<div>Here is the state of the parent component:</div>
<div style="margin-bottom: 15px;">{{content}}</div>
<Child v-model="content"></Child>
</div>
<template id="input">
<div>
<div>Here is the input field for the child component:</div>
<input :value="value" @input="contentChange" />
</div>
</template>
<script type="text/javascript">
var Child = {
template: "#input".props: {
value: {
type: String.required: true}},methods: {
contentChange(value){
this.$emit("input", value.target.value); }}};var vueInstance = new Vue({
el: "#app".components: {Child},
data: {
content: ""}})</script>
</body>
</html>
Copy the code
Open the above HTML page in the browser, and you can see the real-time effect: the input content in the input box of the child component can be displayed in the area of the parent component in real time, achieving the effect of real-time binding of the state of the child component and the state of the parent component.
Change the event that v-Model listens for by default and set the name of prop
The v-model directive sets the prop name to value on the child component by default, and listens for input events on the child component by default. In the demo above, if we change the event name in the contentChange function of the child component, the input of the child component cannot be obtained in real time in the parent component.
Vue provides the ability to change the names of these two parameters by defining the Model property on the child component, but this is required in version 2.2 or later, as shown in the following demo:
demo
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8" />
<title>V - model example</title>
<script type="text/javascript" src="vue.js"></script>
</head>
<body>
<div id="app">
<div>Here is the state of the parent component:</div>
<div style="margin-bottom: 15px;">{{content}}</div>
<Child v-model="content"></Child>
</div>
<template id="input">
<div>
<div>Here is the input field for the child component:</div>
<input :value="content" @input="contentChange" />
</div>
</template>
<script type="text/javascript">
var Child = {
template: "#input".model: {
prop: "content".event: "contentChanged"
},
props: {
content: {
type: String.required: true}},methods: {
contentChange(value){
this.$emit("contentChanged", value.target.value); }}};var vueInstance = new Vue({
el: "#app".components: {Child},
data: {
content: ""}})</script>
</body>
</html>
Copy the code
V -model instruction processing analysis in Vue
Based on vue 2.0, analyze the process by which we write the V-Model attribute on the label to the Vue component to implement the response.
Analytical part
When HTML is parsed as an AST, the attributes of tags in HTML are parsed
function processAttrs(el){... name = name.replace(dirRE,' ')
// parse arg
const argMatch = name.match(argRE)
if (argMatch && (arg = argMatch[1])) {
name = name.slice(0, -(arg.length + 1))
}
addDirective(el, name, value, arg, modifiers)
...
}
Copy the code
Extract the name of the directive, the v-Model directive name is model, and then add it to the instance directive
Add directive related content to the instance directive
export function addDirective (el: ASTElement, name: string, value: string, arg: ? string, modifiers: ? { [key: string]:true }
) {
(el.directives || (el.directives = [])).push({ name, value, arg, modifiers })
}
Copy the code
Add the corresponding instruction to the instruction attribute of the instance, thus achieving the transformation from the HTML attribute to the instruction format on the Vue instance
Instruction setting section
After parsing the HTML as an AST, the instance has the v-Model related values that we set on the DIRECTIVES property, including the value of the parameter value, and the name is model
Calls the constructor of the instruction
function genDirectives (el: ASTElement) :string | void {
const dirs = el.directives
if(! dirs)return
let res = 'directives:['
let hasRuntime = false
let i, l, dir, needRuntime
for (i = 0, l = dirs.length; i < l; i++) {
dir = dirs[i]
needRuntime = true
const gen = platformDirectives[dir.name] || baseDirectives[dir.name]
if (gen) {
// compile-time directive that manipulates AST.
// returns true if it also needs a runtime counterpart.needRuntime = !! gen(el, dir, warn) } ... }Copy the code
The constructor of the V-Model directive creates different functions based on the type of tag. If our custom directive needs to add attributes to a child component, we need to do so in this function
The construction process of the V-Model instruction under the normal tag
function genDefaultModel
el: ASTElement.value: string.modifiers:?Object
): ?boolean {... addProp(el,'value', isNative ? `_s(${value}) ` : ` (${value}) `)
addHandler(el, event, code, null.true)... }Copy the code
- AddProp sets a prop named value on EL and sets its value
- AddHandler sets the event handler on the EL
Instructions respond to changing parts
CreatePatchFunction Hook function for processing instructions
The createPatchFunction function returns a patch function that calls the hook function of the directive during patch processing, including:
- bind
- inserted
- update
- componentUpdated
- unbind
conclusion
The build process
- Parse the set instruction from the HTML
- The command is set to the AST via the gen* function
- Calls the constructor of the instruction to set what the instruction needs to do at compile time
Initialization process
Through the patch function, the unified hook function is called and the hook function of the command is triggered to realize the corresponding function