Home > Blockchain >  How to generate computed props while accessing the Vue instance?
How to generate computed props while accessing the Vue instance?

Time:02-15

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),
    }
  }
}

demo

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>

  • Related