I was wondering if there is a way of creating computed props programatically, while still accessing the instance to achieve dynamic values
Something like that (this
being undefined below)
<script>
export default {
computed: {
...createDynamicPropsWithTheContext(this), // helper function that returns an object
}
}
</script>
On this question, there is a solution given by Linus: https://forum.vuejs.org/t/generating-computed-properties-on-the-fly/14833/4 looking like
computed: {
...mapPropsModels(['cool', 'but', 'static'])
}
This works fine but the main issue is that it's fully static. Is there a way to access the Vue instance to reach upon props for example?
More context
For testing purposes, my helper function is as simple as
export const createDynamicPropsWithTheContext = (listToConvert) => {
return listToConvert?.reduce((acc, curr) => {
acc[curr] = curr
return acc
}, {})
}
What I actually wish to pass down to this helper function (via this
) are props that are matching a specific prefix aka starting with any of those is|can|has|show
(I'm using a regex), that I do have access via this.$options.props
in a classic parent/child state transfer.
The final idea of my question is mainly to avoid manually writing all the props manually like ...createDynamicPropsWithTheContext(['canSubmit', 'showModal', 'isClosed'])
but have them populated programatically (this pattern will be required in a lot of components).
The props are passed like this
<my-component can-submit="false" show-modal="true" />
PS: it's can-submit
and not :can-submit
on purpose (while still being hacked into a falsy
result right now!).
It's for the ease of use for the end user that will not need to remember to prefix with :
, yeah I know...a lot of difficulty just for a semi-colon that could follow Vue's conventions.
CodePudding user response:
You could use the setup()
hook, which receives props
as its first argument. Pass the props
argument to createDynamicPropsWithTheContext
, and spread the result in setup()
's return (like you had done previously in the computed
option):
import { createDynamicPropsWithTheContext } from './props-utils'
export default {
⋮
setup(props) {
return {
...createDynamicPropsWithTheContext(props),
}
}
}
CodePudding user response:
If the whole thing is for avoiding using a :
, then you might want to consider using a simple object (or array of objects) as data source. You could just iterate over a list and bind the data to the components generated. In this scenario the only :
used are in the objects
const comps = [{
"can-submit": false,
"show-modal": true,
"something-else": false,
},
{
"can-submit": true,
"show-modal": true,
"something-else": false,
},
{
"can-submit": false,
"show-modal": true,
"something-else": true,
},
]
const CustomComponent = {
setup(props, { attrs }) {
return {
attrs
}
},
template: `
<div
v-bind="attrs"
>{{ attrs }}</div>
`
}
const vm = Vue.createApp({
setup() {
return {
comps
}
},
template: `
<custom-component
v-for="(item, i) in comps"
v-bind="item"
></custom-component>
`
})
vm.component('CustomComponent', CustomComponent)
vm.mount('#app')
<script src="https://unpkg.com/vue@3"></script>
<div id="app">{{ message }}</div>