• 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

Aruba Cloud - Virtual Private Server VPS
+4 głosów
603 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 542 wizyt
+1 głos
1 odpowiedź 502 wizyt
pytanie zadane 3 sierpnia 2021 w JavaScript przez mikey Użytkownik (820 p.)
0 głosów
1 odpowiedź 285 wizyt
pytanie zadane 19 września 2020 w JavaScript przez Artek Stary wyjadacz (11,800 p.)

93,327 zapytań

142,323 odpowiedzi

322,396 komentarzy

62,656 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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...