I have been a huge VueJS fan for the past several years. Vue has allowed me to create web applications with an extremely high degree of efficiency.
Today in my first attempt to use Vue 3 I fought with it for about 5 hours to create a single simple checkbox.
The idea was simple:
Take a FAST component like checkbox and wrap it up for easy use in a new Vue3 app.
Why Microsoft created these neat components and then proceeded to not provide any way to actually use them in Vue is a bit mind boggling, but, hey I've created thousands of Vue (2) components. Should be a piece of cake right?
Ok... Let's fire up a new Vue3 project following the quickstart quide. Then, crack it open and take a look around:
What the hell is this?
All the code on Vue's Guide looks like this:
The component's code is 100% nothing like what I got in my new project that I just created with the Vue recommended method. (It gets even worse if you choose Typescript, with red squiqqly lines everywhere in your new project!)
By forcing users to start with the new Composition API in starter projects, but maintaining a focus on the Options API in the documentation, Vue is creating a giant mess for developers who are new to the framework.
This single inconsistency is going to result in thousands of developers getting frustrated and trying some other framework instead.
The default starter project must look like the documentation!
I've soldiered on trying to use the Composition API for few hours to make my humble checkbox. However, even simple things like watching a prop have turned out to be extraordinarily difficult.
I did eventually find this page : https://vuejs.org/api/
Unfortunately, my confidence in Vue is horribly shaken at this point.
P.S. I did get the checkbox working (and yes it did take over 5 hours!)
<script setup lang="ts">
import type { Checkbox } from "@microsoft/fast-foundation";
import { watch, ref, onMounted } from "vue";
// Why can't I just do this?
// let checked = false;
// This looks pretty ugly, but it defines our emit for v-model (passes internal changes up to the v-model)
const emit = defineEmits<{
(e: "update:modelValue", value: boolean): void;
}>();
// This is ugly too, but it defines the prop for v-model (brings external changes in from v-model)
const props = defineProps<{
modelValue: boolean;
}>();
// Maintain internal state with a ref
const checked = ref<boolean>(props.modelValue);
// Ok, if you thought the stuff above was ugly, take a look at this.
// Who in their right mind can read this and figure out what is
// going on here.
watch(
() => props.modelValue,
(newValue) => {
if (checked.value != newValue) {
checked.value = newValue;
}
}
);
// When the native fluent-checkbox changes it's value, sync to internal state and v-model
const onChange = (change: CustomEvent) => {
if (change?.target) {
// Gotta love having to do this funky cast...
checked.value = (change.target as Checkbox).checked;
emit("update:modelValue", checked.value);
}
};
</script>
<template>
<fluent-checkbox @change="onChange" :checked="checked">
<slot></slot>
</fluent-checkbox>
</template>