wordpress本地建站,保定网站建设方案托管,北京的网站制作公司,网站分享插件怎么做什么是v-model
v-model 是 Vue 中的一个指令#xff0c;用于实现表单元素与 Vue 实例中数据的双向绑定。这意味着当表单元素的值发生变化时#xff0c;Vue 实例中的数据也会随之更新
工作原理
生成ast树
本质上是语法糖 结合了v-bind和v-on两个指令 示例代码
new Vue({e…什么是v-model
v-model 是 Vue 中的一个指令用于实现表单元素与 Vue 实例中数据的双向绑定。这意味着当表单元素的值发生变化时Vue 实例中的数据也会随之更新
工作原理
生成ast树
本质上是语法糖 结合了v-bind和v-on两个指令 示例代码
new Vue({el: #app,data () {return {msg: Hello, msg}},template: input v-modelmsg /
})
源码解析
processElement方法中调用processAttrs来处理标签上面解析的各种属性
export function processElement (element: ASTElement,options: CompilerOptions
) {// ...省略代码processAttrs(element)return element
}
进入processAttrs这个方法中 用于构建抽象的语法树
export const dirRE process.env.VBIND_PROP_SHORTHAND? /^v-|^|^:|^\.|^#/: /^v-|^|^:|^#/
const argRE /:(.*)$/
function processAttrs (el) {const list el.attrsListlet i, l, name, rawName, value, modifiers, syncGen, isDynamicfor (i 0, l list.length; i l; i) {name rawName list[i].namevalue list[i].valueif (dirRE.test(name)) {el.hasBindings true// modifiers省略代码if (bindRE.test(name)) {// v-bind省略代码} else if (onRE.test(name)) {// v-on省略代码} else {// normal directivesname name.replace(dirRE, )// parse arg//先使用dirRE正则表达式把v-model字符串中的v-前缀去掉//此时name的值就变成了model//它又使用了argRE正则表达式来匹配指令参数//示例 // const template input v-model:valuemsg /// 匹配到的指令参数//const arg valueconst argMatch name.match(argRE)let arg argMatch argMatch[1]isDynamic falseif (arg) {name name.slice(0, -(arg.length 1))if (dynamicArgRE.test(arg)) {arg arg.slice(1, -1)isDynamic true}}addDirective(el, name, rawName, value, arg, isDynamic, modifiers, list[i])if (process.env.NODE_ENV ! production name model) {checkForAliasModel(el, value)}}} else {// ...省略代码}}
}处理完毕后进入调用addDirective方法给ast对象添加directives属性
export function addDirective (el: ASTElement,name: string,rawName: string,value: string,arg: ?string,isDynamicArg: boolean,modifiers: ?ASTModifiers,range?: Range
) {(el.directives || (el.directives [])).push(rangeSetItem({name,rawName,value,arg,isDynamicArg,modifiers}, range))el.plain false
}
生成的ast树如下所示
const ast {type: 1,tag: input,attrsList: [{ name: v-model, value: msg }],attrsMap: {v-model: msg},directives: [{ name: model, rawName: v-model, value: msg }]
}
codegen阶段
codegen代码生成阶段会在genData方法中调用genDirectives来处理指令
export function genData (el: ASTElement, state: CodegenState): string {let data {const dirs genDirectives(el, state)if (dirs) data dirs ,// ...省略代码return data
}function genDirectives (el: ASTElement, state: CodegenState): string | void {const dirs el.directivesif (!dirs) returnlet res directives:[let hasRuntime falselet i, l, dir, needRuntimefor (i 0, l dirs.length; i l; i) {dir dirs[i]needRuntime trueconst gen: DirectiveFunction state.directives[dir.name]if (gen) {// compile-time directive that manipulates AST.// returns true if it also needs a runtime counterpart.needRuntime !!gen(el, dir, state.warn)}if (needRuntime) {hasRuntime trueres {name:${dir.name},rawName:${dir.rawName}${dir.value ? ,value:(${dir.value}),expression:${JSON.stringify(dir.value)} : }${dir.arg ? ,arg:${dir.isDynamicArg ? dir.arg : ${dir.arg}} : }${dir.modifiers ? ,modifiers:${JSON.stringify(dir.modifiers)} : }},}}if (hasRuntime) {return res.slice(0, -1) ]}
}与其他指令不同 state.directives这个属性是在CodegenState类的构造函数中被处理的
export class CodegenState {options: CompilerOptions;warn: Function;transforms: ArrayTransformFunction;dataGenFns: ArrayDataGenFunction;directives: { [key: string]: DirectiveFunction };maybeComponent: (el: ASTElement) boolean;onceId: number;staticRenderFns: Arraystring;pre: boolean;constructor (options: CompilerOptions) {this.options options// ...省略代码this.directives extend(extend({}, baseDirectives), options.directives)// ...省略代码}
}directives中 v-model中
export default function model (el: ASTElement,dir: ASTDirective,_warn: Function
): ?boolean {warn _warnconst value dir.valueconst modifiers dir.modifiersconst tag el.tagconst type el.attrsMap.typeif (process.env.NODE_ENV ! production) {// inputs with typefile are read only and setting the inputs// value will throw an error.if (tag input type file) {warn(${el.tag} v-model${value} typefile:\n File inputs are read only. Use a v-on:change listener instead.,el.rawAttrsMap[v-model])}}if (el.component) {genComponentModel(el, value, modifiers)// component v-model doesnt need extra runtimereturn false} else if (tag select) {genSelect(el, value, modifiers)} else if (tag input type checkbox) {genCheckboxModel(el, value, modifiers)} else if (tag input type radio) {genRadioModel(el, value, modifiers)} else if (tag input || tag textarea) {genDefaultModel(el, value, modifiers)} else if (!config.isReservedTag(tag)) {genComponentModel(el, value, modifiers)// component v-model doesnt need extra runtimereturn false} else if (process.env.NODE_ENV ! production) {warn(${el.tag} v-model${value}: v-model is not supported on this element type. If you are working with contenteditable, it\s recommended to wrap a library dedicated for that purpose inside a custom component.,el.rawAttrsMap[v-model])}// ensure runtime directive metadatareturn true
}最后代码生成阶段
function genDefaultModel (el: ASTElement,value: string,modifiers: ?ASTModifiers
): ?boolean {// ...省略代码addProp(el, value, (${value}))addHandler(el, event, code, null, true)// ...省略代码
}
● addProp调用addProp是为了给ast添加一个value的props属性。 ● addHandler调用addHandler是为了给ast添加一个事件监听至于到底监听什么事件取决于v-model作用于什么标签。 所以处理之后多了props和events属性
export function genData (el: ASTElement, state: CodegenState): string {let data {// directiveconst dirs genDirectives(el, state)if (dirs) data dirs ,// ...省略代码// DOM propsif (el.props) {data domProps:${genProps(el.props)},}// event handlersif (el.events) {data ${genHandlers(el.events, false)},}// ...省略代码return data
}
总结
其实学源码学到后续感觉有点懵 然后就是复习js 感觉红宝书讲的挺多的 马上也要期末考试了 希望期末平稳度过。