A while ago I wrote the same component in Vue 2 and Vue 3 as an example of one versus the other:
https://codesandbox.io/s/bold-shamir-uqm0b?file=/src/compone...
https://codesandbox.io/s/bold-shamir-uqm0b?file=/src/compone...
If you meant more from a conceptual standpoint -- the usage patterns with Vue 3 is pretty nearly identical for most people. You just replace "data()" property with some "reactive()" state value in setup (or "ref()" for single values).
You CAN write things like generic hooks/"useXXX()" helpers, but you likely won't wind up with a ton of those.
Also, about the reference passing: it doesn't actually really work like that. If you pass a "ref()" or "reactive()" value as a prop to a child component, and you mutate it there, it doesn't propagate to the parent.
Vue will throw this warning:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "someRef"It (passing mutable values around) does make it harder to understand the data-flow, yes.
But we programmers keep assuming our rules & protection & orderliness are helpful & necessary. And those patterns we opt in to keep getting codified, embraced. But along comes someone who breaks those rules, & it keeps turning out, a lot of the things we think we do to be orderly & safe & sensible are actually not that helpful at all, or have impeded really wonderful progress elsewhere.
I think of React. Until React came along, everyone doing web development knew, it was obviously correct, that we needed templating languages. We knew we needed content & code separate. We knew content was obviously a different beast than code & that content should have tools designed for content. As it turns out, mixing code & content actually works really well & that we had ruled out a wide space of possibilities that were really simple, powerful, & direct.
Relatedly, here, with shared-mutable-variables, I'd pitch that hopefully tools compensate for a lot. Hopefully it's possible to run the app & see who is modifying values, see who is being updated when values change. It's nice being able to have the code tell you, up front, easily, but also hopefully watching at runtime is possible, makes it easy to suss out what the connections & causalities are within a system.
That said, if you want to use the composition api to share state you can, and you can pretty easily set up some structure to restrict mutability:
// useStore.ts
import { reactive, readonly } from 'vue'
export const useStore = () => {
const state = reactive({ count: 0 })
const increment = (val = 1) => state.count += val
return {
state: readonly(state), // Readonly so state can't be mutated directly...
increment, // ...only through the mutations provided, like Vuex
}
}
// store.ts
import { useStore } from './useStore'
export const store = useStore() // Now components can share this instance
// MyCounter.vue
import { store } from './store'
export default {
setup: () => ({
count: store.state.count,
onClick: () => store.increment(5),
}),
}
Or you can just keep using Vuex for sharing state and use the composition API for sharing self-contained bits of functionality. Or, if nothing else, using the `setup` method instead of the Options API just gives you much more control over how you organize your own code within a component.Vue (and some other frameworks) use a reactivity approach where the data is wrapped with a proxy that basically automates all this code. I find it much easier to reason about since it greatly reduces the complexity and you can focus on the actual data changes rather than all the plumbing to change the data.