Subscribe on changes!

Select options behaving differently in Vue 3 than Vue 2

avatar
Mar 24th 2021

Version

3.0.7

Reproduction link

Vue 3: https://codesandbox.io/s/distracted-ritchie-kdcwo?file=/src/App.vue

Vue 2: https://codesandbox.io/s/focused-glade-qj11z?file=/src/App.vue

Steps to reproduce

Click the submit button in both sandboxes

What is expected?

The <option> with value null shouldn't be rendered as a string in Vue 3.

What is actually happening?

When you add a couple of <option>, eventually an <option> with value null will be rendered as a it has a string value of null.

<!-- Vue 2 -->
<select name="large">
  <option value="">Not set</option>
  ...
</select>

<!-- Vue 3 -->
<select name="large">
  <option value="null">Not set</option>
  ...
</select>
avatar
Mar 24th 2021

https://github.com/vuejs/vue-next/blob/eb1fae63f926435fb0eef890663d24e09d4c79e1/packages/compiler-dom/src/transforms/stringifyStatic.ts#L73-L85

As we can see if you have more than 4 <option>s, Vue's compiler will try to stringify static nodes for performance reasons. So when you have 5 <option>s, the first <option> is stringified into "<option value=\"null\">Not set</option>" so we are experiencing the current issue.

Template Explorer →

avatar
Mar 24th 2021

There seems to be another bug that <option :value="null"> is rendered as <option value> when not taking the optimization path as for Vue 3 we have taken a new strategy for attribute coercion and the expected output should be <option> as null values for an attribute now indicates the attribute should be removed.

avatar
Mar 24th 2021

Though #3477 may fix that null values were rendered as "null", the difference between Vue 2 and 3 still exists and is intentional.

And there's still an issue to be investigated that <option :value="null"> is rendered as <option value="">, which does not comply with our latest coercion behavior.