vuejs / vue-class-component

ES / TypeScript decorator for class-style Vue components.
MIT License
5.81k stars 429 forks source link

Getter decorator inside mixing removes Vue.$style property, why and how to fix that? #566

Open BonBonSlick opened 3 years ago

BonBonSlick commented 3 years ago

component

'use strict';
import * as Template from './_template.html?style=./_styles.scss'; // STYLE LOADING FINE WITHOUT .Getter DECORATOR

import {Component, Vue}                                         from 'vue-property-decorator';
import {namespace}             from 'vuex-class';
import {mixins}                from 'vue-class-component';

export default class Menu extends mixins(Vue, LoadingModalScreenMixin)
    implements
               Vue {
    $style: any ;

mixin


'use strict';
import {Component, Vue}          from 'vue-property-decorator';
import {namespace}                   from 'vuex-class';

const moduleLockScreen = namespace(commonModalLockScreen);

@Component
export default class LoadingModalScreenMixin extends Vue  {
    @moduleLockScreen.Getter // <---- ADDING THIS BREAKS ALL SCOPED STYLES
    isShown!: boolean;

    @moduleLockScreen.Action
    show!: () => void;
}

package.json


  "vue-class-component": "^7.2.3",
    "vue-css-modules": "https://github.com/BonBonSlick/vue-css-modules.git",
    "vue-property-decorator": "^9.1.2",
    "vue-style-loader": "^4.1.0",
    "vue-template-loader": "^1.1.0",
    "vuex": "^3.0.1",
    "vuex-class": "^0.3.2",

vue.d.ts

import {Route} from 'vue-router';
import Vue from 'vue/types/vue';

declare module 'vue/types/vue' {
    interface Vue {
        $route: Route,
        $style: Object,
    }
}

So scoped styles with $style work fine untill adding .Getter decorator to mixin and using this package, it breaks something during build here, overriding or replacing node_modules/vue-class-component/lib/util.d.ts

webpack

'use strict';

const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const HtmlWebpackPlugin          = require('html-webpack-plugin');
const FriendlyErrorsPlugin       = require('friendly-errors-webpack-plugin');
const webpack                    = require('webpack');
const path                       = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin    = require('copy-webpack-plugin');

module.exports         = {
    mode:         'development',
    entry:        [
        './src/main.ts',
    ],
    watch:        true,
    watchOptions: {
        poll: true,
    },
    output:       {
        path:       path.resolve(__dirname, '../dist'),
        filename:   '[name].js',
        publicPath: '/',
    },
    module:       {
        rules: [
            {
                test:    /\.tsx?$/,
                loader:  'ts-loader',
                exclude: /node_modules/,
            },
            {
                test:    /\.html$/,
                loader:  'vue-template-loader',
                include: /src/,
                options: {
                    transformToRequire: {
                        img: 'src',
                    },
                },
            },
            {
                test: /\.css$/,
                use:  [
                    MiniCssExtractPlugin.loader,
                    {
                        loader:  'css-loader',
                        options: {
                            importLoaders:  1,
                            modules:        true,
                            localIdentName: '[local]__[hash:base64:4]',
                            sourceMap:      true,
                        },
                    },
                ],
            },
            {
                test: /\.scss$/,
                use:  [
                    // Adds CSS to the DOM by injecting a `<style>` tag
                    MiniCssExtractPlugin.loader, //'style-loader',
                    {
                        // Interprets `@import` and `url()` as JS `import()/require()` and will resolve them
                        loader:  'css-loader',
                        options: {
                            importLoaders:  1,
                            modules:        true,
                            localIdentName: '[local]__[hash:base64:4]',
                            sourceMap:      true,
                        },
                    },
                    'sass-loader',
                ],
            },
            {
                test:    /\.(png|jpg)$/,
                loader:  'file-loader',
                options: {
                    name: '[name].[ext]?[hash]',
                },
            },
            {
                test: /\.(otf|eot|woff|woff2|ttf|svg)$/,
                use:  [
                    {
                        loader:  'file-loader', // 'url-loader',
                        options: {
                            // limit:      100000,
                            name:       '[name].[ext]',
                            outputPath: 'fonts/',
                        },
                    },
                ],
            },
        ],
    },
    plugins:      [
        new FriendlyErrorsPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new ScriptExtHtmlWebpackPlugin({
                                           defaultAttribute: 'defer',
                                           preload:          {
                                               test:   /\.js$/,
                                               chunks: 'async',
                                           },
                                       }),
        new MiniCssExtractPlugin({
                                     filename:      '[name].css',
                                     chunkFilename: '[id].css',
                                     ignoreOrder:   false,
                                 }),
        new CopyWebpackPlugin([
                                  {
                                      from: path.join(
                                          __dirname,
                                          '../node_modules/@fortawesome/fontawesome-free/webfonts',
                                      ),
                                      to:   path.join(__dirname, '../dist/static/webfonts/'),
                                  },
                                  {
                                      from: path.join(__dirname, '../static'),
                                      to:   path.join(__dirname, '../dist/static'),
                                  },
                                  {
                                      from: path.join(__dirname, '../public'),
                                      to:   path.join(__dirname, '../dist/'),
                                  },
                              ]),
        new HtmlWebpackPlugin({
                                  title:    'Lilim.tv',
                                  filename: './index.html',
                                  template: './index_dev.html',
                                  inject:   true,
                              }),
    ],
    // externals:    [nodeExternals()],
    devtool:      'eval-source-map',
    // @todo - this is fix https://github.com/vuejs/vue/issues/2873
    resolve:      {
        extensions: ['.ts', '.js', '.json', 'scss'],
        alias:      {
            // vue$: 'vue/dist/vue.js',
            '@': path.resolve(__dirname, '../src'),
        },
    },
    performance:  {
        hints: 'warning',
    },
    optimization: {
        splitChunks: {
            chunks: 'all',
        },
    },
};
BonBonSlick commented 3 years ago
[Vue warn]: Error in mounted hook: "TypeError: Cannot read properties of undefined (reading 'test')"

found in

---> <Menu>
       <LayoutDefault>
         <Root>
        console.info(this);
        console.info(this.$style); // < --- WORKS WITHOUT MIXIN WITH .Getter DECORATOR
        console.info(this.$style['test']);// < --- WORKS WITHOUT MIXIN WITH .Getter DECORATOR
    }