Browse Source

make attr behavior more consistent + fix tests

Evan You 10 năm trước cách đây
mục cha
commit
5fb1a549d2

+ 14 - 7
src/platforms/web/runtime/modules/attrs.js

@@ -1,4 +1,11 @@
-import { isBooleanAttr, isEnumeratedAttr, isXlink, xlinkNS, getXlinkProp } from 'web/util/index'
+import {
+  isBooleanAttr,
+  isEnumeratedAttr,
+  isXlink,
+  xlinkNS,
+  getXlinkProp,
+  isFalsyAttrValue
+} from 'web/util/index'
 
 function updateAttrs (oldVnode, vnode) {
   if (!oldVnode.data.attrs && !vnode.data.attrs) {
@@ -31,24 +38,24 @@ function setAttr (el, key, value) {
   if (isBooleanAttr(key)) {
     // set attribute for blank value
     // e.g. <option disabled>Select one</option>
-    if (value == null || value === false) {
+    if (isFalsyAttrValue(value)) {
       el.removeAttribute(key)
     } else {
       el.setAttribute(key, key)
     }
   } else if (isEnumeratedAttr(key)) {
-    el.setAttribute(key, value ? 'true' : 'false')
+    el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true')
   } else if (isXlink(key)) {
-    if (value == null || value === false) {
+    if (isFalsyAttrValue(value)) {
       el.removeAttributeNS(xlinkNS, getXlinkProp(key))
     } else {
-      el.setAttributeNS(xlinkNS, key, value === true ? '' : value)
+      el.setAttributeNS(xlinkNS, key, value)
     }
   } else {
-    if (value == null || value === false) {
+    if (isFalsyAttrValue(value)) {
       el.removeAttribute(key)
     } else {
-      el.setAttribute(key, value === true ? '' : value)
+      el.setAttribute(key, value)
     }
   }
 }

+ 10 - 7
src/platforms/web/server/modules/attrs.js

@@ -1,4 +1,9 @@
-import { isBooleanAttr, isEnumeratedAttr, propsToAttrMap } from 'web/util/index'
+import {
+  isBooleanAttr,
+  isEnumeratedAttr,
+  isFalsyAttrValue,
+  propsToAttrMap
+} from 'web/util/index'
 
 export default function renderAttrs (node) {
   if (node.data.attrs || node.data.props || node.data.staticAttrs) {
@@ -25,15 +30,13 @@ function serialize (attrs, asProps) {
     }
     const value = attrs[key]
     if (isBooleanAttr(key)) {
-      if (!(value == null || value === false)) {
+      if (!isFalsyAttrValue(value)) {
         res += ` ${key}="${key}"`
       }
     } else if (isEnumeratedAttr(key)) {
-      res += ` ${key}="${value ? 'true' : 'false'}"`
-    } else {
-      if (!(value == null || value === false)) {
-        res += ` ${key}="${value === true ? '' : value}"`
-      }
+      res += ` ${key}="${isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true'}"`
+    } else if (!isFalsyAttrValue(value)) {
+      res += ` ${key}="${value}"`
     }
   }
   return res

+ 1 - 0
src/platforms/web/util/attrs.js

@@ -24,3 +24,4 @@ export const propsToAttrMap = {
 export const xlinkNS = 'http://www.w3.org/1999/xlink'
 export const isXlink = name => name.charAt(5) === ':' && name.slice(0, 5) === 'xlink'
 export const getXlinkProp = name => isXlink(name) ? name.slice(6, name.length) : ''
+export const isFalsyAttrValue = val => val == null || val === false

+ 5 - 1
test/ssr/ssr.sync.spec.js

@@ -142,7 +142,7 @@ describe('SSR: renderToString', () => {
         '<span test="ok">hello</span>' +
         '<span>hello</span>' +
         '<span>hello</span>' +
-        '<span test="">hello</span>' +
+        '<span test="true">hello</span>' +
         '<span test="0">hello</span>' +
       '</div>'
     )
@@ -155,7 +155,9 @@ describe('SSR: renderToString', () => {
           <span :draggable="true">hello</span>
           <span :draggable="'ok'">hello</span>
           <span :draggable="null">hello</span>
+          <span :draggable="false">hello</span>
           <span :draggable="''">hello</span>
+          <span :draggable="'false'">hello</span>
         </div>
       `
     })).toContain(
@@ -163,7 +165,9 @@ describe('SSR: renderToString', () => {
         '<span draggable="true">hello</span>' +
         '<span draggable="true">hello</span>' +
         '<span draggable="false">hello</span>' +
+        '<span draggable="false">hello</span>' +
         '<span draggable="true">hello</span>' +
+        '<span draggable="false">hello</span>' +
       '</div>'
     )
   })

+ 8 - 2
test/unit/features/directives/bind.spec.js

@@ -19,7 +19,7 @@ describe('Directive v-bind', () => {
       expect(vm.$el.firstChild.hasAttribute('test')).toBe(false)
       vm.foo = true
     }).then(() => {
-      expect(vm.$el.firstChild.getAttribute('test')).toBe('')
+      expect(vm.$el.firstChild.getAttribute('test')).toBe('true')
       vm.foo = 0
     }).then(() => {
       expect(vm.$el.firstChild.getAttribute('test')).toBe('0')
@@ -68,7 +68,7 @@ describe('Directive v-bind', () => {
       expect(vm.$el.firstChild.hasAttributeNS(xlinkNS, 'special')).toBe(false)
       vm.foo = true
     }).then(() => {
-      expect(vm.$el.firstChild.getAttributeNS(xlinkNS, 'special')).toBe('')
+      expect(vm.$el.firstChild.getAttributeNS(xlinkNS, 'special')).toBe('true')
       done()
     }).catch(done)
   })
@@ -87,6 +87,12 @@ describe('Directive v-bind', () => {
     }).then(() => {
       expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')
       vm.foo = ''
+    }).then(() => {
+      expect(vm.$el.firstChild.getAttribute('draggable')).toBe('true')
+      vm.foo = false
+    }).then(() => {
+      expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')
+      vm.foo = 'false'
     }).then(() => {
       expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')
       done()