• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Po migracji z vue 2 na vue 3 event handler nie jest przypisywany do komponentu

Object Storage Arubacloud
+4 głosów
384 wizyt
pytanie zadane 6 sierpnia 2021 w JavaScript przez Artek Stary wyjadacz (11,800 p.)

Tak jak w opisie. Jestem podczas migracji aplikacji z vue 2 na vue 3. W vue 2 mieliśmy coś takiego :

<some-component v-on:click.native="someEventHandler"> </some-component>

W wersji 3 modyfikator native przeszedł do lamusa i dlatego usunąłem w swych komponentach ów zapis.

Mam np taki kod.

<button-close
        v-on:click="hideCategories"
        class="panel-bar__close-button"></button-close>


hideCategories(){alert('event odpalony'); return 0;}

Oczywiście <button-close> to mój komponent .Teoretycznie jest to zgodne z oficjalną instrukcją. W wersji 3 wszystkie eventy które nie są podawane w opcji emit komponentu są traktowane jako natywne eventy.

https://v3.vuejs.org/guide/migration/v-on-native-modifier-removed.html#_2-x-syntax

Problem polega na tym, że to nie działa, handler nie jest podczepiany, alert się nie wyświetla. Co ciekawe gdy zrobimy coś takiego :

 <button
        v-on:click="hideCategories"
        class="panel-bar__close-button"
      ></button>

Czyli użyjemy zwykłego html'a wszystko działa poprawnie.

Dodam też, że ów komponent jest rejestrowany globalnie, występuje na każdej podstronie - poniższy fragment kodu jest dołączany do każdego skryptu konkretnej podstrony wygląda to tak :

export default {

   registerBasicComponents(app) {
      app.component('authenticated-user-sidebar', AuthenticatedUserSidebar);
      app.component('navbar', Navbar);
      app.component('text-input-combo', TextInputCombo);
      app.component('submit-button', SubmitButton);
      app.component('phantom-button', PhantomButton);
      app.component('labeled-checkbox', LabeledCheckbox);
      app.component('button-close', ButtonClose);
      app.component('empire-logo', EmpireLogo);
      app.component('content-sidebar', ContentSidebar);
   }
};

I na stronie głównej gdzie się obecnie znajduję i walczę :

const settings = {

  data() {
     return {

     };
  },

  methods: {

    showCategories(){
      EventBus.$emit('showMoviesCategories');
    }

  }

};

const app = Vue.createApp(settings);
BasicElements.registerBasicComponents(app);
app.component('smile-in-glasses-icon', SmileInGlassesIcon);
app.component('rocket-launch-icon', RocketLaunchIcon);
app.component('star-full-icon', StarFullIcon);
app.component('video-playlist-icon', VideoPlaylistIcon);
app.component('magnifier-icon', MagnifierIcon);
app.component('add-file-icon', AddFileIcon);
app.mount("#app");

Dla pewności dodam sam kod komponentu - usunąłem css

<template>
  <button v-bind:title="translations['title']" type="button" class="button-close">
    <div class="button-close__cross"></div>
    <span v-text="translations['label']" class="button-close__label"></span>
  </button>
</template>

<script lang="ts">
import { Vue, Options } from "vue-property-decorator";
import Translations from "@jsmodules/translations/components/form_controls/button_close";

@Options({ name: "ButtonClose" })
export default class ButtonClose extends Vue {
  private translations = Translations;
}
</script>

Walczę z tym od kilku godzin i skończyły mi się pomysły. Teoretycznie niby wszytko jest O.K a i tak nie działa.

komentarz 6 sierpnia 2021 przez niezalogowany
pokaż dependencies i devDependencies w package.json
komentarz 6 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)
"devDependencies": {
        "@babel/core": "^7.12.16",
        "@babel/helper-compilation-targets": "^7.12.16",
        "@babel/plugin-syntax-jsx": "^7.12.13",
        "@babel/preset-env": "^7.12.16",
        "@babel/preset-react": "^7.12.13",
        "axios": "^0.19",
        "babel-loader": "^8.2.2",
        "bootstrap": "^4.6.0",
        "cross-env": "^5.2.1",
        "jquery": "^3.2",
        "laravel-mix": "^6.0.11",
        "lodash": "^4.17.20",
        "node-sass": "^4.14.1",
        "popper.js": "^1.12",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.32.7",
        "sass-loader": "^7.3.1",
        "ts-loader": "^8.0.17",
        "vue-svg-loader": "^0.16.0",
        "webpack": "^5.22.0",
        "webpack-cli": "^4.5.0"
    },
    "dependencies": {
        "@babel/plugin-proposal-decorators": "^7.14.5",
        "@vue/compat": "^3.1.0",
        "image-to-blob": "^0.2.0",
        "laravel-mix-compress-images": "^1.0.4",
        "laravel-mix-imgmin": "^0.1.1",
        "laravel-mix-svg-vue": "0.3.0",
        "plyr": "^3.6.4",
        "postcss": "^8.2.6",
        "typescript": "^4.1.5",
        "vue": "^3.1.0",
        "vue-class-component": "^8.0.0-rc.1",
        "vue-clickaway": "^2.2.2",
        "vue-loader": "^16.0.0",
        "vue-multiselect": "^2.1.6",
        "vue-property-decorator": "^10.0.0-rc.3",
        "vue-slider-component": "^3.2.11",
        "vue3-click-away": "^1.2.1"
    },
    "peerDependencies": {
        "@vue/compiler-sfc": "^3.1.5"
    }

 

3 odpowiedzi

0 głosów
odpowiedź 6 sierpnia 2021 przez niezalogowany
Nie wiem, wygląda dziwnie. Możesz spróbować to obejść, emitując event click w close-button po kliknięciu w natywny button. Niezbyt ładne, ale lepsze to niż siedzenie kilka godzin bez rozwiązania
komentarz 6 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)
Też o tym myślałem, gdyby to był tylko jeden komponent to jeszcze spoko, ale obawiam się, że może się to powtarzać w przypadku innych komponentów i powtarzane tego za każdym razem niespecjalnie mi się uśmiecha. Tak czy siak, dzięki za poświęcenie uwagi temu problemowi.
1
komentarz 6 sierpnia 2021 przez niezalogowany
Z tego co rozumiem, nie działa u Ciebie taki przypadek:
Tworzysz komponent X i Y
w komponencie Y dodajesz komponent <X @click="hander"/> i handler się nie odpala?

Brzmi dość nieprawdopodobnie, żeby tak było opisane w dokumentacji i nie działało na czystej instalacji vue3

1. Sprawdziłbym na czystej instacji vue3/compact czy to działa
2. Szukałbym różnic między czystą instacją a Twoim projektem
komentarz 6 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)
Układ komponentów jest taki jak opisałeś. Nie wiem czy określenie czysta instalacja jest tu do końca trafne, jest to migration build, a cały projekt oczywiście wcześniej stał na vue 2.
1
komentarz 6 sierpnia 2021 przez niezalogowany
czysta instacja - chodziło mi o nowy zainstalowany projekt vue2 z cli z tymi dwoma komponentami - i sprawdzenie, czy z migration build będą działać według dokumentacji vue3
komentarz 6 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)
Mogę dodać, że handler nawet nie jest podpinany - sprawdzałem w konsoli przeglądarki.
komentarz 6 sierpnia 2021 przez niezalogowany
no tak, jakby był, to by działało : )
0 głosów
odpowiedź 6 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)

Zrobiłem test, zrobiłem super-prostą stronę tylko z jednym komponentem - też nie działa. Wydaje mi się, że problem leży w narzędziu laravel.mix.js którego używam do konfigurowania webpack'a .  Okazuje się, że jest nowa wersja pod vue 3.

https://www.npmjs.com/package/laravel-mix-vue3

Zrobiłem jak kazali w instrukcji jednak teraz gdy uruchamiam npm run development to dostaję :

ReferenceError: File is not defined
    at /node_modules/laravel-mix-vue3/index.js:63:44
    at Array.map (<anonymous>)
    at Vue3.register (node_modules/laravel-mix-vue3/index.js:63:30)
    at Object.components.<computed> [as vue3] (/var/www/html/sex-imperium/node_modules/laravel-mix/src/components/ComponentRegistrar.js:133:53)
    at Object.<anonymous> (/webpack.mix.js:19:5)
    at Module._compile (/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1120:10)
    at Module.load (node:internal/modules/cjs/loader:971:32)
    at Function.Module._load (node:internal/modules/cjs/loader:812:14)
    at Module.require (node:internal/modules/cjs/loader:995:19)
 

Kod w pliku laravel.mix.js wygląda tak :

const mix = require('laravel-mix');
require("laravel-mix-vue3");
require('laravel-mix-svg-vue');
var path = require('path');
const webpack = require('webpack')

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */
//mix.vue3("resources/js/test.js', 'public/js");

mix.vue3('resources/js/test.js', 'public/js')
  .options({ processCssUrls: false })
  .babelConfig({
    plugins: ['@babel/plugin-syntax-dynamic-import', "@babel/plugin-transform-modules-commonjs"],
    presets: ["@babel/env"]
  })
  .webpackConfig({
    plugins: [
      new webpack.DefinePlugin({
        __VUE_OPTIONS_API__: true,
        __VUE_PROD_DEVTOOLS__: false,
      }),
    ],
    resolve: {
      alias: {
        '@js': path.resolve('resources/js'),
        '@jscomponents': path.resolve('resources/js/components'),
        '@jsmodules': path.resolve('resources/js/modules'),
        'sass': path.resolve('resources/sass'),
        'sasscomponent': path.resolve('resources/sass/components'),
        '@jscomponents-decoration': path.resolve("resources/js/components/decoration"),
        '@jscomponents-form-controls': path.resolve('resources/js/components/form_controls'),
        '@interfaces': path.resolve('resources/js/interfaces'),
        '@svgicon': path.resolve('resources/js/components/decoration/icons/svg'),
        '@config' : path.resolve('resources/js/config'),
        'vue' : '@vue/compat'
      },
      extensions: ["*", ".js", ".jsx", ".vue", ".ts", ".tsx", ".svg"]
    },

    module: {
      rules: [
        {
          test: /\.tsx?$/,
          loader: "ts-loader",
          options: { appendTsSuffixTo: [/\.vue$/] },
          exclude: /node_modules/
        },

        {
          test: /\.svg$/,
          use: [
            'babel-loader',
            'vue-svg-loader',
          ],
        },

        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: {
            compilerOptions: {
              compatConfig: {
                MODE: 2
              }
            }
          }
        }
      ]
    }
  })

 Znowu googlowałem ale nic nie znalazłem. Sam komunikat niby jasny i oczywisty, ale nie mam pojęcia jakiego pliku mu brakuje i dlaczego.

komentarz 7 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)
Teraz nie rzuca błędem - kompiluje się poprawnie, ale w przeglądarce on click nadal nie działa dla komponentów
komentarz 7 sierpnia 2021 przez ScriptyChris Mędrzec (190,190 p.)

Sprawdzałeś czystą instalację wg tego komentarza?

komentarz 7 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)

Dokładnie to zrobiłem tak :

Dodałem nową super prostą stronę 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
         <test-button v-on:click="showAlert"></test-button>
    </div>
    <script src="http://localhost/js/test.js"></script>
</body>
</html>

I dodałem taki skrypt

import Vue from 'vue';
import TestButton from '@jscomponents/test.vue';

const settings = {

    components : {
        TestButton
    },

    data() {
       return {
  
       };
    },
  
    methods: {
  
        showAlert(){
        alert("a ja działam, yeeeeahh!!"); 
      }
  
    }
  
  };
  
  const app = Vue.createApp(settings);
  app.config.compilerOptions.whitespace = 'preserve';
  app.mount("#app");
  

Nadal nie działa.

komentarz 7 sierpnia 2021 przez ScriptyChris Mędrzec (190,190 p.)
Czy możesz ten uproszczony projekt ze świeżą instalacją udostępnić na GitHub?
komentarz 7 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)

To co udostępniłem powyżej to podstrona w bieżącym projekcie. Mogę dodać kod komponentu i ewentualnie pliki package.json i ustawienia webpack'a.

Package.json

{
    "private": true,
    "scripts": {
        "development": "mix",
        "watch": "mix watch",
        "watch-poll": "mix watch -- --watch-options-poll=1000",
        "hot": "mix watch --hot",
        "production": "mix --production"
    },
    "devDependencies": {
        "@babel/core": "^7.12.16",
        "@babel/helper-compilation-targets": "^7.12.16",
        "@babel/plugin-syntax-jsx": "^7.12.13",
        "@babel/preset-env": "^7.12.16",
        "@babel/preset-react": "^7.12.13",
        "@types/webpack-env": "^1.16.2",
        "@vue/compiler-sfc": "^3.1.5",
        "axios": "^0.19",
        "babel-loader": "^8.2.2",
        "bootstrap": "^4.6.0",
        "cross-env": "^5.2.1",
        "jquery": "^3.2",
        "laravel-mix": "^6.0.27",
        "laravel-mix-vue3": "^0.7.0",
        "lodash": "^4.17.20",
        "node-sass": "^4.14.1",
        "popper.js": "^1.12",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.32.7",
        "sass-loader": "^7.3.1",
        "ts-loader": "^8.0.17",
        "vue-loader": "^16.5.0",
        "vue-svg-loader": "^0.16.0",
        "webpack": "^5.22.0",
        "webpack-cli": "^4.5.0"
    },
    "dependencies": {
        "@babel/plugin-proposal-decorators": "^7.14.5",
        "@vue/compat": "^3.1.0",
        "image-to-blob": "^0.2.0",
        "laravel-mix-imgmin": "^0.1.1",
        "laravel-mix-svg-vue": "0.3.0",
        "mitt": "^3.0.0",
        "plyr": "^3.6.4",
        "postcss": "^8.2.6",
        "tiny-emitter": "^2.1.0",
        "typescript": "^4.1.5",
        "vue": "^3.1.0",
        "vue-class-component": "^8.0.0-rc.1",
        "vue-clickaway": "^2.2.2",
        "vue-multiselect": "^2.1.6",
        "vue-property-decorator": "^10.0.0-rc.3",
        "vue-slider-component": "^3.2.11",
        "vue3-click-away": "^1.2.1"
    }
}

Komponent.

<template>
  <button>Test button</button>
</template>

<script>

export default {

  name : "test-button"
}
</script>

<style>

</style>

Webpack.mix.js

const mix = require('laravel-mix');
var path = require('path');
const webpack = require('webpack')

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */
//mix.vue3("resources/js/test.js', 'public/js");

mix.js('resources/js/test.js', 'public/js').vue()
  .options({ processCssUrls: false })
  .babelConfig({
    plugins: ['@babel/plugin-syntax-dynamic-import', "@babel/plugin-transform-modules-commonjs"],
    presets: ["@babel/env"]
  })
  .webpackConfig({
    plugins: [
      new webpack.DefinePlugin({
        __VUE_OPTIONS_API__: true,
        __VUE_PROD_DEVTOOLS__: true,
      }),
    ],
    resolve: {
      alias: {
        '@js': path.resolve('resources/js'),
        '@jscomponents': path.resolve('resources/js/components'),
        '@jsmodules': path.resolve('resources/js/modules'),
        'sass': path.resolve('resources/sass'),
        'sasscomponent': path.resolve('resources/sass/components'),
        '@jscomponents-decoration': path.resolve("resources/js/components/decoration"),
        '@jscomponents-form-controls': path.resolve('resources/js/components/form_controls'),
        '@interfaces': path.resolve('resources/js/interfaces'),
        '@svgicon': path.resolve('resources/js/components/decoration/icons/svg'),
        '@config' : path.resolve('resources/js/config'),
        'vue' : '@vue/compat'
      },
      extensions: ["*", ".js", ".jsx", ".vue", ".ts", ".tsx", ".svg"]
    },

    module: {
      rules: [
        {
          test: /\.tsx?$/,
          loader: "ts-loader",
          options: { appendTsSuffixTo: [/\.vue$/] },
          exclude: /node_modules/
        },

        {
          test: /\.svg$/,
          use: [
            'babel-loader',
            'vue-svg-loader',
          ],
        },

        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: {
            compilerOptions: {
              compatConfig: {
                MODE: 2
              }
            }
          }
        }
      ]
    }
  })

 

0 głosów
odpowiedź 17 sierpnia 2021 przez Artek Stary wyjadacz (11,800 p.)
Okazało się, że migration build głównie tylko emituje ostrzeżenia, że coś nie pasuje do wersji 3 - ale wychodzi na to, że większość funkcjonalności działa zgodnie z tym jak w 2. Chociaż np. inicjowanie instancji działa zarówno jak w wersji 2 jak i 3 - ej.

Podobne pytania

0 głosów
0 odpowiedzi 396 wizyt
+1 głos
1 odpowiedź 284 wizyt
pytanie zadane 3 sierpnia 2021 w JavaScript przez mikey Użytkownik (820 p.)
0 głosów
1 odpowiedź 231 wizyt
pytanie zadane 19 września 2020 w JavaScript przez Artek Stary wyjadacz (11,800 p.)

92,655 zapytań

141,544 odpowiedzi

319,968 komentarzy

62,024 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...