Ошибка во время выполнения при интеграции библиотеки компонентов, использующей @vue / composition-api: «Вы должны использовать эту функцию в методе «setup ()»»

#vue.js #vuejs2 #vue-cli #vue-composition-api #vue-cli-4

#vue.js #vuejs2 #vue-cli #vue-composition-api #vue-cli-4

Вопрос:

Любая помощь в решении следующей проблемы будет с благодарностью!

Ситуация:

Мой проект содержит два пакета:

  1. дочерний компонент-библиотека

    • содержит единственное представление About.vue , написанное в стиле composition-API (со вспомогательными библиотеками @vue/composition-api vue2 и vuex-composition-helpers )
    • экспортирует один RouteConfig
    • сборка как библиотека

    views/About.vue (дочерний элемент)

     <template>
      <div class="about">
        <h1>This is an about page (as component lib)</h1>
      </div>
    </template>
    
    <script>
    import { defineComponent } from "@vue/composition-api";
    import { createNamespacedHelpers } from "vuex-composition-helpers";
    
    export default defineComponent({
      components: {},
      setup(_, { root }) {
        const { useGetters, useActions } = createNamespacedHelpers("account"); // error thrown here!
      }
    });
    </script>
      

    router/index.ts (дочерний элемент)

     export const routes: Array<RouteConfig> = [{
        path: "/",
        name: "About",
        component: () => import(/* webpackChunkName: "about" */ "../views/About.vue")
    }];
      

    lib.ts (дочерний элемент)

     export const routes = require("@/router").routes;
      

    package.json (дочерний элемент)

     "scripts": {
      "build": "vue-cli-service build --target lib --name child-component-lib src/lib.ts"
    ...
      

  1. родительское приложение

    • импортирует маршрут из child-component-lib своего маршрутизатора
    • содержит простое представление, в котором отображается одна строка текста и <router-view />

    package.json (родительский)

     "dependencies": {
        "@tholst/child-component-lib": "file:../child-component-lib",
      

    router/index.ts (родительский)

     import { routes as childComponentRoutes } from "@tholst/child-component-lib";
    
    const routes: Array<RouteConfig> = [...childComponentRoutes];
    const router = new VueRouter({routes});    
    export default router;
      

    App.vue (родительский)

     <template>
      <div id="app">
        <Home />
        <router-view />
      </div>
    </template>
    
    <script>
    import { defineComponent } from "@vue/composition-api";
    import Home from "@/views/Home.vue";
    
    export default defineComponent({
      components: {
        Home
      },
      setup(_, { root }) {
        ...
      }
    });
    </script>
      

Ожидаемое поведение

Она работает без проблем.

Фактическое поведение

Я вижу вывод ошибки в консоли. [Vue warn]: Error in data(): "Error: You must use this function within the "setup()" method, or insert the store as first argument." Сообщение об ошибке вводит в заблуждение, потому что ошибка фактически выдается внутри setup() метода. Это можно проследить до getCurrentInstance() возврата undefined (внутри @vue/composition-api ).


Расследование:

  • Оказывается, ошибка исчезает, когда я включаю то же About.vue самое в само родительское приложение (просто переключите маршрут, чтобы попробовать), т. Е. Это работает, когда мы избегаем импорта из встроенной библиотеки.
  • Похоже, это проблема с настройкой сборки (одна из vue.config.js , webpack , babel , typescript , …)

Воспроизвести ошибку:

1. Клонировать, устанавливать, запускать

 git clone git@github.com:tholst/vue-composition-api-comp-lib.git amp;amp; cd vue-composition-api-comp-lib/child-component-lib amp;amp; npm install amp;amp; npm run build amp;amp; cd ../parent-app/ amp;amp; npm install amp;amp; npm run serve
  

или один за другим

 git clone git@github.com:tholst/vue-composition-api-comp-lib.git
cd vue-composition-api-comp-lib/child-component-lib
npm install
npm run build
cd ../parent-app/
npm install
npm run serve
  

2. Откройте браузер

  • Перейдите к http://localhost:8080/

3. Откройте инструменты разработки, чтобы увидеть ошибку

 [Vue warn]: Error in data(): "Error: You must use this function within the "setup()" method, or insert the store as first argument."

found in

---> <Anonymous>
       <App> at src/App.vue
         <Root>
  

Скриншот ошибки

Ошибка в консоли

Информация об окружающей среде:

 Node: 14.2.0
npm: 6.14.8
Chrome: 86.0.4240.198

npmPackages:
    @vue/babel-sugar-composition-api-inject-h:  1.2.1 
    @vue/babel-sugar-composition-api-render-instance:  1.2.4 
    ...    
    @vue/cli-overlay:  4.5.8 
    @vue/cli-plugin-babel: 4.5.8 
    @vue/cli-plugin-router: 4.5.8 
    @vue/cli-plugin-typescript: 4.5.8 
    @vue/cli-plugin-vuex:4.5.8 
    @vue/cli-service: 4.5.8 
    @vue/cli-shared-utils:  4.5.8 
    @vue/component-compiler-utils:  3.2.0 
    @vue/composition-api: 1.0.0-beta.19 
    @vue/preload-webpack-plugin:  1.1.2 
    typescript: 3.9.7 
    vue: 2.6.12 
    vue-loader:  15.9.5 (16.0.0-rc.1)
    vue-router: 3.4.9
    vue-template-compiler: 2.6.12 
    vue-template-es2015-compiler:  1.9.1 
    vuex: 3.5.1 
    vuex-composition-helpers: 1.0.21 

npmGlobalPackages:
    @vue/cli: 4.5.8
  

Ответ №1:

Я наконец понял, в чем были проблемы. Во-первых, возникла реальная проблема. Во-вторых, в локальной настройке разработки была проблема, из-за которой решения реальной проблемы выглядели так, как будто они не работают.

Фактическая проблема решение

Дочерняя библиотека компонентов объединяла свои собственные версии пакетов npm @vue/composition-api и vuex-composition-helpers . Это имело следующий эффект: когда я запускал родительское приложение, на самом деле было два экземпляра этих библиотек, и компонент vue из дочерней библиотеки-компонента обращался к неправильному объекту, который не был должным образом инициализирован.

Решение состояло в том, чтобы предотвратить объединение этих библиотек в дочернюю библиотеку компонентов, путем

  1. создание их devDependencies и peerDependencies .

  2. указание webpack не связывать их npm run build .

    package.json

     "dependencies": {
        ...
    },
    "devDependencies": {
        "@vue/composition-api": "^1.0.0-beta.19",
        "vuex-composition-helpers": "^1.0.21",
        ...
    },
    "peerDependencies": {
        "@vue/composition-api": "^1.0.0-beta.19",
        "vuex-composition-helpers": "^1.0.21"
    },
      

    vue.config.js

     configureWebpack: {
        externals: {
            "@vue/composition-api": "@vue/composition-api",
            "vuex-composition-helpers": "vuex-composition-helpers"
        },
        ...
    }
      

Сложная проблема, которая усложняла ситуацию

Я пытался решить эту проблему локально, фактически не публикуя пакет. И, похоже, это сработало, потому что я видел ту же проблему локально, что и в опубликованных пакетах.

Я выполнил локальную разработку, напрямую связав библиотеки родительского приложения и дочернего компонента. Я пробовал оба

  1. прямая зависимость от папки

    package.json

     "dependencies": {
        "@tholst/child-component-lib": "file:../child-component-lib",
    },
      
  2. npm link

     cd child-component-lib
    npm link
    cd ../parent-app
    npm link @tholst/child-component-lib
      

Оба подхода приводят к тому, что они фактически импортируют (= символическую ссылку на) папку дочерней библиотеки компонентов со всеми файлами и папками (вместо только файлов, которые будут опубликованы в пакете npm).

И это означало следующее: несмотря на то, что я исключил две библиотеки composition-API из пакета и сделал их зависимостями от разработчиков / одноранговых узлов (см. Решение Актуальной проблемы), они все еще были установлены и присутствовали в дочерних библиотеках component-lib node_modules . И эта node_modules папка была символически связана с пакетом родительского приложения. И таким образом дочерняя библиотека компонентов по-прежнему имела доступ к своей собственной копии библиотек, которые мы хотели исключить из сборки (см. Актуальную проблему).). И я все еще видел ошибку, как и раньше.

И таким образом, мой локальный подход к разработке скрыл тот факт, что решение реальной проблемы действительно работало.

Комментарии:

1. Я хотел бы видеть ваш пост раньше, столкнулся с точно такой же проблемой, и я так сильно старался найти решение!

2. @JoelPintoRibeiro Да, мне тоже потребовались дни борьбы!