经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
Vue?组件上的v-model双向绑定原理解析
来源:jb51  时间:2022/5/18 8:43:06  对本文有异议

之前我们分析了Vuev-model指令在普通表单元素上的使用原理(点击这里跳转),这一节我们继续分析v-model指令在组件上的原理。

组件上的v-model原理

v-model指令在组件上的编译过程的parse阶段与在表单元素上一样(可以参考),与普通表单元素不同之处在于genCode的阶段,在执行model函数生成代码的时候,会执行genComponentModel函数:

v-model编译阶段

  1. export default function model (
  2. el: ASTElement,
  3. dir: ASTDirective,
  4. _warn: Function
  5. ): ?boolean {
  6. warn = _warn
  7. // 解析指令对象的值、修饰符、标签、类型
  8. const value = dir.value
  9. const modifiers = dir.modifiers
  10. const tag = el.tag
  11. const type = el.attrsMap.type
  12. ......
  13. } else if (tag === 'input' || tag === 'textarea') {
  14. // 本案例进入这个逻辑,我们分析一下
  15. genDefaultModel(el, value, modifiers)
  16. } else if (!config.isReservedTag(tag)) {
  17. // 非保留标签,说明是组件节点,执行genComponentModel
  18. genComponentModel(el, value, modifiers)
  19. // component v-model doesn't need extra runtime
  20. return false
  21. }
  22. ......
  23. return true
  24. }
  1. export function genComponentModel (
  2. el: ASTElement,
  3. value: string,
  4. modifiers: ?ASTModifiers
  5. ): ?boolean {
  6. // 解析修饰符
  7. const { number, trim } = modifiers || {}
  8.  
  9. const baseValueExpression = '$$v'
  10. let valueExpression = baseValueExpression
  11. // 有trim修饰符,进入下面逻辑,生成value表达式
  12. if (trim) {
  13. valueExpression =
  14. `(typeof ${baseValueExpression} === 'string'` +
  15. `? ${baseValueExpression}.trim()` +
  16. `: ${baseValueExpression})`
  17. }
  18. // 有number修饰符,生成下面表达式
  19. if (number) {
  20. valueExpression = `_n(${valueExpression})`
  21. }
  22. // 解析 value,生成解析规范后的表达式
  23. const assignment = genAssignmentCode(value, valueExpression)
  24.  
  25. // AST element上挂载model对象
  26. el.model = {
  27. value: `(${value})`,
  28. expression: `"${value}"`,
  29. callback: `function (${baseValueExpression}) {${assignment}}`
  30. }
  31. }

可以看到组件执行完genDirectives解析model指令后,会在AST element节点上生成model对象,这是与普通表单元素不同的地方。组件的v-modelgenCode过程中,执行完genDirectives后还有有一段逻辑,如下:

  1. export function genData (el: ASTElement, state: CodegenState): string {
  2. let data = '{'
  3.  
  4. // directives may mutate the el's other properties before they are generated.
  5. // 解析model指令
  6. const dirs = genDirectives(el, state)
  7. if (dirs) data += dirs + ','
  8.  
  9. ......
  10. // component v-model
  11. // 组件上的v-model,进入该逻辑,拼接生成下面代码字符串
  12. if (el.model) {
  13. data += `model:{value:${
  14. el.model.value
  15. },callback:${
  16. el.model.callback
  17. },expression:${
  18. el.model.expression
  19. }},`
  20. }

到这个时候才生成了最终的代码字符串。

组件生成阶段

  1. export function createComponent (
  2. Ctor: Class<Component> | Function | Object | void,
  3. data: ?VNodeData,
  4. context: Component,
  5. children: ?Array<VNode>,
  6. tag?: string
  7. ): VNode | Array<VNode> | void {
  8. // ...
  9. // transform component v-model data into props & events
  10. // 如果data上有model属性
  11. if (isDef(data.model)) {
  12. // 调用transformModel,传入的参数为组件构造器的options配置项
  13. transformModel(Ctor.options, data)
  14. }
  15.  
  16. // ...
  17. const vnode = new VNode(
  18. `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
  19. data, undefined, undefined, undefined, context,
  20. { Ctor, propsData, listeners, tag, children },
  21. asyncFactory
  22. )
  23. return vnode
  24. }

在创建组件的时候,有上面这样一段逻辑,当分析到节点上有model对象的时候,会调用transformModel函数,对v-model对象做下转化:

  1. // transform component v-model info (value and callback) into
  2. // prop and event handler respectively.
  3. function transformModel (options, data: any) {
  4. // 找到model上的prop属性
  5. const prop = (options.model && options.model.prop) || 'value'
  6. // 找到model上的event事件
  7. const event = (options.model && options.model.event) || 'input'
  8. // 在data的props属性对象上添加prop属性值
  9. ;(data.props || (data.props = {}))[prop] = data.model.value
  10. // 在data的on属性对象上添加event事件
  11. const on = data.on || (data.on = {})
  12. if (isDef(on[event])) {
  13. on[event] = [data.model.callback].concat(on[event])
  14. } else {
  15. on[event] = data.model.callback
  16. }
  17. }

可以看到最终是将编译过程中生成的model对象,解析成为value属性和input事件,扩展到组件构造器的options配置项中。

以上可以得知,组件上v-model指令的本质也是生成了value属性和input事件。

到此这篇关于Vue 组件上的v-model双向绑定原理的文章就介绍到这了,更多相关Vue v-model双向绑定内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号