Kaynağa Gözat

fix: backwards compat with checkbox code generated in < 2.5

fix #6803
Evan You 8 yıl önce
ebeveyn
işleme
5665eaf985

+ 1 - 0
src/platforms/web/compiler/directives/model.js

@@ -9,6 +9,7 @@ let warn
 // in some cases, the event used has to be determined at runtime
 // so we used some reserved tokens during compile.
 export const RANGE_TOKEN = '__r'
+export const CHECKBOX_RADIO_TOKEN = '__c'
 
 export default function model (
   el: ASTElement,

+ 8 - 1
src/platforms/web/runtime/modules/events.js

@@ -3,7 +3,7 @@
 import { isDef, isUndef } from 'shared/util'
 import { updateListeners } from 'core/vdom/helpers/index'
 import { isIE, supportsPassive } from 'core/util/env'
-import { RANGE_TOKEN } from 'web/compiler/directives/model'
+import { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'
 
 // normalize v-model event tokens that can only be determined at runtime.
 // it's important to place the event as the first in the array because
@@ -17,6 +17,13 @@ function normalizeEvents (on) {
     on[event] = [].concat(on[RANGE_TOKEN], on[event] || [])
     delete on[RANGE_TOKEN]
   }
+  // This was originally intended to fix #4521 but no longer necessary
+  // after 2.5. Keeping it for backwards compat with generated code from < 2.4
+  /* istanbul ignore if */
+  if (isDef(on[CHECKBOX_RADIO_TOKEN])) {
+    on.change = [].concat(on[CHECKBOX_RADIO_TOKEN], on.change || [])
+    delete on[CHECKBOX_RADIO_TOKEN]
+  }
 }
 
 let target: HTMLElement

+ 48 - 0
test/unit/modules/vdom/patch/edge-cases.spec.js

@@ -198,4 +198,52 @@ describe('vdom patch: edge cases', () => {
     }).$mount()
     expect(vm.$el.textContent).toBe('')
   })
+
+  // #6803
+  it('backwards compat with checkbox code generated before 2.4', () => {
+    const spy = jasmine.createSpy()
+    const vm = new Vue({
+      data: {
+        label: 'foobar',
+        name: 'foobar'
+      },
+      computed: {
+        value: {
+          get () {
+            return 1
+          },
+          set: spy
+        }
+      },
+      render (h) {
+        const _vm = this
+        return h('div', {},
+          [h('input', {
+            directives: [{
+              name: 'model',
+              rawName: 'v-model',
+              value: (_vm.value),
+              expression: 'value'
+            }],
+            attrs: {
+              'type': 'radio',
+              'name': _vm.name
+            },
+            domProps: {
+              'value': _vm.label,
+              'checked': _vm._q(_vm.value, _vm.label)
+            },
+            on: {
+              '__c': function ($event) {
+                _vm.value = _vm.label
+              }
+            }
+          })])
+      }
+    }).$mount()
+
+    document.body.appendChild(vm.$el)
+    vm.$el.children[0].click()
+    expect(spy).toHaveBeenCalled()
+  })
 })