bind.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { warn, setClass } from '../../util/index'
  2. import { BIND } from '../priorities'
  3. import vStyle from '../internal/style'
  4. import { tokensToExp } from '../../parsers/text'
  5. // xlink
  6. const xlinkNS = 'http://www.w3.org/1999/xlink'
  7. const xlinkRE = /^xlink:/
  8. // check for attributes that prohibit interpolations
  9. const disallowedInterpAttrRE = /^v-|^:|^@|^(?:is|transition|transition-mode|debounce|track-by|stagger|enter-stagger|leave-stagger)$/
  10. // these attributes should also set their corresponding properties
  11. // because they only affect the initial state of the element
  12. const attrWithPropsRE = /^(?:value|checked|selected|muted)$/
  13. // these attributes should set a hidden property for
  14. // binding v-model to object values
  15. const modelProps = {
  16. value: '_value',
  17. 'true-value': '_trueValue',
  18. 'false-value': '_falseValue'
  19. }
  20. export default {
  21. priority: BIND,
  22. bind () {
  23. var attr = this.arg
  24. var tag = this.el.tagName
  25. // should be deep watch on object mode
  26. if (!attr) {
  27. this.deep = true
  28. }
  29. // handle interpolation bindings
  30. const descriptor = this.descriptor
  31. const tokens = descriptor.interp
  32. if (tokens) {
  33. // handle interpolations with one-time tokens
  34. if (descriptor.hasOneTime) {
  35. this.expression = tokensToExp(tokens, this._scope || this.vm)
  36. }
  37. // only allow binding on native attributes
  38. if (
  39. disallowedInterpAttrRE.test(attr) ||
  40. (attr === 'name' && (tag === 'PARTIAL' || tag === 'SLOT'))
  41. ) {
  42. process.env.NODE_ENV !== 'production' && warn(
  43. attr + '="' + descriptor.raw + '": ' +
  44. 'attribute interpolation is not allowed in Vue.js ' +
  45. 'directives and special attributes.'
  46. )
  47. this.el.removeAttribute(attr)
  48. this.invalid = true
  49. }
  50. /* istanbul ignore if */
  51. if (process.env.NODE_ENV !== 'production') {
  52. var raw = attr + '="' + descriptor.raw + '": '
  53. // warn src
  54. if (attr === 'src') {
  55. warn(
  56. raw + 'interpolation in "src" attribute will cause ' +
  57. 'a 404 request. Use v-bind:src instead.'
  58. )
  59. }
  60. // warn style
  61. if (attr === 'style') {
  62. warn(
  63. raw + 'interpolation in "style" attribute will cause ' +
  64. 'the attribute to be discarded in Internet Explorer. ' +
  65. 'Use v-bind:style instead.'
  66. )
  67. }
  68. }
  69. }
  70. },
  71. update (value) {
  72. if (this.invalid) {
  73. return
  74. }
  75. var attr = this.arg
  76. if (this.arg) {
  77. this.handleSingle(attr, value)
  78. } else {
  79. this.handleObject(value || {})
  80. }
  81. },
  82. // share object handler with v-bind:class
  83. handleObject: vStyle.handleObject,
  84. handleSingle (attr, value) {
  85. const el = this.el
  86. const interp = this.descriptor.interp
  87. if (
  88. !interp &&
  89. attrWithPropsRE.test(attr) &&
  90. attr in el
  91. ) {
  92. el[attr] = attr === 'value'
  93. ? value == null // IE9 will set input.value to "null" for null...
  94. ? ''
  95. : value
  96. : value
  97. }
  98. // set model props
  99. var modelProp = modelProps[attr]
  100. if (!interp && modelProp) {
  101. el[modelProp] = value
  102. // update v-model if present
  103. var model = el.__v_model
  104. if (model) {
  105. model.listener()
  106. }
  107. }
  108. // do not set value attribute for textarea
  109. if (attr === 'value' && el.tagName === 'TEXTAREA') {
  110. el.removeAttribute(attr)
  111. return
  112. }
  113. // update attribute
  114. if (value != null && value !== false) {
  115. if (attr === 'class') {
  116. // handle edge case #1960:
  117. // class interpolation should not overwrite Vue transition class
  118. if (el.__v_trans) {
  119. value += ' ' + el.__v_trans.id + '-transition'
  120. }
  121. setClass(el, value)
  122. } else if (xlinkRE.test(attr)) {
  123. el.setAttributeNS(xlinkNS, attr, value === true ? '' : value)
  124. } else {
  125. el.setAttribute(attr, value === true ? '' : value)
  126. }
  127. } else {
  128. el.removeAttribute(attr)
  129. }
  130. }
  131. }