【问题标题】:Laravel 6.4.1 + webpack + vue + scss dynamically loadedLaravel 6.4.1 + webpack + vue + scss 动态加载
【发布时间】:2019-12-11 10:16:38
【问题描述】:

我有 laravel 6.4.1,对默认的 webpack 配置做了一些小改动。 我也在使用具有作用域样式的 vue 组件。

当我运行npm run dev 时,一切正常。我的 Vue 组件已加载并具有样式。 当我运行npm run production 时,我的 Vue 组件没有加载。 或者好吧... JS 文件已加载,但组件永远不会触发 createdmounted 并且在屏幕上不可见,在 DOM 中不可见。

那我怎么知道它已经加载了?

当我将console.log('test') 放在export default 上方(或下方)时,它会显示在控制台中。

当我完全删除 <style scoped lang="scss"> 标记时,我的组件也会在屏幕上可见。

我已经尝试过删除部分样式,但始终没有效果。即使是空的样式标签也不会呈现组件。只有当我完全移除它时它才会起作用。

当然,我想在组件中保留我的样式,那么我该如何解决这个问题呢?

我已经从 Vue 组件中删除了一些 JS 以使其更具可读性,并且由于我强烈怀疑该问题不在 JS 中,我认为它对这个问题没有任何价值。

webpack.mix.js

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | 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
    .js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

if (mix.inProduction()) {
    mix.version();
} else {
    mix.sourceMaps();
}

// webpack.mix.js
const path = require('path'),
    WebpackShellPlugin = require('webpack-shell-plugin'),
    BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin,
    {CleanWebpackPlugin} = require('clean-webpack-plugin');

mix.webpackConfig({
    plugins: [
        new WebpackShellPlugin({
            onBuildStart: [
                'php artisan js-localization:export --quiet',
                'php artisan ziggy:generate resources/js/ziggy-routes.js --quiet'
            ]
        }),
        new BundleAnalyzerPlugin({
            analyzerMode: mix.inProduction() ? 'disabled' : 'server',
            openAnalyzer: false
        }),
        new CleanWebpackPlugin({
            dry: false,
            cleanStaleWebpackAssets: true,
            cleanOnceBeforeBuildPatterns: [],
            cleanAfterEveryBuildPatterns: [
                'js/chunk/*'
            ],
            dangerouslyAllowCleanPatternsOutsideProject: true,
        }),
    ],
    resolve: {
        alias: {
            ziggy: path.resolve('vendor/tightenco/ziggy/dist/js/route.js'),
        },
    },
    output: {
        publicPath: '/',
        chunkFilename: 'js/chunk/[name].[chunkhash].js',
    },
});

Vue 组件

<template>
    <div class="position-relative my-2" :style="{backgroundColor: properties.settings.backgroundColor}">
        <block-template-content-text
            v-if="canDisplayBlock(block, 'content', 'text')"
            :text-config="tinyMce.text"
            :block="block"
            @block-change="storeBlockChange">
        </block-template-content-text>
        <block-template-content-text-image
            v-if="canDisplayBlock(block, 'content', 'text-image')"
            :text-config="tinyMce.text"
            :image-config="tinyMce.image"
            :block="block"
            @block-change="storeBlockChange">
        </block-template-content-text-image>

        <div class="d-flex align-items-center justify-content-center flex-column position-absolute controls">
            <i class="fas fa-2x fa-fw fa-chevron-up cursor-pointer" @click="$emit('sort-item', 'up', block)"></i>
            <div>
                <i class="fas fa-1x fa-fw fa-plus-circle cursor-pointer" @click="$emit('add-new-block', block)"></i>
                <!-- delete section start -->
                <i class="fas fa-1x fa-fw fa-trash cursor-pointer"
                   :id="'delete-' + block.hash"
                   @click="$emit('delete-block', $event, block)"></i>
                <b-tooltip :target="'delete-' + block.hash"
                           :id="'tooltip-' + block.hash"
                           triggers="focus">
                    <button type="button"
                            class="btn btn-primary"
                            @click="$emit('cancel-delete-block', block)">
                        {{ Lang.get('general.buttons.cancel') }}
                    </button>

                    <button type="button"
                            class="btn btn-danger"
                            @click="$emit('delete-block', $event, block)">
                        <i class="fas fa-fw fa-trash"></i>
                        {{ Lang.get('general.buttons.delete')}}
                    </button>
                </b-tooltip>
                <!-- delete section end -->

                <!-- popover start -->
                <div class="popover-content" :hidden="!showPopover">
                    <i class="fas fa-fw fa-times close-popover cursor-pointer" @click="closePopover"></i>
                    <div class="form-group">
                        <label for="background-color">
                            {{ Lang.get('project.design.pages.block.settings.background-color') }}
                        </label>
                        <input type="color"
                               name="background-color"
                               id="background-color"
                               class="form-control"
                               v-model="properties.settings.backgroundColor"
                               value="#ffffff"
                               @input="setSetting('backgroundColor', $event)">
                    </div>
                </div>
                <i class="fas fa-1x fa-fw fa-cog cursor-pointer"
                   @click="togglePopover"></i>
                <!-- popover end -->
            </div>
            <i class="fas fa-2x fa-fw fa-chevron-down sort-order cursor-pointer"
               @click="$emit('sort-item', 'down', block)"></i>
        </div>
    </div>
</template>

<script>
    // Bootstrap Vue
    import {TooltipPlugin} from 'bootstrap-vue';
    Vue.use(TooltipPlugin);

    // TinyMCE editor
    import 'tinymce/tinymce.min';
    import 'tinymce/themes/silver/theme.min';
    import 'tinymce/plugins/paste';
    import 'tinymce/plugins/link';
    import 'tinymce/plugins/imagetools';
    import {EventBus} from "../../vue/EventBus";

    export default {
        name: "display-block",
        components: {
            'block-template-content-text': () => import('./blocks/content/Text'),
            'block-template-content-text-image': () => import('./blocks/content/TextImage'),
        },
        props: {
            block: {
                required: true,
                type: Object
            }
        },
        data() {
           [...]
        },
        methods: {
            [...]
        },
        mounted() {
            [...]
        }
    }
</script>

<style scoped lang="scss">
    @import "../../../sass/variables";
    @import "~bootstrap/scss/mixins";
    @import "~bootstrap/scss/bootstrap-grid";
    @import "~bootstrap/scss/utilities/position";
    @import "~bootstrap/scss/popover";

    // Bootstrap Vue
    @import '~bootstrap-vue/src/index.scss';

    .block {
        .block- {
            &text {
                @import '~tinymce/skins/ui/oxide/skin.min.css';
                @import '~tinymce/skins/ui/oxide/content.min.css';
                @import '~tinymce/skins/content/default/content.min.css';
            }
        }
    }

    .controls {
        @extend .position-relative;

        top: map_get($sizes, 50);
        right: - map_get($spacers, 5);
        transform: translateY(-50%);

        &:first-child {
            @extend .d-none;
        }

        .popover-content {
            @extend .popover;
            @extend .p-2;

            min-width: 150px;
            min-height: 150px;

            .close-popover {
                @extend .position-absolute;
                @extend .mt-2;
                @extend .mr-2;

                top: 0;
                right: 0;
            }

            input {
                &[type=color] {
                    @extend .p-0;

                    width: 25px;
                    height: 25px;
                    border: none;
                }
            }
        }
    }
</style>

page.js

import {EventBus} from "../../vue/EventBus";
import {TooltipPlugin} from 'bootstrap-vue';
// import DisplayBlock from "../../components/project/DisplayBlock";

if (document.getElementById('page-editor')) {
    // Bootstrap Vue
    Vue.use(TooltipPlugin);

    new Vue({
        el: '#page-editor',
        components: {
            BlockModal: () => import('../../components/project/BlockModal'),
            DisplayBlock: () => import('../../components/project/DisplayBlock'),
            // DisplayBlock
        },
        data: {
            [...]
        },
        computed: {
            [...]
        },
        watch: {
            [...]
        },
        methods: {
            [...]
        },
        mounted() {
            [...]
        }
    });
}

【问题讨论】:

    标签: vue.js webpack laravel-6


    【解决方案1】:

    在您的 webpack 文件中,VUE 缺少解析器。

      resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' 
        }
      }
    

    尝试添加上面的sn-p。

    【讨论】:

    • 我试过了,但我收到了这条消息 TypeError: Vue.mixin is not a function 我还尝试将 esm 更改为 common (您在评论中放置的文件)但这不会给出任何错误并且不起作用也是。 vue.esm.js 的路径应该在我的 node_modules 目录中吗?
    • 没有。它应该是这样的。但是你在哪里使用 mixin。
    • where are you using the mixin 是什么意思?我将别名放在webpack.mix.js 文件中。
    • 你是否添加了 vue 加载器来编译 .vue 模板。并且在你的 webpack 中没有指定 vue 加载器。
    • 我认为这是随 webpack 默认的 laravel mix 配置一起提供的。因为npm run dev 一切正常?
    猜你喜欢
    • 2018-02-24
    • 2018-09-21
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 2017-05-25
    • 2017-01-16
    • 2016-01-23
    相关资源
    最近更新 更多