dom-props.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /* @flow */
  2. import { isDef, isUndef, extend, toNumber } from 'shared/util'
  3. function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
  4. if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
  5. return
  6. }
  7. let key, cur
  8. const elm: any = vnode.elm
  9. const oldProps = oldVnode.data.domProps || {}
  10. let props = vnode.data.domProps || {}
  11. // clone observed objects, as the user probably wants to mutate it
  12. if (isDef(props.__ob__)) {
  13. props = vnode.data.domProps = extend({}, props)
  14. }
  15. for (key in oldProps) {
  16. if (isUndef(props[key])) {
  17. elm[key] = ''
  18. }
  19. }
  20. for (key in props) {
  21. cur = props[key]
  22. // ignore children if the node has textContent or innerHTML,
  23. // as these will throw away existing DOM nodes and cause removal errors
  24. // on subsequent patches (#3360)
  25. if (key === 'textContent' || key === 'innerHTML') {
  26. if (vnode.children) vnode.children.length = 0
  27. if (cur === oldProps[key]) continue
  28. }
  29. if (key === 'value') {
  30. // store value as _value as well since
  31. // non-string values will be stringified
  32. elm._value = cur
  33. // avoid resetting cursor position when value is the same
  34. const strCur = isUndef(cur) ? '' : String(cur)
  35. if (shouldUpdateValue(elm, vnode, strCur)) {
  36. elm.value = strCur
  37. }
  38. } else {
  39. elm[key] = cur
  40. }
  41. }
  42. }
  43. // check platforms/web/util/attrs.js acceptValue
  44. type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement;
  45. function shouldUpdateValue (
  46. elm: acceptValueElm,
  47. vnode: VNodeWithData,
  48. checkVal: string
  49. ): boolean {
  50. return (!elm.composing && (
  51. vnode.tag === 'option' ||
  52. isDirty(elm, checkVal) ||
  53. isInputChanged(elm, checkVal)
  54. ))
  55. }
  56. function isDirty (elm: acceptValueElm, checkVal: string): boolean {
  57. // return true when textbox (.number and .trim) loses focus and its value is
  58. // not equal to the updated value
  59. let notInFocus = true
  60. // #6157
  61. // work around IE bug when accessing document.activeElement in an iframe
  62. try { notInFocus = document.activeElement !== elm } catch (e) {}
  63. return notInFocus && elm.value !== checkVal
  64. }
  65. function isInputChanged (elm: any, newVal: string): boolean {
  66. const value = elm.value
  67. const modifiers = elm._vModifiers // injected by v-model runtime
  68. if (isDef(modifiers) && modifiers.number) {
  69. return toNumber(value) !== toNumber(newVal)
  70. }
  71. if (isDef(modifiers) && modifiers.trim) {
  72. return value.trim() !== newVal.trim()
  73. }
  74. return value !== newVal
  75. }
  76. export default {
  77. create: updateDOMProps,
  78. update: updateDOMProps
  79. }