davestewart / vuex-pathify

Vue / Vuex plugin providing a unified path syntax to Vuex stores
https://davestewart.github.io/vuex-pathify
MIT License
1.37k stars 57 forks source link

questions about the new Vue 3 beta #145

Open vesper8 opened 2 years ago

vesper8 commented 2 years ago

Hello! I've been using your awesome library for many years now, and recently I was tasked with migrating a project that made heavy use of this library to Vue 3.

I've begun doing this and am currently using your 3.0.0-beta branch in my package.json

I guess my first question is, if I have it set like this "vuex-pathify": "3.0.0-beta", will I receive your new updates when you make them?

I use a module autoloader script which looks like this:

import modules from './modules';

Pathify.options.mapping = 'simple' // options

const store = createStore({
  plugins: [
    Pathify.plugin,
  ],

  modules,
});

export default store;
import camelCase from 'lodash/camelCase';

const requireModule = require.context(
  '.', false, /\.js/,
);

const modules = {};

requireModule.keys().forEach(fileName => {
  // Don't register this file as a Vuex module
  if (fileName === './index.js') return;

  const moduleName = camelCase(
    fileName.replace(/(\.\/|.js)/g, ''),
  );

  modules[moduleName] = {
    ...requireModule(fileName).default,
  };
});

export default modules;

And I'm happy to report that this continues to work with the latest beta.

Now onto a question. Previously I would use the sync helper pretty much exclusively and I had things like this:

computed: {
    ...sync([
      'device',
      'search/count',
      'meta/title',
      'meta/description',
    ]),
}

So here I'm referencing from 3 different modules (device, search and meta), in the case of device, I'm loading the entire module, which then gives me access to anything of the nested items in the device module. With the other two modules, I'm referencing nested items from the module state.

Now I'm trying to wrap my head around how this has changed with Vue 3.

I also prefer to keep using the options API for now.

So for a simple case where I was previously doing this:

    ...sync([
      'search/zipSlug', //
      'search/count', //
    ]),

It seems I must now do this:

    ...sync(
      'search',
      [
        'zipSlug',
        'count',
      ],
      false,
    ),

Correct?

This does seem to work. My problem is.. how do I rewrite the above sample to the new Vue 3 syntax?

It looks like when using sync I can only reference one module at a time. So I now have to use multiple ...sync inside my computed ? Like this:

computed: {
    ...sync(
      'search', //
      [
        'zipSlug', //
        'count', //
      ],
      false,
    ),
    ...sync(
      'meta', //
      [
        'title', //
        'description', //
      ],
      false,
    ),
},

Is that right? Not quite as clean as it was before.. but ok.. but if there's a better way please let me know.

I can't figure out how to tap into the whole module using sync. I've tried this:

    ...sync(
      'device',
      false,
    ),

but this doesn't seem to work...

This does work:

    device: get(
      'device',
      false,
    ),

I'm just not used to using get, is this now a requirement if I want to gain access to the root of my vuex module like I was doing before with sync ? I was also under the impression that when using sync you can get and set, but this won't work now if I use get will it?

Overall it would have been nice if it was possible to just keep using the same syntax as before.. possibly we could still achieve this, by setting configuration properties when initializing the plugin in the store? So for example, if we want to keep using the options api, could we set a configuration param so we don't have to pass false everywhere.

And if it would be possible to continue using it like before, such as in my sample above:

computed: {
    ...sync([
      'device',
      'search/count',
      'meta/title',
      'meta/description',
    ]),
}

That would be super fantastic!!

Please let me know if this is maybe already possible and I'm just doing it wrong. And thanks a lot for your continued work on this library.

vesper8 commented 2 years ago

Also wanted to point out that on this page https://github.com/davestewart/vuex-pathify/blob/feat/vue3/docs/pages/guide/composition-api.md

These two links don't work:

https://github.com/davestewart/vuex-pathify/blob/feat/vue3/guide/component https://github.com/davestewart/vuex-pathify/blob/feat/vue3/reference/api?id=component-helpers

davestewart commented 2 years ago

Hey Vesper!

Thanks for the issue.

In hindsight, I think @sanscheese made a good point here proposing that the new Vuex Pathify API lean towards supporting the Options API by default, seeing as most users will probably be migrating from Vue 2 apps which will already be built using Options API.

Either that, or I could make an additional import path available to them, something like this:

import { get, sync } from 'vuex-pathify/options'

As for the changed syntax, you make a valid point. It would be great if the old syntax could be used verbatim, maybe with the additional import path as mentioned above.

Thanks for raising the issue, and let me take a look over the next week to see what can be done.

sanscheese commented 2 years ago

Options import path is a great idea!

rob-64 commented 2 years ago

For my TS friends:

export default (context: SetupContext) => {
  const { $store } = context.root;
  function get<T extends {}>(path: string) {
    return computed(() => $store.get(path) as T);
  }
  function set<T>(path: string, value: T) {
    return computed(() => $store.set(path, value) as T);
  }
  function sync<T>(path: string) {
    return computed({
      get() {
        return $store.get(path) as T;
      },
      set(value: T) {
        return $store.set(path, value) as T;
      },
    });
  }

  return { get, set, sync };
};