vModel.ts 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import {
  2. transformModel as baseTransform,
  3. DirectiveTransform,
  4. ElementTypes,
  5. findProp,
  6. NodeTypes
  7. } from '@vue/compiler-core'
  8. import { createDOMCompilerError, DOMErrorCodes } from '../errors'
  9. import {
  10. V_MODEL_CHECKBOX,
  11. V_MODEL_RADIO,
  12. V_MODEL_SELECT,
  13. V_MODEL_TEXT,
  14. V_MODEL_DYNAMIC
  15. } from '../runtimeHelpers'
  16. export const transformModel: DirectiveTransform = (dir, node, context) => {
  17. const res = baseTransform(dir, node, context)
  18. const { tag, tagType } = node
  19. if (tagType === ElementTypes.ELEMENT) {
  20. if (dir.arg) {
  21. context.onError(
  22. createDOMCompilerError(
  23. DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
  24. dir.arg.loc
  25. )
  26. )
  27. }
  28. if (tag === 'input' || tag === 'textarea' || tag === 'select') {
  29. let directiveToUse = V_MODEL_TEXT
  30. if (tag === 'input') {
  31. const type = findProp(node, `type`)
  32. if (type) {
  33. if (type.type === NodeTypes.DIRECTIVE) {
  34. // :type="foo"
  35. directiveToUse = V_MODEL_DYNAMIC
  36. } else if (type.value) {
  37. switch (type.value.content) {
  38. case 'radio':
  39. directiveToUse = V_MODEL_RADIO
  40. break
  41. case 'checkbox':
  42. directiveToUse = V_MODEL_CHECKBOX
  43. break
  44. }
  45. }
  46. }
  47. } else if (tag === 'select') {
  48. directiveToUse = V_MODEL_SELECT
  49. }
  50. // inject runtime directive
  51. // by returning the helper symbol via needRuntime
  52. // the import will replaced a resovleDirective call.
  53. res.needRuntime = context.helper(directiveToUse)
  54. } else {
  55. context.onError(
  56. createDOMCompilerError(
  57. DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
  58. dir.loc
  59. )
  60. )
  61. }
  62. }
  63. return res
  64. }